Thus spake Mitsuru IWASAKI <[EMAIL PROTECTED]>:
> 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 [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to