161 lines
5.3 KiB
Diff
161 lines
5.3 KiB
Diff
Index: 2007-05-14/xen/arch/x86/dmi_scan.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/dmi_scan.c 2007-08-17 17:13:44.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/dmi_scan.c 2007-08-16 16:44:35.000000000 +0200
|
|
@@ -102,7 +102,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;
|
|
@@ -123,6 +123,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.
|
|
@@ -436,13 +441,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-05-14/xen/arch/x86/setup.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/setup.c 2007-08-17 17:13:44.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/setup.c 2007-08-20 11:59:15.000000000 +0200
|
|
@@ -35,6 +35,7 @@
|
|
#include <xen/kexec.h>
|
|
|
|
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);
|
|
|
|
@@ -301,8 +302,9 @@ void __init __start_xen(multiboot_info_t
|
|
unsigned long _policy_len = 0;
|
|
module_t *mod = (module_t *)__va(mbi->mods_addr);
|
|
unsigned long nr_pages, modules_length;
|
|
- paddr_t s, e;
|
|
+ u64 s, e;
|
|
int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
|
|
+ u32 dmi_table_start, dmi_table_len;
|
|
struct ns16550_defaults ns16550 = {
|
|
.data_bits = 8,
|
|
.parity = 'n',
|
|
@@ -361,7 +363,7 @@ void __init __start_xen(multiboot_info_t
|
|
|
|
if ( mbi->flags & MBI_MEMMAP )
|
|
{
|
|
- while ( bytes < mbi->mmap_length )
|
|
+ while ( bytes < mbi->mmap_length && e820_raw_nr < E820MAX )
|
|
{
|
|
memory_map_t *map = __va(mbi->mmap_addr + bytes);
|
|
|
|
@@ -411,15 +413,52 @@ void __init __start_xen(multiboot_info_t
|
|
printk("WARNING: Buggy e820 map detected and fixed "
|
|
"(truncated length fields).\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++ )
|
|
{
|
|
- 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 */
|
|
+
|
|
+ /*
|
|
+ * 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;
|
|
@@ -427,6 +466,19 @@ void __init __start_xen(multiboot_info_t
|
|
}
|
|
}
|
|
|
|
+ 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(e820_raw, &e820_raw_nr);
|
|
|