From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH] x86: force DMI table to not be in E820 RAM region Date: Tue, 21 Aug 2007 16:19:46 +0100 Message-ID: <46CB1EB2.76E4.0078.0@novell.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Return-path: Content-Disposition: inline List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org 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 Index: 2007-08-08/xen/arch/x86/dmi_scan.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-08-08.orig/xen/arch/x86/dmi_scan.c 2007-08-06 15:08:40.0000000= 00 +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=3D=3D0); } =20 -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=3Dbuf[7]<<8|buf[6]; u32 base=3Dbuf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]= ; =20 + if (pbase) + *pbase =3D 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 =20 void __init dmi_scan_machine(void) { - int err =3D dmi_iterate(dmi_decode); + int err =3D dmi_iterate(dmi_decode, NULL); if(err =3D=3D 0) dmi_check_system(dmi_blacklist); else printk(KERN_INFO "DMI not present.\n"); } =20 +int __init dmi_get_table(u32*pbase, u32*plen) +{ + int rc =3D dmi_iterate(NULL, pbase); + + if (rc < 0) { + *pbase =3D *plen =3D 0; + return rc; + } + + *plen =3D rc; + + return 0; +} + =20 /** * dmi_check_system - check system DMI data Index: 2007-08-08/xen/arch/x86/setup.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2007-08-08.orig/xen/arch/x86/setup.c 2007-08-09 12:58:04.0000000= 00 +0200 +++ 2007-08-08/xen/arch/x86/setup.c 2007-08-21 13:48:30.000000000 = +0200 @@ -45,6 +45,7 @@ #endif =20 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); =20 @@ -425,6 +426,7 @@ void __init __start_xen(unsigned long mb module_t *mod =3D (module_t *)__va(mbi->mods_addr); unsigned long nr_pages, modules_length; int i, e820_warn =3D 0, bytes =3D 0; + u32 dmi_table_start, dmi_table_len; struct ns16550_defaults ns16550 =3D { .data_bits =3D 8, .parity =3D 'n', @@ -554,7 +556,7 @@ void __init __start_xen(unsigned long mb else if ( mbi->flags & MBI_MEMMAP ) { memmap_type =3D "Multiboot-e820"; - while ( bytes < mbi->mmap_length ) + while ( bytes < mbi->mmap_length && e820_raw_nr < E820MAX ) { memory_map_t *map =3D __va(mbi->mmap_addr + bytes); =20 @@ -605,6 +607,9 @@ void __init __start_xen(unsigned long mb EARLY_FAIL("Bootloader provided no memory information.\n"); } =20 + dmi_get_table(&dmi_table_start, &dmi_table_len); + e820_warn =3D 0; + /* Ensure that all E820 RAM regions are page-aligned and -sized. */ for ( i =3D 0; i < e820_raw_nr; i++ ) { @@ -615,6 +620,41 @@ void __init __start_xen(unsigned long mb s =3D PFN_UP(e820_raw[i].addr); e =3D PFN_DOWN(e820_raw[i].addr + e820_raw[i].size); e820_raw[i].size =3D 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 =3D (u64)dmi_table_start + dmi_table_len; + + if ( (s << PAGE_SHIFT) >=3D dmi_table_start && + (e << PAGE_SHIFT) <=3D dmi_table_end ) + e =3D s; + else if ( (s << PAGE_SHIFT) >=3D dmi_table_start ) + s =3D PFN_UP(dmi_table_end); + else if ( (e << PAGE_SHIFT) <=3D dmi_table_end ) + e =3D PFN_DOWN(dmi_table_start); + else if ( e820_raw_nr < E820MAX ) + { + e820_raw[e820_raw_nr].addr =3D dmi_table_end; + e820_raw[e820_raw_nr].size =3D (e << PAGE_SHIFT) - = dmi_table_end; + e820_raw[e820_raw_nr].type =3D E820_RAM; + ++e820_raw_nr; + e =3D PFN_DOWN(dmi_table_start); + } + else if ( dmi_table_start - (s << PAGE_SHIFT) >=3D + (e << PAGE_SHIFT) - dmi_table_end ) + e =3D PFN_DOWN(dmi_table_start); + else + s =3D PFN_UP(dmi_table_end); + e820_warn =3D 1; + } + if ( s < e ) { e820_raw[i].addr =3D s << PAGE_SHIFT; @@ -622,6 +662,19 @@ void __init __start_xen(unsigned long mb } } =20 + 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 =3D dmi_table_start; + e820_raw[e820_raw_nr].size =3D dmi_table_len; + e820_raw[e820_raw_nr].type =3D E820_RESERVED; + ++e820_raw_nr; + } + } + /* Sanitise the raw E820 map to produce a final clean version. */ max_page =3D init_e820(memmap_type, e820_raw, &e820_raw_nr); =20