Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Nov 2002 04:43:54 -0800
From:      David Schultz <dschultz@uclink.Berkeley.EDU>
To:        Mitsuru IWASAKI <iwasaki@jp.FreeBSD.org>
Cc:        arg-bsd@arg1.demon.co.uk, stable@FreeBSD.ORG, current@FreeBSD.ORG, David Rhodu <david@uky.edu>, Sidcarter <sidcarter@symonds.net>
Subject:   Re: machdep.c problem
Message-ID:  <20021110124354.GA2292@HAL9000.homeunix.com>
In-Reply-To: <20021110.050300.98560281.iwasaki@jp.FreeBSD.org>
References:  <20021109.041802.45867347.iwasaki@jp.FreeBSD.org> <20021108234404.L22249-100000@server.arg.sj.co.uk> <20021110.050300.98560281.iwasaki@jp.FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Thus spake Mitsuru IWASAKI <iwasaki@jp.FreeBSD.org>:
> 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021110124354.GA2292>