Commit 54465502 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86_64: Fix ioremap attribute restoration on i386 and x86-64

We need to save the access flags to properly restore the direct mapping on
unmap.  For that we use some upper bits in vm_flags

Also add a comment for that to the header file.
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 82a71519
...@@ -157,7 +157,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l ...@@ -157,7 +157,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/* /*
* Ok, go for it.. * Ok, go for it..
*/ */
area = get_vm_area(size, VM_IOREMAP); area = get_vm_area(size, VM_IOREMAP | (flags << 20));
if (!area) if (!area)
return NULL; return NULL;
area->phys_addr = phys_addr; area->phys_addr = phys_addr;
...@@ -235,9 +235,9 @@ void iounmap(volatile void __iomem *addr) ...@@ -235,9 +235,9 @@ void iounmap(volatile void __iomem *addr)
if (!p) { if (!p) {
printk("__iounmap: bad address %p\n", addr); printk("__iounmap: bad address %p\n", addr);
return; return;
} }
if (p->flags && p->phys_addr < virt_to_phys(high_memory) - 1) { if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
change_page_attr(virt_to_page(__va(p->phys_addr)), change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT, p->size >> PAGE_SHIFT,
PAGE_KERNEL); PAGE_KERNEL);
......
...@@ -175,11 +175,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l ...@@ -175,11 +175,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
if (phys_addr >= 0xA0000 && last_addr < 0x100000) if (phys_addr >= 0xA0000 && last_addr < 0x100000)
return (__force void __iomem *)phys_to_virt(phys_addr); return (__force void __iomem *)phys_to_virt(phys_addr);
#ifndef CONFIG_DISCONTIGMEM
/* /*
* Don't allow anybody to remap normal RAM that we're using.. * Don't allow anybody to remap normal RAM that we're using..
*/ */
if (phys_addr < virt_to_phys(high_memory)) { if (last_addr < virt_to_phys(high_memory)) {
#ifndef CONFIG_DISCONTIGMEM
char *t_addr, *t_end; char *t_addr, *t_end;
struct page *page; struct page *page;
...@@ -189,8 +189,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l ...@@ -189,8 +189,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
if(!PageReserved(page)) if(!PageReserved(page))
return NULL; return NULL;
#endif
} }
#endif
/* /*
* Mappings have to be page-aligned * Mappings have to be page-aligned
...@@ -202,7 +202,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l ...@@ -202,7 +202,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/* /*
* Ok, go for it.. * Ok, go for it..
*/ */
area = get_vm_area(size, VM_IOREMAP | (flags << 24)); area = get_vm_area(size, VM_IOREMAP | (flags << 20));
if (!area) if (!area)
return NULL; return NULL;
area->phys_addr = phys_addr; area->phys_addr = phys_addr;
...@@ -263,7 +263,7 @@ void iounmap(volatile void __iomem *addr) ...@@ -263,7 +263,7 @@ void iounmap(volatile void __iomem *addr)
} }
*pprev = p->next; *pprev = p->next;
unmap_vm_area(p); unmap_vm_area(p);
if ((p->flags >> 24) && if ((p->flags >> 20) &&
p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) { p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
change_page_attr(virt_to_page(__va(p->phys_addr)), change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT, p->size >> PAGE_SHIFT,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define VM_IOREMAP 0x00000001 /* ioremap() and friends */ #define VM_IOREMAP 0x00000001 /* ioremap() and friends */
#define VM_ALLOC 0x00000002 /* vmalloc() */ #define VM_ALLOC 0x00000002 /* vmalloc() */
#define VM_MAP 0x00000004 /* vmap()ed pages */ #define VM_MAP 0x00000004 /* vmap()ed pages */
/* bits [20..32] reserved for arch specific ioremap internals */
struct vm_struct { struct vm_struct {
void *addr; void *addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment