Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6d40fc514c9ea886dc18ddd20043a411816b63d1
Commit:     6d40fc514c9ea886dc18ddd20043a411816b63d1
Parent:     2cb22e23a5fcbcac2de49493aa57c7694028a06a
Author:     Bjorn Helgaas <[EMAIL PROTECTED]>
AuthorDate: Fri Mar 30 10:35:43 2007 -0600
Committer:  Tony Luck <[EMAIL PROTECTED]>
CommitDate: Fri Mar 30 09:38:25 2007 -0700

    [IA64] fail mmaps that span areas with incompatible attributes
    
    Example memory map (from HP sx1000 with VGA enabled):
        0x00000 - 0x9FFFF supports only WB (cacheable) access
        0xA0000 - 0xBFFFF supports only UC (uncacheable) access
        0xC0000 - 0xFFFFF supports only WB (cacheable) access
    
    Some versions of X map the entire 0x00000-0xFFFFF area at once.  With the
    example above, this mmap must fail because there's no memory attribute 
that's
    safe for the entire area.
    
    Prior to this patch, we performed the mmap with a UC mapping.  When X
    accessed the WB memory at 0xC0000, it caused an MCA.  The crash can happen
    when mapping 0xC0000 from either /dev/mem or a /sys/.../legacy_mem file.
    
    Signed-off-by: Bjorn Helgaas <[EMAIL PROTECTED]>
    Signed-off-by: Tony Luck <[EMAIL PROTECTED]>
---
 arch/ia64/kernel/efi.c |   46 +++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index f45f91d..78d29b7 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -660,6 +660,29 @@ efi_memory_descriptor (unsigned long phys_addr)
        return NULL;
 }
 
+static int
+efi_memmap_intersects (unsigned long phys_addr, unsigned long size)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+       unsigned long end;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       end = phys_addr + size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+
+               if (md->phys_addr < end && efi_md_end(md) > phys_addr)
+                       return 1;
+       }
+       return 0;
+}
+
 u32
 efi_mem_type (unsigned long phys_addr)
 {
@@ -766,11 +789,28 @@ valid_phys_addr_range (unsigned long phys_addr, unsigned 
long size)
 int
 valid_mmap_phys_addr_range (unsigned long pfn, unsigned long size)
 {
+       unsigned long phys_addr = pfn << PAGE_SHIFT;
+       u64 attr;
+
+       attr = efi_mem_attribute(phys_addr, size);
+
        /*
-        * MMIO regions are often missing from the EFI memory map.
-        * We must allow mmap of them for programs like X, so we
-        * currently can't do any useful validation.
+        * /dev/mem mmap uses normal user pages, so we don't need the entire
+        * granule, but the entire region we're mapping must support the same
+        * attribute.
         */
+       if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC)
+               return 1;
+
+       /*
+        * Intel firmware doesn't tell us about all the MMIO regions, so
+        * in general we have to allow mmap requests.  But if EFI *does*
+        * tell us about anything inside this region, we should deny it.
+        * The user can always map a smaller region to avoid the overlap.
+        */
+       if (efi_memmap_intersects(phys_addr, size))
+               return 0;
+
        return 1;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to