Re: [PATCH] Workaround for bogus INT 12H BIOS serviceimplementation

2002-10-21 Thread Mitsuru IWASAKI
> > -   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 -  1.542
+++ machdep.c   22 Oct 2002 03:04:15 -
@@ -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] == 0x) {
+   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(biosb

Re: [PATCH] Workaround for bogus INT 12H BIOS serviceimplementation

2002-10-21 Thread Mitsuru IWASAKI
> > > Hmmm, actually no.  I know that some machines get panic with fatal trap
> > > 12 if we do 0x12 call.  The worst case is getting panic, not losing
> > > 640K memory.
> > 
> > Where does the panic occur?  I checked that there is no problem here if
> > the result of INT 0x12 is ignored and basemem is set to 0.
> 
> panic messages attached.  It seems to be within BIOS routine after reti
> jumped from vm86_bioscall.
> Strangely, this panic can be recovered by continue command in DDB,
> FreeBSD continues its boot process after this.  So, this panic problem
> is not serious for me :)
> OTOH, the same problem in boot program is very critical, completely stops
> with register dump...

FYI: On RELENG_4, this problem is critical too because this panic
isn't recoverable.  This means that it's impossible to install onto
some newer machines.

> > > And it seems that today's Linux don't have 0x12 calling any more,
> > > so I didn't see any problem on the machines.
> > >
> > > Now I have some ideas on this issue;
> > >  - 0x15/0xe820 call in getmemsize() to determine base mem size. (But how?)
> > >  - 0x15/0xe820 call in locore.s before calling init386().
> > >  - specify the size by loader tunable (e.g. hw.basememsize).
> > 
> > I would first fix all the broken code that doesn't check for errors
> > and see if the problem goes away.  Then recover any low memory not
> > reported by int 0x12 in the int 0x15/0xe820 code in i386/machdep.c,
> > like libi386/biosmem.c does it (I think machdep.c intentionally skips
> > the low memory, while biosmem.c tries to find it).
> 
> Cool.  Thanks!
> 
> Stopped at  0xf842:
> 
> Fatal trap 12: page fault while in kernel mode
> fault virtual address   = 0xf842
> fault code= supervisor read, page not present
> instruction pointer   = 0x8:0xc03b5108
> stack pointer = 0x10:0xc0a68e90
> frame pointer = 0x10:0xc0a68e94
> code segment  = base 0x0,limit 0xf, type 0x1b
>   = DPL 0, press 1, def32 1, gran 1
> processor eflags  = resume,IOPL = 0
> current process   = 0 ()
>  kernel:type 12 trap,code=0
> db> t
> Fatal trap 12: page fault while in kernel mode

I've recalled that FreeBSD used RTC to determine base memory size in
old days.  I've tested this method on my machines and confirmed it's
working well.

I'll commit this coming weekend if no objections.

Thanks

Index: machdep.c
===
RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v
retrieving revision 1.541
diff -u -r1.541 machdep.c
--- machdep.c   5 Oct 2002 14:36:14 -   1.541
+++ machdep.c   21 Oct 2002 15:27:02 -
@@ -1284,8 +1284,14 @@
/*
 * Perform "base memory" related probes & setup
 */
-   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);

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message



Re: [PATCH] Workaround for bogus INT 12H BIOS serviceimplementation

2002-10-21 Thread Nate Williams
> I've recalled that FreeBSD used RTC to determine base memory size in
> old days.  I've tested this method on my machines and confirmed it's
> working well.

If this is done, then FreeBSD won't work on many laptops and other
desktops, which report 640K for memory, but the BIOS actually steals
some of the memory for things like APM, so when the VM86 call is done
the reported memory size is actually like (like 637K or something).

This change may break FreeBSD on these 'newer' hardware as well.



Nate

> I'll commit this coming weekend if no objections.
> 
> Thanks
> 
> Index: machdep.c
> ===
> RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v
> retrieving revision 1.541
> diff -u -r1.541 machdep.c
> --- machdep.c 5 Oct 2002 14:36:14 -   1.541
> +++ machdep.c 21 Oct 2002 15:27:02 -
> @@ -1284,8 +1284,14 @@
>   /*
>* Perform "base memory" related probes & setup
>*/
> - 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);
> 
> To Unsubscribe: send mail to [EMAIL PROTECTED]
> with "unsubscribe freebsd-current" in the body of the message

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message



Re: [PATCH] Workaround for bogus INT 12H BIOS serviceimplementation

2002-10-02 Thread Mitsuru IWASAKI

Hi,

> > > The patch makes no difference for booting directly from boot2 ... except
> > > memsize() in boot2 also fails to check for errors, so it returns garbage
> > > values.
> >
> > Yes I know that :-)
> > But booting kernel directly from boot2 is not working at all for
> > several years, so my understanding is that /boot/loader is necessary
> > to boot kernel.
> 
> It mostly works.  I submitted patches in a PR many years ago and still use
> them.

