diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2006-05-05 19:19:50 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2006-05-08 19:32:05 -0400 |
commit | 32e62c636a728cb39c0b3bd191286f2ca65d4028 (patch) | |
tree | 656454a01e720819103c172daae15b5f2fd85d68 /include | |
parent | 6810b548b25114607e0814612d84125abccc0a4f (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 'include')
-rw-r--r-- | include/asm-ia64/io.h | 1 | ||||
-rw-r--r-- | include/asm-ia64/pgtable.h | 22 | ||||
-rw-r--r-- | include/linux/efi.h | 1 |
3 files changed, 12 insertions, 12 deletions
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h index c2e3742108bb..781ee2c7e8c3 100644 --- a/include/asm-ia64/io.h +++ b/include/asm-ia64/io.h | |||
@@ -88,6 +88,7 @@ phys_to_virt (unsigned long address) | |||
88 | } | 88 | } |
89 | 89 | ||
90 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE | 90 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE |
91 | extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size); | ||
91 | extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */ | 92 | extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */ |
92 | extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count); | 93 | extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count); |
93 | 94 | ||
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index c0f8144f2349..90f3a2329232 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h | |||
@@ -317,22 +317,20 @@ ia64_phys_addr_valid (unsigned long addr) | |||
317 | #define pte_mkhuge(pte) (__pte(pte_val(pte))) | 317 | #define pte_mkhuge(pte) (__pte(pte_val(pte))) |
318 | 318 | ||
319 | /* | 319 | /* |
320 | * Macro to a page protection value as "uncacheable". Note that "protection" is really a | 320 | * Make page protection values cacheable, uncacheable, or write- |
321 | * misnomer here as the protection value contains the memory attribute bits, dirty bits, | 321 | * combining. Note that "protection" is really a misnomer here as the |
322 | * and various other bits as well. | 322 | * protection value contains the memory attribute bits, dirty bits, and |
323 | * various other bits as well. | ||
323 | */ | 324 | */ |
325 | #define pgprot_cacheable(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WB) | ||
324 | #define pgprot_noncached(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC) | 326 | #define pgprot_noncached(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC) |
325 | |||
326 | /* | ||
327 | * Macro to make mark a page protection value as "write-combining". | ||
328 | * Note that "protection" is really a misnomer here as the protection | ||
329 | * value contains the memory attribute bits, dirty bits, and various | ||
330 | * other bits as well. Accesses through a write-combining translation | ||
331 | * works bypasses the caches, but does allow for consecutive writes to | ||
332 | * be combined into single (but larger) write transactions. | ||
333 | */ | ||
334 | #define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC) | 327 | #define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC) |
335 | 328 | ||
329 | struct file; | ||
330 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
331 | unsigned long size, pgprot_t vma_prot); | ||
332 | #define __HAVE_PHYS_MEM_ACCESS_PROT | ||
333 | |||
336 | static inline unsigned long | 334 | static inline unsigned long |
337 | pgd_index (unsigned long address) | 335 | pgd_index (unsigned long address) |
338 | { | 336 | { |
diff --git a/include/linux/efi.h b/include/linux/efi.h index e203613d3aec..66d621dbcb6c 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -294,6 +294,7 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos | |||
294 | extern u64 efi_get_iobase (void); | 294 | extern u64 efi_get_iobase (void); |
295 | extern u32 efi_mem_type (unsigned long phys_addr); | 295 | extern u32 efi_mem_type (unsigned long phys_addr); |
296 | extern u64 efi_mem_attributes (unsigned long phys_addr); | 296 | extern u64 efi_mem_attributes (unsigned long phys_addr); |
297 | extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); | ||
297 | extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, | 298 | extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, |
298 | u64 attr); | 299 | u64 attr); |
299 | extern int __init efi_uart_console_only (void); | 300 | extern int __init efi_uart_console_only (void); |