Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Oct 2002 12:13:55 +0900 (JST)
From:      Mitsuru IWASAKI <iwasaki@jp.FreeBSD.org>
To:        bde@zeta.org.au
Cc:        current@FreeBSD.ORG
Subject:   Re: [PATCH] Workaround for bogus INT 12H BIOS service implementation
Message-ID:  <20021022.121355.78702461.iwasaki@jp.FreeBSD.org>
In-Reply-To: <20021022103609.V12732-100000@gamplex.bde.org>
References:  <20021022.003512.15273101.iwasaki@jp.FreeBSD.org> <20021022103609.V12732-100000@gamplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
> > -	vm86_intcall(0x12, &vmf);
> > -	basemem = vmf.vmf_ax;
> > +	if ((basemem = rtcin(RTC_BASELO) + (rtcin(RTC_BASEHI)<<8)) > 640)
> > +		basemem = 640;
> > +
> > +	if (basemem == 0) {
> > +		vm86_intcall(0x12, &vmf);
> > +		basemem = vmf.vmf_ax;
> > +	}
> > +
> >  	if (basemem > 640) {
> >  		printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
> >  			basemem);
> >
> 
> This would reintroduce a large bug.  The RTC gives the hardware memory
> size, but the interrupt gives the software memory size.  These differ
> for one of two machines under my desk (both have Award BIOSes).  The
> BIOS often steals some of the base memory.  It's hard to tell whether
> this memory will be used after FreeBSD determines the memory size.  It
> might be used for VM86 or (much more magically) for SMM.
> 
> Reading the memory size from BIOS RAM (offset 0x413) would be safer.
> I'm not sure how standard this is.  I thought that it is less standard
> than INT 0x12.

OK, RELENG_3 GENERIC kernel might have problems with base memory, RTC
was used there...

How about this?  It's my original idea.

Thanks

Index: machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v
retrieving revision 1.542
diff -u -r1.542 machdep.c
--- machdep.c	12 Oct 2002 05:32:23 -0000	1.542
+++ machdep.c	22 Oct 2002 03:04:15 -0000
@@ -1281,49 +1281,7 @@
 
 	bzero(&vmf, sizeof(struct vm86frame));
 	bzero(physmap, sizeof(physmap));
-
-	/*
-	 * 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)
-		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;
+	basemem = 0;
 
 	/*
 	 * map page 1 R/W into the kernel page table so we can use it
@@ -1391,6 +1349,60 @@
 		physmap[physmap_idx + 1] = smap->base + smap->length;
 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;
+		}
+	}
+
+	/* Fall back to the old compatibility function for base memory */
+	if (basemem == 0) {
+		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)
+		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;

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?20021022.121355.78702461.iwasaki>