aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/mm/ioremap.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2006-05-05 19:19:50 -0400
committerTony Luck <tony.luck@intel.com>2006-05-08 19:32:05 -0400
commit32e62c636a728cb39c0b3bd191286f2ca65d4028 (patch)
tree656454a01e720819103c172daae15b5f2fd85d68 /arch/ia64/mm/ioremap.c
parent6810b548b25114607e0814612d84125abccc0a4f (diff)
[IA64] rework memory attribute aliasing
This closes a couple holes in our attribute aliasing avoidance scheme: - The current kernel fails mmaps of some /dev/mem MMIO regions because they don't appear in the EFI memory map. This keeps X from working on the Intel Tiger box. - The current kernel allows UC mmap of the 0-1MB region of /sys/.../legacy_mem even when the chipset doesn't support UC access. This causes an MCA when starting X on HP rx7620 and rx8620 boxes in the default configuration. There's more detail in the Documentation/ia64/aliasing.txt file this adds, but the general idea is that if a region might be covered by a granule-sized kernel identity mapping, any access via /dev/mem or mmap must use the same attribute as the identity mapping. Otherwise, we fall back to using an attribute that is supported according to the EFI memory map, or to using UC if the EFI memory map doesn't mention the region. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/mm/ioremap.c')
-rw-r--r--arch/ia64/mm/ioremap.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 643ccc6960ce..07bd02b6c372 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -11,6 +11,7 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/efi.h> 12#include <linux/efi.h>
13#include <asm/io.h> 13#include <asm/io.h>
14#include <asm/meminit.h>
14 15
15static inline void __iomem * 16static inline void __iomem *
16__ioremap (unsigned long offset, unsigned long size) 17__ioremap (unsigned long offset, unsigned long size)
@@ -21,16 +22,29 @@ __ioremap (unsigned long offset, unsigned long size)
21void __iomem * 22void __iomem *
22ioremap (unsigned long offset, unsigned long size) 23ioremap (unsigned long offset, unsigned long size)
23{ 24{
24 if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB)) 25 u64 attr;
25 return phys_to_virt(offset); 26 unsigned long gran_base, gran_size;
26 27
27 if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC)) 28 /*
29 * For things in kern_memmap, we must use the same attribute
30 * as the rest of the kernel. For more details, see
31 * Documentation/ia64/aliasing.txt.
32 */
33 attr = kern_mem_attribute(offset, size);
34 if (attr & EFI_MEMORY_WB)
35 return phys_to_virt(offset);
36 else if (attr & EFI_MEMORY_UC)
28 return __ioremap(offset, size); 37 return __ioremap(offset, size);
29 38
30 /* 39 /*
31 * Someday this should check ACPI resources so we 40 * Some chipsets don't support UC access to memory. If
32 * can do the right thing for hot-plugged regions. 41 * WB is supported for the whole granule, we prefer that.
33 */ 42 */
43 gran_base = GRANULEROUNDDOWN(offset);
44 gran_size = GRANULEROUNDUP(offset + size) - gran_base;
45 if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
46 return phys_to_virt(offset);
47
34 return __ioremap(offset, size); 48 return __ioremap(offset, size);
35} 49}
36EXPORT_SYMBOL(ioremap); 50EXPORT_SYMBOL(ioremap);
@@ -38,6 +52,9 @@ EXPORT_SYMBOL(ioremap);
38void __iomem * 52void __iomem *
39ioremap_nocache (unsigned long offset, unsigned long size) 53ioremap_nocache (unsigned long offset, unsigned long size)
40{ 54{
55 if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB)
56 return 0;
57
41 return __ioremap(offset, size); 58 return __ioremap(offset, size);
42} 59}
43EXPORT_SYMBOL(ioremap_nocache); 60EXPORT_SYMBOL(ioremap_nocache);