From: "Andi Kleen" 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: Andi Kleen Signed-off-by: Andrew Morton --- 25-akpm/arch/i386/mm/ioremap.c | 6 +++--- 25-akpm/arch/x86_64/mm/ioremap.c | 10 +++++----- 25-akpm/include/linux/vmalloc.h | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff -puN arch/i386/mm/ioremap.c~x86_64-fix-ioremap-attribute-restoration-on-i386-and arch/i386/mm/ioremap.c --- 25/arch/i386/mm/ioremap.c~x86_64-fix-ioremap-attribute-restoration-on-i386-and 2005-01-09 23:01:27.226244088 -0800 +++ 25-akpm/arch/i386/mm/ioremap.c 2005-01-09 23:01:27.233243024 -0800 @@ -157,7 +157,7 @@ void __iomem * __ioremap(unsigned long p /* * Ok, go for it.. */ - area = get_vm_area(size, VM_IOREMAP); + area = get_vm_area(size, VM_IOREMAP | (flags << 20)); if (!area) return NULL; area->phys_addr = phys_addr; @@ -235,9 +235,9 @@ void iounmap(volatile void __iomem *addr if (!p) { printk("__iounmap: bad address %p\n", addr); 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)), p->size >> PAGE_SHIFT, PAGE_KERNEL); diff -puN arch/x86_64/mm/ioremap.c~x86_64-fix-ioremap-attribute-restoration-on-i386-and arch/x86_64/mm/ioremap.c --- 25/arch/x86_64/mm/ioremap.c~x86_64-fix-ioremap-attribute-restoration-on-i386-and 2005-01-09 23:01:27.227243936 -0800 +++ 25-akpm/arch/x86_64/mm/ioremap.c 2005-01-09 23:01:27.234242872 -0800 @@ -175,11 +175,11 @@ void __iomem * __ioremap(unsigned long p if (phys_addr >= 0xA0000 && last_addr < 0x100000) return (__force void __iomem *)phys_to_virt(phys_addr); +#ifndef CONFIG_DISCONTIGMEM /* * Don't allow anybody to remap normal RAM that we're using.. */ - if (phys_addr < virt_to_phys(high_memory)) { -#ifndef CONFIG_DISCONTIGMEM + if (last_addr < virt_to_phys(high_memory)) { char *t_addr, *t_end; struct page *page; @@ -189,8 +189,8 @@ void __iomem * __ioremap(unsigned long p for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) if(!PageReserved(page)) return NULL; -#endif } +#endif /* * Mappings have to be page-aligned @@ -202,7 +202,7 @@ void __iomem * __ioremap(unsigned long p /* * Ok, go for it.. */ - area = get_vm_area(size, VM_IOREMAP | (flags << 24)); + area = get_vm_area(size, VM_IOREMAP | (flags << 20)); if (!area) return NULL; area->phys_addr = phys_addr; @@ -263,7 +263,7 @@ void iounmap(volatile void __iomem *addr } *pprev = p->next; unmap_vm_area(p); - if ((p->flags >> 24) && + if ((p->flags >> 20) && p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff -puN include/linux/vmalloc.h~x86_64-fix-ioremap-attribute-restoration-on-i386-and include/linux/vmalloc.h --- 25/include/linux/vmalloc.h~x86_64-fix-ioremap-attribute-restoration-on-i386-and 2005-01-09 23:01:27.229243632 -0800 +++ 25-akpm/include/linux/vmalloc.h 2005-01-09 23:01:27.234242872 -0800 @@ -8,6 +8,7 @@ #define VM_IOREMAP 0x00000001 /* ioremap() and friends */ #define VM_ALLOC 0x00000002 /* vmalloc() */ #define VM_MAP 0x00000004 /* vmap()ed pages */ +/* bits [20..32] reserved for arch specific ioremap internals */ struct vm_struct { void *addr; _