Re: Why reassert ix86 NMI?

From: Richard B. Johnson (root@chaos.analogic.com)
Date: Wed Jun 07 2000 - 09:03:23 EST


On Wed, 7 Jun 2000, Maciej W. Rozycki wrote:

> On Tue, 6 Jun 2000, Richard B. Johnson wrote:
>
> > > I can't recall Linux using INT 0x15, function 0x87... This is
> > > irrelevant.
> >
> > LILO uses it to load the kernel above the "1 megabyte boundary".
> > This is, therefore, quite relevant.
>
> Of course, but LILO exits long before there is a chance for our NMI
> handler to be invoked.
>
> > > If you start from a cold-boot, the BIOS checks for a cold startup
> > > condition in the 8042 before checking the shutdown byte. It's usually
> > > just after executing a far jump at 0xf000:0xfff0. There is only a smsw
> >
> > The BIOS for most new processors, i.e., after the 486/DX does not do
> > a far jump at 0xf000:fff0. What you see there with `debug` is after
> > the BIOS has been shadowed. That vector usually points to some low-
> > memory code before jumping to the previous vector.
>
> Hmm, have I written anything about debug? Just mmap() 64kB of /dev/mem
> at 0xffff0000 and study it with objdump. You'll see what I mean.

You are not looking at the PROM. You are looking at what was shadowed.
The physical PROM (or NVRAM) exists at physical address 0xfffff000, with
the reset vector at 0xfffffff0, as previously stated.

>
> > Upon startup, the BIOS does _not_ exists at 0xF000:0000, with the
> > reset-vector at 0xF000:FFF0!!
>
> Most if not all current chipsets decode both 0xffff0000 and 0x000f0000 to
> the ROM chip upon reset (they also decode 0xffef0000 to account for
> masking of the A20 line). These two (three) ranges are the same. Other
> areas, such as 64kB at 0xfffe0000 may differ as there might be the rest of
> the ROM mapped. Talk to linuxbios people -- they chased 2Mbit Flashes
> recently.

No. The gobble-de-gook quoted above has no basis in fact and is an
amateur explanation of some, otherwise unexplainable, observation.
The modern chip-sets use 'PARs' Programmable Address Registers, to
map various PROMS, including BIOS modules. It is important to understand
this, therefore I am taking the time to explain.

Upon hardware reset, the BIOS module, which may be NVRAM or a PROM,
is decoded at one place and one place only. If it is 64k in length, it
will be decoded 64k from the top of physical address space, i.e.,
0xffff0000.

The CPU will start fetching instructions 16 bytes from the end of this
area, i.e., 0xfffffff0. Address-bit A<20> does not enter into this.
If it's not enabled, you just get aliases of the same code at 1 Mb
intervals throughout address space.

The instruction fetches in real mode, with 32-bit addressing will work
as long as the CS register is not reloaded with a 'far' jump or call.
This happens because, upon reset, the CPU core sets the base value
of the CS Descriptor Cache register to 0xffff0000, with a limit of
0x0000ffff. The processor CS:EIP pair is set to F000:0000FFF0. The
redirection works because in real mode linear addresses for code fetches
are generated by taking the offset in EIP and adding it to the contents
of the base register in the CS descriptor cache.

One of the first things done by the BIOS is to look in CMOS to
see if this was a processor-only reset caused by an exception in
protected mode. If so, it doesn't have to build the machine. It
just reloads SS:SP, restores previous registers, and returns to the
caller.

Otherwise, the machine must be built. A PAR register (hardware
specific) is used to to enable a decode of the BIOS module at 0x000f0000.

Since the previously-described code takes more instruction-space than the
16 bytes available, the first instruction at the reset-vector will be a
'near' jump to the code necessary to do this.

Then the BIOS has to enable other hardware-specific bits in configuration
registers to connect up the components within the chip-sets. This
basically involves building the machine using software configuration
registers. In the 'olden days' hardware engineers made PALs to connect
up (decode) devices. Now it's done in software.

Eventually, the BIOS has built the machine into its PC-Compatible
architecture. At this time, it does a far jump to the code in the
BIOS module that it has enabled at the 'standard' location.

Then it turns off A<20> (if it was enabled) for compatibility-wrap.

Then it sets about getting the memory-controller working and sizing
RAM. Eventually, there is RAM which has been cleared.

Then it copies itself to low RAM, jumps to low RAM, then it
disables the PROM decode at the standard location. It is truly and
completely disabled. Its one-and-only decode exists at physical
address 0xfffff000 which is not visible anymore in real mode.

Then it copies itself back to F000:0000 and jumps into code existing
at its final address.

After all the other POST stuff is done, the BIOS puts a far jump
instruction at F000:FFF0 to 'warm-boot' code. It then may or may
not write-protect the BIOS area. What you see when you disassemble
the code this points to, is never the code that would be executed
after power-on or reset switch operation.

During the ROM-Scan routines where other BIOS modules are found, these
modules are shadowed just, like the BIOS, by disabling the decodes
after copying the BIOS module contents.

As previously stated, the PCI specification specifically requires that
all BIOS modules execute from RAM, not PROM. This allows interrupts
to be shared (another specification). Hooking of a shared interrupt
requires saving the previous vector somewhere. It can't be saved in
PROM so it must be saved in its code/data space. Therefore it must be
writable, hence RAM.

Cheers,
Dick Johnson

Penguin : Linux version 2.3.41 on an i686 machine (800.63 BogoMips).

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Jun 07 2000 - 21:00:28 EST