qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [SeaBIOS] [edk2] (PAM stuff) reset doesn't work on OVMF


From: Laszlo Ersek
Subject: Re: [Qemu-devel] [SeaBIOS] [edk2] (PAM stuff) reset doesn't work on OVMF + SeaBIOS CSM
Date: Thu, 14 Feb 2013 23:41:28 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130108 Thunderbird/10.0.12

On 02/14/13 22:27, David Woodhouse wrote:
> On Thu, 2013-02-14 at 22:14 +0100, Laszlo Ersek wrote:
>> On 02/14/13 21:54, H. Peter Anvin wrote:
>>> On 02/14/2013 12:41 PM, Laszlo Ersek wrote:
>>>>
>>>> ). cpu_reset() [target-i386/helper.c] sets CS:IP to f000:fff0, which is
>>>> the exact address of... reset_vector() in SeaBIOS.
>>>>
>>>
>>> This would be a bug, but it isn't quite true.
>>>
>>> If you look at x86_cpu_reset() you will note that it sets the code
>>> segment base to 0xffff0000, not 0xf0000 as one could expect from the
>>> above.  This is also true of a physical x86.
>>>
>>> As such, the *real* reset vector is at 0xfffffff0 as opposed to the
>>> SeaBIOS vector at 0xffff0 -- this is a backwards compatibility vector
>>> which typically just issues a real reset.
>>>
>>> Now, if Qemu doesn't handle the distinction here correctly, that is a bug.
>>
>> I think I was simply wrong :)
> 
> So it *is* jumping to 0xfffffff0 but the memory at that location isn't
> what we expect? Do the PAM registers affect *that* too, or only the
> region from 0xc0000-0xfffff? Surely the contents at 4GiB-δ should be
> unchanged by *anything* we do with the PAM registers?

I meant that my reading of what x86_cpu_reset() [nee cpu_reset()] was
wrong, because the constant that it passes as argument in fact conforms
to what Peter says.

(
Also check the rom_add_file_fixed() call in pc_init1() / qemu:

    ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);

("bios_size" is an "int"). I referred to this in my thread starter as

    When qemu-kvm starts, "OVMF.fd" is installed as ROM, such that the
    last address it occupies is "all-bits-one", independently of its
    size [...]

Namely, the value of (uint32_t)(-bios_size) is

    UINT32_MAX + 1 - bios_size

(the above is meant as a math formula, not as a C expression), hence the
last byte occupied is at UINT32_MAX. In my first post I silently thought
that this value would be truncated to fewer bits somewhere, but
apparently that's not the case.
)

> 
> Or maybe not... after also downloading the i440fx data sheet, I'm even
> more confused. There's some aliasing with... not the region at 1MiB-δ
> but the region at 16MiB-δ:
> 
> (From §4.1 System Address Map):
> 
> 2. High BIOS Area (FFE0_0000h−− FFFF_FFFFh)
>   The top 2 Mbytes of the Extended Memory Region is reserved for System
>   BIOS (High BIOS), extended BIOS for PCI devices, and the A20 alias of
>   the system BIOS. The CPU begins execution from the High BIOS after
>   reset. This region is mapped to the PCI so that the upper subset of
>   this region is aliased to 16 Mbytes minus 256-Kbyte range.

After Peter emphasized that the code segment base was 0xffff0000, I went
back to wikipedia <http://en.wikipedia.org/wiki/Reset_vector>, and
finally managed to parse

    The reset vector for the 80386DX and later x86 processors is
    0xFFFF0, although the value of the CS register at reset is 0xF000
    and the value of the IP register at reset is 0xFFF0. In actuality,
    current x86 processors fetch from the physical address 0xFFFFFFF0.
    This is due to a hidden base address portion of the CS register in
    real mode which defaults to 0xFFFF0000 after reset.

This is again consistent with the 0xfffffff0 vector pointed out by Peter
(= 0xFFFF0000 + 0xFFF0), but I don't know how to match it to the data
sheet language...

Thanks
Laszlo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]