lkml.org 
[lkml]   [2008]   [Mar]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[patch 05/13] x86: PAT use reserve free memtype in ioremap and iounmap
Use reserve_memtype and free_memtype interfaces in ioremap/iounmap to avoid
aliasing.

If there is an existing alias for the region, inherit the memory type from
the alias. If there are conflicting aliases for the entire region, then fail
ioremap.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>

Index: linux-2.6-x86.git/arch/x86/mm/ioremap.c
===================================================================
--- linux-2.6-x86.git.orig/arch/x86/mm/ioremap.c 2008-03-18 03:14:09.000000000 -0700
+++ linux-2.6-x86.git/arch/x86/mm/ioremap.c 2008-03-18 09:20:36.000000000 -0700
@@ -20,6 +20,7 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/pgalloc.h>
+#include <asm/pat.h>

#ifdef CONFIG_X86_64

@@ -119,6 +120,7 @@
{
unsigned long pfn, offset, last_addr, vaddr;
struct vm_struct *area;
+ unsigned long new_prot_val;
pgprot_t prot;
void __iomem *ret_addr;

@@ -153,6 +155,28 @@
WARN_ON_ONCE(is_ram);
}

+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr+1) - phys_addr;
+
+ if (reserve_memtype(phys_addr, phys_addr + size,
+ prot_val, &new_prot_val)) {
+ /*
+ * Do not fallback to certain memory types with certain
+ * requested type:
+ * - request is uncached, return cannot be write-back
+ */
+ if ((prot_val == _PAGE_CACHE_UC &&
+ new_prot_val == _PAGE_CACHE_WB)) {
+ free_memtype(phys_addr, phys_addr + size);
+ return NULL;
+ }
+ prot_val = new_prot_val;
+ }
+
switch (prot_val) {
case _PAGE_CACHE_UC:
default:
@@ -164,13 +188,6 @@
}

/*
- * Mappings have to be page-aligned
- */
- offset = phys_addr & ~PAGE_MASK;
- phys_addr &= PAGE_MASK;
- size = PAGE_ALIGN(last_addr+1) - phys_addr;
-
- /*
* Ok, go for it..
*/
area = get_vm_area(size, VM_IOREMAP);
@@ -179,11 +196,13 @@
area->phys_addr = phys_addr;
vaddr = (unsigned long) area->addr;
if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
+ free_memtype(phys_addr, phys_addr + size);
free_vm_area(area);
return NULL;
}

if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
+ free_memtype(phys_addr, phys_addr + size);
vunmap(area->addr);
return NULL;
}
@@ -272,6 +291,8 @@
return;
}

+ free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
+
/* Finally remove it */
o = remove_vm_area((void *)addr);
BUG_ON(p != o || o == NULL);
--


\
 
 \ /
  Last update: 2008-03-19 21:51    [W:0.167 / U:0.284 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site