[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86: force DMI table to not be in E820 RAM region



In order for Dom0 to be able to map the DMI table, it must not be in
E820 RAM; since some BIOS versions apparently fail to set the type
correctly for the page(s) containing this table, adjust it before
starting to consume memory.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-08-08/xen/arch/x86/dmi_scan.c
===================================================================
--- 2007-08-08.orig/xen/arch/x86/dmi_scan.c     2007-08-06 15:08:40.000000000 
+0200
+++ 2007-08-08/xen/arch/x86/dmi_scan.c  2007-08-21 13:44:10.000000000 +0200
@@ -100,7 +100,7 @@ inline static int __init dmi_checksum(u8
        return (sum==0);
 }
 
-static int __init dmi_iterate(void (*decode)(struct dmi_header *))
+static int __init dmi_iterate(void (*decode)(struct dmi_header *), u32 *pbase)
 {
        u8 buf[15];
        char __iomem *p, *q;
@@ -121,6 +121,11 @@ static int __init dmi_iterate(void (*dec
                        u16 len=buf[7]<<8|buf[6];
                        u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
 
+                       if (pbase)
+                               *pbase = base;
+                       if (!decode)
+                               return len;
+
                        /*
                         * DMI version 0.0 means that the real version is taken 
from
                         * the SMBIOS version, which we don't know at this 
point.
@@ -433,13 +438,27 @@ static void __init dmi_decode(struct dmi
 
 void __init dmi_scan_machine(void)
 {
-       int err = dmi_iterate(dmi_decode);
+       int err = dmi_iterate(dmi_decode, NULL);
        if(err == 0)
                dmi_check_system(dmi_blacklist);
        else
                printk(KERN_INFO "DMI not present.\n");
 }
 
+int __init dmi_get_table(u32*pbase, u32*plen)
+{
+       int rc = dmi_iterate(NULL, pbase);
+
+       if (rc < 0) {
+               *pbase = *plen = 0;
+               return rc;
+       }
+
+       *plen = rc;
+
+       return 0;
+}
+
 
 /**
  *     dmi_check_system - check system DMI data
Index: 2007-08-08/xen/arch/x86/setup.c
===================================================================
--- 2007-08-08.orig/xen/arch/x86/setup.c        2007-08-09 12:58:04.000000000 
+0200
+++ 2007-08-08/xen/arch/x86/setup.c     2007-08-21 13:48:30.000000000 +0200
@@ -45,6 +45,7 @@
 #endif
 
 extern void dmi_scan_machine(void);
+extern int dmi_get_table(u32 *pbase, u32 *plen);
 extern void generic_apic_probe(void);
 extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
 
@@ -425,6 +426,7 @@ void __init __start_xen(unsigned long mb
     module_t *mod = (module_t *)__va(mbi->mods_addr);
     unsigned long nr_pages, modules_length;
     int i, e820_warn = 0, bytes = 0;
+    u32 dmi_table_start, dmi_table_len;
     struct ns16550_defaults ns16550 = {
         .data_bits = 8,
         .parity    = 'n',
@@ -554,7 +556,7 @@ void __init __start_xen(unsigned long mb
     else if ( mbi->flags & MBI_MEMMAP )
     {
         memmap_type = "Multiboot-e820";
-        while ( bytes < mbi->mmap_length )
+        while ( bytes < mbi->mmap_length && e820_raw_nr < E820MAX )
         {
             memory_map_t *map = __va(mbi->mmap_addr + bytes);
 
@@ -605,6 +607,9 @@ void __init __start_xen(unsigned long mb
         EARLY_FAIL("Bootloader provided no memory information.\n");
     }
 
+    dmi_get_table(&dmi_table_start, &dmi_table_len);
+    e820_warn = 0;
+
     /* Ensure that all E820 RAM regions are page-aligned and -sized. */
     for ( i = 0; i < e820_raw_nr; i++ )
     {
@@ -615,6 +620,41 @@ void __init __start_xen(unsigned long mb
         s = PFN_UP(e820_raw[i].addr);
         e = PFN_DOWN(e820_raw[i].addr + e820_raw[i].size);
         e820_raw[i].size = 0; /* discarded later */
+
+        /*
+         * Dom0 will want to map the DMI table, yet some BIOSes put it
+         * in RAM regions - forcibly cut off the portion that overlaps.
+         */
+        if ( s < e &&
+             dmi_table_len > 0 &&
+             (e << PAGE_SHIFT) > dmi_table_start &&
+             (s << PAGE_SHIFT) < (u64)dmi_table_start + dmi_table_len )
+        {
+            u64 dmi_table_end = (u64)dmi_table_start + dmi_table_len;
+
+            if ( (s << PAGE_SHIFT) >= dmi_table_start &&
+                 (e << PAGE_SHIFT) <= dmi_table_end )
+                e = s;
+            else if ( (s << PAGE_SHIFT) >= dmi_table_start )
+                s = PFN_UP(dmi_table_end);
+            else if ( (e << PAGE_SHIFT) <= dmi_table_end )
+                e = PFN_DOWN(dmi_table_start);
+            else if ( e820_raw_nr < E820MAX )
+            {
+                e820_raw[e820_raw_nr].addr = dmi_table_end;
+                e820_raw[e820_raw_nr].size = (e << PAGE_SHIFT) - dmi_table_end;
+                e820_raw[e820_raw_nr].type = E820_RAM;
+                ++e820_raw_nr;
+                e = PFN_DOWN(dmi_table_start);
+            }
+            else if ( dmi_table_start - (s << PAGE_SHIFT) >=
+                      (e << PAGE_SHIFT) - dmi_table_end )
+                e = PFN_DOWN(dmi_table_start);
+            else
+                s = PFN_UP(dmi_table_end);
+            e820_warn = 1;
+        }
+
         if ( s < e )
         {
             e820_raw[i].addr = s << PAGE_SHIFT;
@@ -622,6 +662,19 @@ void __init __start_xen(unsigned long mb
         }
     }
 
+    if ( e820_warn )
+    {
+        printk("WARNING: DMI table located in E820 RAM "
+               "(fixed by shrinking/splitting RAM region).\n");
+        if ( e820_raw_nr < E820MAX )
+        {
+            e820_raw[e820_raw_nr].addr = dmi_table_start;
+            e820_raw[e820_raw_nr].size = dmi_table_len;
+            e820_raw[e820_raw_nr].type = E820_RESERVED;
+            ++e820_raw_nr;
+        }
+    }
+
     /* Sanitise the raw E820 map to produce a final clean version. */
     max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);
 



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.