From owner-freebsd-current Sun Nov 10 4:45:31 2002 Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4D5C237B401; Sun, 10 Nov 2002 04:45:25 -0800 (PST) Received: from HAL9000.homeunix.com (12-232-220-15.client.attbi.com [12.232.220.15]) by mx1.FreeBSD.org (Postfix) with ESMTP id 879D043E6E; Sun, 10 Nov 2002 04:45:24 -0800 (PST) (envelope-from dschultz@uclink.Berkeley.EDU) Received: from HAL9000.homeunix.com (localhost [127.0.0.1]) by HAL9000.homeunix.com (8.12.6/8.12.5) with ESMTP id gAACi6DN002398; Sun, 10 Nov 2002 04:44:06 -0800 (PST) (envelope-from dschultz@uclink.Berkeley.EDU) Received: (from das@localhost) by HAL9000.homeunix.com (8.12.6/8.12.5/Submit) id gAAChsMu002397; Sun, 10 Nov 2002 04:43:54 -0800 (PST) (envelope-from dschultz@uclink.Berkeley.EDU) Date: Sun, 10 Nov 2002 04:43:54 -0800 From: David Schultz To: Mitsuru IWASAKI Cc: arg-bsd@arg1.demon.co.uk, stable@FreeBSD.ORG, current@FreeBSD.ORG, David Rhodu , Sidcarter Subject: Re: machdep.c problem Message-ID: <20021110124354.GA2292@HAL9000.homeunix.com> Mail-Followup-To: Mitsuru IWASAKI , arg-bsd@arg1.demon.co.uk, stable@FreeBSD.ORG, current@FreeBSD.ORG, David Rhodu , Sidcarter References: <20021109.041802.45867347.iwasaki@jp.FreeBSD.org> <20021108234404.L22249-100000@server.arg.sj.co.uk> <20021110.050300.98560281.iwasaki@jp.FreeBSD.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20021110.050300.98560281.iwasaki@jp.FreeBSD.org> Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Thus spake Mitsuru IWASAKI : > OK, it seems to be difficult to determine the region for any BIOSes. > I've decided to introduce a new loader tunable to indicate that BIOS > has broken int 12H. Attached patch back out 1.385.2.26 changes to > support older BIOSes, and add support for broken int 12 BIOSes by > new loader tunable. > I don't think this is the best solution, but it is probably good for > all people for now. > I'll make the equivalent patches for CURRENT and commit them, > then MFC soon. > Sorry for inconvenience, folks. This approach is okay with me in the sense that it doesn't break anything that wasn't already broken, but as you say, I think we can do better. Below is a patch that merely extracts the basemem size from the bootinfo structure for the purposes of mapping the EBDA. I retained the int 12h fallback just to be safe, but I think the bootinfo structure is initialized with a valid basemem for all loaders since at least 1998. (Maybe the fallbacks in the kernel should be removed entirely to avoid redundancy, or moved from loader and boot2 to locore.s.) I also converted basemem from kilobytes to bytes in order to simplify the math in the common case. Patches are against -CURRENT; I can provide patches against -STABLE as well, barring any complaints. Index: machdep.c =================================================================== RCS file: /cvs/src/sys/i386/i386/machdep.c,v retrieving revision 1.547 diff -u -r1.547 machdep.c --- machdep.c 7 Nov 2002 23:57:16 -0000 1.547 +++ machdep.c 10 Nov 2002 12:09:19 -0000 @@ -1477,7 +1477,25 @@ bzero(&vmf, sizeof(struct vm86frame)); bzero(physmap, sizeof(physmap)); - basemem = 0; + + /* + * If basemem is < 640, the gap contains an extended BIOS + * data area and must be mapped read/write before any + * BIOS calls are made. Note that we can't use int 0x12 + * to determine the base memory at this point because + * some modern machines do not support that interface. + * Instead, we rely on the loader to supply the value. + */ + basemem = bootinfo.bi_basemem; + if (basemem) { + for (pa = trunc_page(basemem); + pa < ISA_HOLE_START; pa += PAGE_SIZE) + pmap_kenter(KERNBASE + pa, pa); + + pte = (pt_entry_t *)vm86paddr; + for (i = basemem >> PAGE_SHIFT; i < 160; i++) + pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U; + } /* * map page 1 R/W into the kernel page table so we can use it @@ -1515,6 +1533,11 @@ if (smap->length == 0) goto next_run; + if (smap->base == 00 && smap->length >= (512 * 1024)) { + basemem = smap->length; + goto next_run; + } + if (smap->base >= 0xffffffff) { printf("%uK of memory above 4GB ignored\n", (u_int)(smap->length / 1024)); @@ -1546,64 +1569,21 @@ next_run: ; } while (vmf.vmf_ebx != 0); - /* - * Perform "base memory" related probes & setup - */ - for (i = 0; i <= physmap_idx; i += 2) { - if (physmap[i] == 0x00000000) { - basemem = physmap[i + 1] / 1024; - break; - } - } + if (physmap[1] != 0) + goto physmap_done; - /* Fall back to the old compatibility function for base memory */ if (basemem == 0) { vm86_intcall(0x12, &vmf); - basemem = vmf.vmf_ax; + basemem = vmf.vmf_ax * 1024; } - if (basemem > 640) { + if (basemem > 640 * 1024) { printf("Preposterous BIOS basemem of %uK, truncating to 640K\n", - basemem); - basemem = 640; + basemem / 1024); + basemem = 640 * 1024; } /* - * XXX if biosbasemem is now < 640, there is a `hole' - * between the end of base memory and the start of - * ISA memory. The hole may be empty or it may - * contain BIOS code or data. Map it read/write so - * that the BIOS can write to it. (Memory from 0 to - * the physical end of the kernel is mapped read-only - * to begin with and then parts of it are remapped. - * The parts that aren't remapped form holes that - * remain read-only and are unused by the kernel. - * The base memory area is below the physical end of - * the kernel and right now forms a read-only hole. - * The part of it from PAGE_SIZE to - * (trunc_page(biosbasemem * 1024) - 1) will be - * remapped and used by the kernel later.) - * - * This code is similar to the code used in - * pmap_mapdev, but since no memory needs to be - * allocated we simply change the mapping. - */ - for (pa = trunc_page(basemem * 1024); - pa < ISA_HOLE_START; pa += PAGE_SIZE) - pmap_kenter(KERNBASE + pa, pa); - - /* - * if basemem != 640, map pages r/w into vm86 page table so - * that the bios can scribble on it. - */ - pte = (pt_entry_t *)vm86paddr; - for (i = basemem / 4; i < 160; i++) - pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U; - - if (physmap[1] != 0) - goto physmap_done; - - /* * If we failed above, try memory map with INT 15:E801 */ vmf.vmf_ax = 0xE801; @@ -1636,7 +1616,7 @@ extmem = 15 * 1024; physmap[0] = 0; - physmap[1] = basemem * 1024; + physmap[1] = basemem; physmap_idx = 2; physmap[physmap_idx] = 0x100000; physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024; To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message