Great!  I tried to find the PR, but couldn't find...
Why isn't it committed yet? :-)

> > Hmmm, actually no.  I know that some machines get panic with fatal trap
> > 12 if we do 0x12 call.  The worst case is getting panic, not losing
> > 640K memory.
> 
> Where does the panic occur?  I checked that there is no problem here if
> the result of INT 0x12 is ignored and basemem is set to 0.

panic messages attached.  It seems to be within BIOS routine after reti
jumped from vm86_bioscall.
Strangely, this panic can be recovered by continue command in DDB,
FreeBSD continues its boot process after this.  So, this panic problem
is not serious for me :)
OTOH, the same problem in boot program is very critical, completely stops
with register dump...

> > And it seems that today's Linux don't have 0x12 calling any more,
> > so I didn't see any problem on the machines.
> >
> > Now I have some ideas on this issue;
> >  - 0x15/0xe820 call in getmemsize() to determine base mem size. (But how?)
> >  - 0x15/0xe820 call in locore.s before calling init386().
> >  - specify the size by loader tunable (e.g. hw.basememsize).
> 
> I would first fix all the broken code that doesn't check for errors
> and see if the problem goes away.  Then recover any low memory not
> reported by int 0x12 in the int 0x15/0xe820 code in i386/machdep.c,
> like libi386/biosmem.c does it (I think machdep.c intentionally skips
> the low memory, while biosmem.c tries to find it).

Cool.  Thanks!

Stopped at  0xf842:

Fatal trap 12: page fault while in kernel mode
fault virtual address   = 0xf842
fault code  = supervisor read, page not present
instruction pointer = 0x8:0xc03b5108
stack pointer   = 0x10:0xc0a68e90
frame pointer   = 0x10:0xc0a68e94
code segment= base 0x0,limit 0xf, type 0x1b
= DPL 0, press 1, def32 1, gran 1
processor eflags= resume,IOPL = 0
current process = 0 ()
 kernel:type 12 trap,code=0
db> t
Fatal trap 12: page fault while in kernel mode

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message



Re: [PATCH] Workaround for bogus INT 12H BIOS serviceimplementation

2002-09-30 Thread Mitsuru IWASAKI

Hi,

> > Index: sys/i386/i386/machdep.c
> > ===
> > RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v
> > retrieving revision 1.532
> > diff -u -r1.532 machdep.c
> > --- sys/i386/i386/machdep.c 7 Sep 2002 19:12:42 -   1.532
> > +++ sys/i386/i386/machdep.c 29 Sep 2002 21:15:26 -
> > @@ -1269,8 +1269,12 @@
> > /*
> >  * Perform "base memory" related probes & setup
> >  */
> > -   vm86_intcall(0x12, &vmf);
> > -   basemem = vmf.vmf_ax;
> > +   if (bootinfo.bi_basemem != 0) {
> > +   basemem = bootinfo.bi_basemem;
> > +   } else {
> > +   vm86_intcall(0x12, &vmf);
> > +   basemem = vmf.vmf_ax;
> > +   }
> > if (basemem > 640) {
> > printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
> > basemem);
> 
> The kernel hasn't used bootinfo.bi_basemem for a long time and shouldn't
> start using it again now.  It already uses the 0x15/0xe820 call for
> everything except basemem (except when the this call fails, it falls
> back to 0x15/0xe801).  Maybe the bug has something to do with the
> kernel using the 0x12 call without checking whether the call succeeded.
> 
> When both the 0x15/0xe820 and the 0x15/0xe801 calls fail, the kernel
> falls back to an 0x15/0x88 call for determining extmem ... except this
> is ifdefed out and replaced by looking at the rtc values.  Maybe the
> unreliability of the 0x15/0x88 call has something to do with not
> checking if the call succeeded.

Yes, I think the best way to determine base mem size in getmemsize()
is to try 0x15/0xe820 call first, then fall back to 0x12 call.  But
I'm not sure whether it's OK to call vm86_datacall(0x15) before
determining base mem size...

> The patch makes no difference for booting directly from boot2 ... except
> memsize() in boot2 also fails to check for errors, so it returns garbage
> values.

Yes I know that :-)
But booting kernel directly from boot2 is not working at all for
several years, so my understanding is that /boot/loader is necessary
to boot kernel.

> I think the basemem == 0 case should just work, so the systems with a
> broken INT 0x12 should at worst lose 640K of memory, no matter whether
> basemem is set to 0 because INT 0x12 fails or because it actually
> returns 0.

Hmmm, actually no.  I know that some machines get panic with fatal trap
12 if we do 0x12 call.  The worst case is getting panic, not losing
640K memory.
And it seems that today's Linux don't have 0x12 calling any more,
so I didn't see any problem on the machines.

Now I have some ideas on this issue;
 - 0x15/0xe820 call in getmemsize() to determine base mem size. (But how?)
 - 0x15/0xe820 call in locore.s before calling init386().
 - specify the size by loader tunable (e.g. hw.basememsize).

Comments?

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message