From owner-freebsd-current@FreeBSD.ORG Sat Feb 7 18:03:22 2015 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 61B777C0 for ; Sat, 7 Feb 2015 18:03:22 +0000 (UTC) Received: from mail.grem.de (outcast.grem.de [213.239.217.27]) by mx1.freebsd.org (Postfix) with SMTP id 8640367D for ; Sat, 7 Feb 2015 18:03:20 +0000 (UTC) Received: (qmail 52848 invoked by uid 89); 7 Feb 2015 17:56:38 -0000 Received: from unknown (HELO bsd64.grem.de) (mg@grem.de@88.217.180.225) by mail.grem.de with ESMTPA; 7 Feb 2015 17:56:38 -0000 Date: Sat, 7 Feb 2015 18:56:31 +0100 From: Michael Gmelin To: "freebsd-current@freebsd.org" Subject: Call for testers, change BIOS memory detection Message-ID: <20150207185631.5766c2e9@bsd64.grem.de> X-Mailer: Claws Mail 3.11.1 (GTK+ 2.24.25; amd64-portbld-freebsd10.0) X-Face: $wrgCtfdVw_H9WAY?S&9+/F"!41z'L$uo*WzT8miX?kZ~W~Lr5W7v?j0Sde\mwB&/ypo^}> +a'4xMc^^KroE~+v^&^#[B">soBo1y6(TW6#UZiC]o>C6`ej+i Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAJFBMVEWJBwe5BQDl LASZU0/LTEWEfHbyj0Txi32+sKrp1Mv944X8/fm1rS+cAAAACXBIWXMAAAsTAAAL EwEAmpwYAAAAB3RJTUUH3wESCxwC7OBhbgAAACFpVFh0Q29tbWVudAAAAAAAQ3Jl YXRlZCB3aXRoIFRoZSBHSU1QbbCXAAAAAghJREFUOMu11DFvEzEUAGCfEhBVFzuq AKkLd0O6VrIQsLXVSZXoWE5N1K3DobBBA9fQpRWc8OkWouaIjedWKiyREOKs+3PY fvalCNjgLVHeF7/3bMtBzV8C/VsQ8tecEgCcDgrzjekwKZ7TwsJZd/ywEKwwP+ZM 8P3drTsAwWn2mpWuDDuYiK1bFs6De0KUUFw0tWxm+D4AIhuuvZqtyWYeO7jQ4Aea 7jUqI+ixhQoHex4WshEvSXdood7stlv4oSuFOC4tqGcr0NjEqXgV4mMJO38nld4+ xKNxRDon7khyKVqY7YR4d+Cg0OMrkWXZOM7YDkEfKiilCn1qYv4mighZiynuHHOA Wq9QJq+BIES7lMFUtcikMnkDGHUoncA+uHgrP0ctIEqfwLHzeSo+eUA66AqzwN6n 2ZHJhw6Qh/PoyC/QENyEyC/AyNjq74Bs+3UH0xYwzDUC4B97HgLocg1QLYgDDO1v f3UX9Y307Ew4AHh67YAFFsxEpkXwpXY3eIgMhAAE3R19L919nNnuD2wlPcDE3UeT L2ytEICQib9BXgS2fU8PrD82ToYO1OEmMSnYTjSqSv9wdC0tPYC+rQRQD9ESnldF CyqfmiYW+tlALt8gH2xrMdC/youbjzPXEun+/ReXsMCDyve3dZc09fn2Oas8oXGc Jj6/fOeK5UmSMPmf/jL+GD8BEj0k/Fn6IO4AAAAASUVORK5CYII= MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Cc: Adrian Chadd X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Feb 2015 18:03:22 -0000 The patch to CURRENT below is an extended version of a patch originally done by Adrian and accomplishes the following: * Add a quirks table based on BIOS vendor / maker / product (NULL matches any), making use of the new smbios_match function * pass in an smap+acpi entry size for e820; like what biossmap.c does; * don't blindly believe e820 if it doesn't give us enough memory to successfully load things, but ONLY if the machine is listed as BQ_DISTRUST_E820_EXTMEM in the quirks table (in this patch this is only the Acer C720 aka Peppy, since it was the reason to write this patch). There are probably other models out there with these issues, but without data it's probably best to add them one at a time. * don't blindly concat cx/dx with e801 - ensure that cx indicates there's no hole and there's a full 15mb of ram before concat'ing; * truncate how much RAM we probe for via e801 (which adrian doesn't entirely think is needed) * if we use e801, don't use the heap as-is; use the end of bios_extmem instead as if we didn't get anything from E820; * add a boot loader command "biosmem" which give details about how memory was detected The code has already been reviewed and more details can be found here: https://reviews.freebsd.org/D1741 It would be great, if a few more people could take a look at this and test it before it's committed to HEAD. Thanks, Michael Index: sys/boot/i386/libi386/biosmem.c =================================================================== diff --git a/head/sys/boot/i386/libi386/biosmem.c b/head/sys/boot/i386/libi386/biosmem.c --- a/head/sys/boot/i386/libi386/biosmem.c (revision 277957) +++ b/head/sys/boot/i386/libi386/biosmem.c (working copy) @@ -32,6 +32,7 @@ */ #include #include +#include "bootstrap.h" #include "libi386.h" #include "btxv86.h" @@ -38,13 +39,56 @@ vm_offset_t memtop, memtop_copyin, high_heap_base; uint32_t bios_basemem, bios_extmem, high_heap_size; -static struct bios_smap smap; +static struct bios_smap_xattr smap; /* + * Used to track which method was used to set BIOS memory + * regions. + */ +static uint8_t b_bios_probed; +#define B_BASEMEM_E820 0x1 +#define B_BASEMEM_12 0x2 +#define B_EXTMEM_E820 0x4 +#define B_EXTMEM_E801 0x8 +#define B_EXTMEM_8800 0x10 + +/* * The minimum amount of memory to reserve in bios_extmem for the heap. */ #define HEAP_MIN (3 * 1024 * 1024) +/* + * Products in this list need quirks to detect + * memory correctly. You need both maker and product as + * reported by smbios. + */ +#define BQ_DISTRUST_E820_EXTMEM 0x1 /* e820 might not return useful + extended memory */ +struct bios_getmem_quirks { + const char* bios_vendor; + const char* maker; + const char* product; + int quirk; +}; + +static struct bios_getmem_quirks quirks[] = { + {"coreboot", "Acer", "Peppy", BQ_DISTRUST_E820_EXTMEM}, + {NULL, NULL, NULL, 0} +}; + +static int +bios_getquirks(void) +{ + int i; + + for (i=0; quirks[i].quirk != 0; ++i) + if (smbios_match(quirks[i].bios_vendor, quirks[i].maker, + quirks[i].product)) + return (quirks[i].quirk); + + return (0); +} + void bios_getmem(void) { @@ -56,7 +100,7 @@ v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; - v86.ecx = sizeof(struct bios_smap); + v86.ecx = sizeof(struct bios_smap_xattr); v86.edx = SMAP_SIG; v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); @@ -65,11 +109,17 @@ break; /* look for a low-memory segment that's large enough */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) && - (smap.length >= (512 * 1024))) + (smap.length >= (512 * 1024))) { bios_basemem = smap.length; + b_bios_probed |= B_BASEMEM_E820; + } /* look for the first segment in 'extended' memory */ - if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) { + /* we need it to be at least 32MiB or -HEAD won't load */ + if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000) && + (smap.length >= (32 * 1024 * 1024) || + !(bios_getquirks() & BQ_DISTRUST_E820_EXTMEM))) { bios_extmem = smap.length; + b_bios_probed |= B_EXTMEM_E820; } /* @@ -100,6 +150,7 @@ v86int(); bios_basemem = (v86.eax & 0xffff) * 1024; + b_bios_probed |= B_BASEMEM_12; } /* Fall back through several compatibility functions for extended memory */ @@ -109,7 +160,29 @@ v86.eax = 0xe801; v86int(); if (!(V86_CY(v86.efl))) { - bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024; + /* + * Clear high_heap; it may end up overlapping + * with the segment we're determining here. + * Let the default "steal stuff from top of + * bios_extmem" code below pick up on it. + */ + high_heap_size = 0; + high_heap_base = 0; + /* + * cx is the number of 1KiB blocks between 1..16MiB. + * It can only be up to 0x3c00; if it's smaller then + * there's a PC AT memory hole so we can't treat + * it as contiguous. + */ + bios_extmem = (v86.ecx & 0xffff) * 1024; + if (bios_extmem == (1024 * 0x3c00)) + bios_extmem += (v86.edx & 0xffff) * 64 * 1024; + + /* truncate bios_extmem */ + if (bios_extmem > 0x3ff00000) + bios_extmem = 0x3ff00000; + + b_bios_probed |= B_EXTMEM_E801; } } if (bios_extmem == 0) { @@ -118,6 +191,7 @@ v86.eax = 0x8800; v86int(); bios_extmem = (v86.eax & 0xffff) * 1024; + b_bios_probed |= B_EXTMEM_8800; } /* Set memtop to actual top of memory */ @@ -132,4 +206,36 @@ high_heap_size = HEAP_MIN; high_heap_base = memtop - HEAP_MIN; } -} +} + +static int +command_biosmem(int argc, char *argv[]) +{ + int bq = bios_getquirks(); + + printf("bios_basemem: 0x%llx\n", (unsigned long long) bios_basemem); + printf("bios_extmem: 0x%llx\n", (unsigned long long) bios_extmem); + printf("memtop: 0x%llx\n", (unsigned long long) memtop); + printf("high_heap_base: 0x%llx\n", (unsigned long long) high_heap_base); + printf("high_heap_size: 0x%llx\n", (unsigned long long) high_heap_size); + printf("bios_quirks: 0x%02x", bq); + if (bq & BQ_DISTRUST_E820_EXTMEM) + printf(" BQ_DISTRUST_E820_EXTMEM"); + printf("\n"); + printf("b_bios_probed: 0x%02x", (int) b_bios_probed); + if (b_bios_probed & B_BASEMEM_E820) + printf(" B_BASEMEM_E820"); + if (b_bios_probed & B_BASEMEM_12) + printf(" B_BASEMEM_12"); + if (b_bios_probed & B_EXTMEM_E820) + printf(" B_EXTMEM_E820"); + if (b_bios_probed & B_EXTMEM_E801) + printf(" B_EXTMEM_E801"); + if (b_bios_probed & B_EXTMEM_8800) + printf(" B_EXTMEM_8800"); + printf("\n"); + + return (CMD_OK); +} + +COMMAND_SET(smap, "biosmem", "show BIOS memory setup", command_biosmem); -- Michael Gmelin