Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Nov 2002 05:03:00 +0900 (JST)
From:      Mitsuru IWASAKI <iwasaki@jp.FreeBSD.org>
To:        arg-bsd@arg1.demon.co.uk
Cc:        stable@FreeBSD.ORG
Subject:   Re: machdep.c problem
Message-ID:  <20021110.050300.98560281.iwasaki@jp.FreeBSD.org>
In-Reply-To: <20021108234404.L22249-100000@server.arg.sj.co.uk>
References:  <20021109.041802.45867347.iwasaki@jp.FreeBSD.org> <20021108234404.L22249-100000@server.arg.sj.co.uk>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi,

Thanks for reporting.

> > OK, revised patches (w/ debug printing) attached.
> > Could you let me know what was the last message one of these?
> >  1. getmemsize: mapping BIOS work pages
> >  2. getmemsize: calling INT 15:E820
> >  3. getmemsize: unmapping BIOS work pages
> 
> 
> Messages 1 and 2 appear, followed by:
>  Fatal trap 1: privileged instructonfault ....
> Message 3 does not appear.
> 
> 
> > Also previous patches might give too many pages to BIOS.
> > Can you adjust this value and try again increasing up to 159?
> > #define BIOSWORKSTARTPAGE	152
> 
> I will try this tomorrow.

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.

Thanks

Index: machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v
retrieving revision 1.385.2.26
diff -u -r1.385.2.26 machdep.c
--- machdep.c	2 Nov 2002 05:07:18 -0000	1.385.2.26
+++ machdep.c	9 Nov 2002 19:27:02 -0000
@@ -152,6 +152,9 @@
 #endif
 SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, "");
 
+static int	hasbrokenint12 = 0;
+TUNABLE_INT("hw.hasbrokenint12", &hasbrokenint12);
+
 int physmem = 0;
 int cold = 1;
 
@@ -1468,6 +1471,61 @@
 	basemem = 0;
 
 	/*
+	 * Some newer BIOSes has broken INT 12H implementation which cause
+	 * kernel panic immediately. In this case, we need to scan SMAP
+	 * with INT 15:E820 first, then determine base memory size.
+	 */
+	if (hasbrokenint12) {
+		goto int15e820;
+	}
+
+	/*
+	 * Perform "base memory" related probes & setup
+	 */
+	vm86_intcall(0x12, &vmf);
+	basemem = vmf.vmf_ax;
+	if (basemem > 640) {
+		printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
+			basemem);
+		basemem = 640;
+	}
+
+	/*
+	 * 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) {
+		pte = (pt_entry_t)vtopte(pa + KERNBASE);
+		*pte = pa | PG_RW | PG_V;
+	}
+
+	/*
+	 * 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;
+
+int15e820:
+	/*
 	 * map page 1 R/W into the kernel page table so we can use it
 	 * as a buffer.  The kernel will unmap this page later.
 	 */
@@ -1539,60 +1597,36 @@
 	} while (vmf.vmf_ebx != 0);
 
 	/*
-	 * Perform "base memory" related probes & setup
+	 * Perform "base memory" related probes & setup based on SMAP
 	 */
-	for (i = 0; i <= physmap_idx; i += 2) {
-		if (physmap[i] == 0x00000000) {
-			basemem = physmap[i + 1] / 1024;
-			break;
+	if (basemem == 0) {
+		for (i = 0; i <= physmap_idx; i += 2) {
+			if (physmap[i] == 0x00000000) {
+				basemem = physmap[i + 1] / 1024;
+				break;
+			}
 		}
-	}
 
-	/* Fall back to the old compatibility function for base memory */
-	if (basemem == 0) {
-		vm86_intcall(0x12, &vmf);
-		basemem = vmf.vmf_ax;
-	}
+		if (basemem == 0) {
+			basemem = 640;
+		}
 
-	if (basemem > 640) {
-		printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
-			basemem);
-		basemem = 640;
-	}
+		if (basemem > 640) {
+			printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
+				basemem);
+			basemem = 640;
+		}
 
-	/*
-	 * 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) {
-		pte = (pt_entry_t)vtopte(pa + KERNBASE);
-		*pte = pa | PG_RW | PG_V;
-	}
+		for (pa = trunc_page(basemem * 1024);
+		     pa < ISA_HOLE_START; pa += PAGE_SIZE) {
+			pte = (pt_entry_t)vtopte(pa + KERNBASE);
+			*pte = pa | PG_RW | PG_V;
+		}
 
-	/*
-	 * 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;
+		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;

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




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