WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86: force DMI table to not be in E820 RA

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: force DMI table to not be in E820 RAM region
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 26 Sep 2007 15:50:10 -0700
Delivery-date: Wed, 26 Sep 2007 15:51:13 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1190812456 -3600
# Node ID 80277ff19c9ccfae3bade36ca2664aae339cb91c
# Parent  0b873d909ad30e554a3ffebf14176e7257a3e023
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>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/dmi_scan.c    |   31 +++++++++++++--------
 xen/arch/x86/e820.c        |   65 +++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/setup.c       |   64 ++++----------------------------------------
 xen/include/asm-x86/e820.h |    1 
 xen/include/xen/dmi.h      |    2 +
 5 files changed, 94 insertions(+), 69 deletions(-)

diff -r 0b873d909ad3 -r 80277ff19c9c xen/arch/x86/dmi_scan.c
--- a/xen/arch/x86/dmi_scan.c   Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/arch/x86/dmi_scan.c   Wed Sep 26 14:14:16 2007 +0100
@@ -100,23 +100,32 @@ inline static int __init dmi_checksum(u8
        return (sum==0);
 }
 
-static int __init dmi_iterate(void (*decode)(struct dmi_header *))
+int __init dmi_get_table(u32 *base, u32 *len)
 {
        u8 buf[15];
        char __iomem *p, *q;
 
-       /*
-        * no iounmap() for that ioremap(); it would be a no-op, but it's
-        * so early in setup that sucker gets confused into doing what
-        * it shouldn't if we actually call it.
-        */
-       p = ioremap(0xF0000, 0x10000);
-       if (p == NULL)
-               return -1;
+       p = maddr_to_virt(0xF0000);
        for (q = p; q < p + 0x10000; q += 16) {
                memcpy_fromio(buf, q, 15);
-               if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
-               {
+               if (memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) {
+                       *base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+                       *len=buf[7]<<8|buf[6];
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+static int __init dmi_iterate(void (*decode)(struct dmi_header *))
+{
+       u8 buf[15];
+       char __iomem *p, *q;
+
+       p = maddr_to_virt(0xF0000);
+       for (q = p; q < p + 0x10000; q += 16) {
+               memcpy_fromio(buf, q, 15);
+               if (memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) {
                        u16 num=buf[13]<<8|buf[12];
                        u16 len=buf[7]<<8|buf[6];
                        u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
diff -r 0b873d909ad3 -r 80277ff19c9c xen/arch/x86/e820.c
--- a/xen/arch/x86/e820.c       Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/arch/x86/e820.c       Wed Sep 26 14:14:16 2007 +0100
@@ -2,6 +2,7 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/compat.h>
+#include <xen/dmi.h>
 #include <asm/e820.h>
 #include <asm/page.h>
 
@@ -343,6 +344,15 @@ static void __init clip_to_limit(uint64_
     }
 }
 
+static void __init reserve_dmi_region(void)
+{
+    u32 base, len;
+    if ( (dmi_get_table(&base, &len) == 0) && ((base + len) > base) &&
+         reserve_e820_ram(&e820, base, base + len) )
+        printk("WARNING: DMI table located in E820 RAM %08x-%08x. Fixed.\n",
+               base, base+len);
+}
+
 static void __init machine_specific_memory_setup(
     struct e820entry *raw, int *raw_nr)
 {
@@ -366,6 +376,61 @@ static void __init machine_specific_memo
                   "Only the first %u GB of the physical memory map "
                   "can be accessed by 32-on-64 guests.");
 #endif
+
+    reserve_dmi_region();
+}
+
+/* Reserve RAM area (@s,@e) in the specified e820 map. */
+int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e)
+{
+    uint64_t rs = 0, re = 0;
+    int i;
+
+    for ( i = 0; i < e820->nr_map; i++ )
+    {
+        /* Have we found the e820 region that includes the specified range? */
+        rs = e820->map[i].addr;
+        re = rs + e820->map[i].size;
+        if ( (s >= rs) && (e <= re) )
+            break;
+    }
+
+    if ( (i == e820->nr_map) || (e820->map[i].type != E820_RAM) )
+        return 0;
+
+    if ( (s == rs) && (e == re) )
+    {
+        /* Complete excision. */
+        memmove(&e820->map[i], &e820->map[i+1],
+                (e820->nr_map-i-1) * sizeof(e820->map[0]));
+        e820->nr_map--;
+    }
+    else if ( s == rs )
+    {
+        /* Truncate start. */
+        e820->map[i].addr += e - s;
+        e820->map[i].size -= e - s;
+    }
+    else if ( e == re )
+    {
+        /* Truncate end. */
+        e820->map[i].size -= e - s;
+    }
+    else
+    {
+        /* Split in two. */
+        if ( e820->nr_map >= ARRAY_SIZE(e820->map) )
+            return 0;
+        memmove(&e820->map[i+1], &e820->map[i],
+                (e820->nr_map-i) * sizeof(e820->map[0]));
+        e820->nr_map++;
+        e820->map[i].size = s - rs;
+        i++;
+        e820->map[i].addr = e;
+        e820->map[i].size = re - e;
+    }
+
+    return 1;
 }
 
 unsigned long __init init_e820(
diff -r 0b873d909ad3 -r 80277ff19c9c xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/arch/x86/setup.c      Wed Sep 26 14:14:16 2007 +0100
@@ -19,6 +19,7 @@
 #include <xen/numa.h>
 #include <xen/rcupdate.h>
 #include <xen/vga.h>
+#include <xen/dmi.h>
 #include <public/version.h>
 #ifdef CONFIG_COMPAT
 #include <compat/platform.h>
@@ -45,7 +46,6 @@
 #define maddr_to_bootstrap_virt(m) ((void *)(long)(m))
 #endif
 
-extern void dmi_scan_machine(void);
 extern void generic_apic_probe(void);
 extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
 
@@ -280,41 +280,6 @@ static void __init move_memory(
 
 /* A temporary copy of the e820 map that we can mess with during bootstrap. */
 static struct e820map __initdata boot_e820;
-
-/* Reserve area (@s,@e) in the temporary bootstrap e820 map. */
-static int __init reserve_in_boot_e820(unsigned long s, unsigned long e)
-{
-    uint64_t rs, re;
-    int i;
-
-    for ( i = 0; i < boot_e820.nr_map; i++ )
-    {
-        /* Have we found the e820 region that includes the specified range? */
-        rs = boot_e820.map[i].addr;
-        re = rs + boot_e820.map[i].size;
-        if ( (s >= rs) && (e <= re) )
-            goto found;
-    }
-
-    return 0;
-
- found:
-    /* Start fragment. */
-    boot_e820.map[i].size = s - rs;
-
-    /* End fragment. */
-    if ( e < re )
-    {
-        memmove(&boot_e820.map[i+1], &boot_e820.map[i],
-                (boot_e820.nr_map-i) * sizeof(boot_e820.map[0]));
-        boot_e820.nr_map++;
-        i++;
-        boot_e820.map[i].addr = e;
-        boot_e820.map[i].size = re - e;
-    }
-
-    return 1;
-}
 
 struct boot_video_info {
     u8  orig_x;             /* 0x00 */
@@ -547,7 +512,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);
 
@@ -597,23 +562,6 @@ void __init __start_xen(unsigned long mb
         EARLY_FAIL("Bootloader provided no memory information.\n");
     }
 
-    /* Ensure that all E820 RAM regions are page-aligned and -sized. */
-    for ( i = 0; i < e820_raw_nr; i++ )
-    {
-        uint64_t s, e;
-
-        if ( e820_raw[i].type != E820_RAM )
-            continue;
-        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 */
-        if ( s < e )
-        {
-            e820_raw[i].addr = s << PAGE_SHIFT;
-            e820_raw[i].size = (e - s) << PAGE_SHIFT;
-        }
-    }
-
     /* Sanitise the raw E820 map to produce a final clean version. */
     max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);
 
@@ -760,7 +708,7 @@ void __init __start_xen(unsigned long mb
 
     if ( !initial_images_start )
         EARLY_FAIL("Not enough memory to relocate the dom0 kernel image.\n");
-    reserve_in_boot_e820(initial_images_start, initial_images_end);
+    reserve_e820_ram(&boot_e820, initial_images_start, initial_images_end);
 
     /*
      * With modules (and Xen itself, on x86/64) relocated out of the way, we
@@ -772,8 +720,8 @@ void __init __start_xen(unsigned long mb
     if ( !xen_phys_start )
         EARLY_FAIL("Not enough memory to relocate Xen.\n");
     xenheap_phys_end += xen_phys_start;
-    reserve_in_boot_e820(xen_phys_start,
-                         xen_phys_start + (opt_xenheap_megabytes<<20));
+    reserve_e820_ram(&boot_e820, xen_phys_start,
+                     xen_phys_start + (opt_xenheap_megabytes<<20));
     init_boot_pages(1<<20, 16<<20); /* Initial seed: 15MB */
 #else
     init_boot_pages(xenheap_phys_end, 16<<20); /* Initial seed: 4MB */
@@ -786,7 +734,7 @@ void __init __start_xen(unsigned long mb
 
         kdump_size = (kdump_size + PAGE_SIZE - 1) & PAGE_MASK;
 
-        if ( !reserve_in_boot_e820(kdump_start, kdump_size) )
+        if ( !reserve_e820_ram(&boot_e820, kdump_start, kdump_size) )
         {
             printk("Kdump: DISABLED (failed to reserve %luMB (%lukB) at 0x%lx)"
                    "\n", kdump_size >> 20, kdump_size >> 10, kdump_start);
diff -r 0b873d909ad3 -r 80277ff19c9c xen/include/asm-x86/e820.h
--- a/xen/include/asm-x86/e820.h        Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/include/asm-x86/e820.h        Wed Sep 26 14:14:16 2007 +0100
@@ -23,6 +23,7 @@ struct e820map {
     struct e820entry map[E820MAX];
 };
 
+extern int reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e);
 extern unsigned long init_e820(const char *, struct e820entry *, int *);
 extern struct e820map e820;
 
diff -r 0b873d909ad3 -r 80277ff19c9c xen/include/xen/dmi.h
--- a/xen/include/xen/dmi.h     Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/include/xen/dmi.h     Wed Sep 26 14:14:16 2007 +0100
@@ -34,5 +34,7 @@ struct dmi_system_id {
 
 extern int dmi_check_system(struct dmi_system_id *list);
 extern char * dmi_get_system_info(int field);
+extern void dmi_scan_machine(void);
+extern int dmi_get_table(u32 *base, u32 *len);
 
 #endif /* __DMI_H__ */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86: force DMI table to not be in E820 RAM region, Xen patchbot-unstable <=