[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] (PAM stuff) reset doesn't work on OVMF + SeaBIOS CSM
From: |
Laszlo Ersek |
Subject: |
[Qemu-devel] (PAM stuff) reset doesn't work on OVMF + SeaBIOS CSM |
Date: |
Thu, 14 Feb 2013 21:41:03 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130108 Thunderbird/10.0.12 |
Hi,
I noticed that under OVMF + SeaBIOS CSM + your related patches for both,
reset requested by the guest doesn't work as expected. The behavior is
an infinite loop, with the following debug fragment repeated by the
CSM-ized SeaBIOS:
In resume (status=0)
In 32bit resume
Attempting a hard reboot
i8042_wait_write
The corresponding call chain seems to be:
reset_vector() [src/romlayout.S]
entry_post()
entry_resume()
handle_resume() [src/resume.c]
prints "In resume"
handle_resume32()
prints "In 32bit resume"
tryReboot()
prints "Attempting a hard reboot"
i8042_reboot() [src/ps2port.c]
i8042_wait_write()
prints "i8042_wait_write"
outb(0xfe, PORT_PS2_STATUS)
(The entry_post -> entry_resume jump occurs because HaveRunPost has been
set to 1 by csm_maininit() --> interface_init() --> ivt_init().)
At this point kbd_write_command() in qemu-kvm's "hw/pckbd.c", case
KBD_CCMD_RESET, requests a system reset. Soon the reset handlers run,
among them cpu_reset() (which was registered by
pc_init1() [hw/pc.c]
pc_new_cpu()
). cpu_reset() [target-i386/helper.c] sets CS:IP to f000:fff0, which is
the exact address of... reset_vector() in SeaBIOS.
Of course OVMF should be re-run instead of SeaBIOS. 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 (below a limit of
course):
pc_init1() [hw/pc.c]
rom_add_file_fixed() []
open() / read() /close()
rom_insert()
some calls to inform KVM
I think when OVMF runs SeaBIOS as CSM, OVMF shadows the original ROM
(containing the OVMF binary itself) with the SeaBIOS code + static data
(I'm peeking at
<http://en.wikipedia.org/wiki/Shadow_RAM#Shadow_RAM>...). This should
render SeaBIOS visible / executable / writeable in the top 16-bit
segment, and leave OVMF in a permanently unusable state (in RAM at least).
My guess at the relevant edk2 function is ShadowAndStartLegacy16()
[IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c]. The
LegacyRegion->UnLock() call should be instrumental (implemented in
"OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c" with PAM (Programmable
Attribute Map) registers?)
Hence I *presume* qemu-kvm should un-shadow the ROM at reset time (ie.
make OVMF visible again as ROM) not later than allowing the VCPU to
continue at f000:fff0 again. Normally that address should be occupied by
OVMF code from (I guess) "UefiCpuPkg/ResetVector/Vtf0".
Does this make any sense? Is qemu-kvm forgetting to reset the PAMs? Or
would that be the responsibility of tryReboot() in SeaBIOS?
... Aah! qemu_prep_reset() in SeaBIOS [src/shadow.c] goes like:
void
qemu_prep_reset(void)
{
if (!CONFIG_QEMU)
return;
// QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
// reset, so do that manually before invoking a hard reset.
make_bios_writable();
extern u8 code32flat_start[], code32flat_end[];
memcpy(code32flat_start, code32flat_start + BIOS_SRC_OFFSET
, code32flat_end - code32flat_start);
if (HaveRunPost)
// Memory copy failed to work - try to halt the machine.
apm_shutdown();
}
and this function is actually called inside the infinite loop (I ignored
it before):
tryReboot()
prints "Attempting a hard reboot"
qemu_prep_reset() [src/shadow.c] <-------------- here
i8042_reboot() [src/ps2port.c]
i8042_wait_write()
prints "i8042_wait_write"
outb(0xfe, PORT_PS2_STATUS)
but of course it doesn't do anything with CONFIG_CSM (since that implies
!CONFIG_QEMU). What's more, qemu_prep_reset() and
make_bios_writable_intel() seem to exploit SeaBIOS characteristics
(code32flat_*, HaveRunPost etc.) that probably make no sense when the
data being restored is a different (= OVMF) image.
Can we dumb down ^W^W generalize this code? :) Or maybe should qemu
introduce a reset handler for PAMs?
(I realize I've been reading all the time about PAMs, in the "Writeable
files in fw_cfg" thread, in the discussion about unlocking the 0xE0000
segment for stack purposes... Didn't understand a single word before,
sorry. Downloaded my copy of the i440FX spec just today; I finally have
a remote idea how shadowing / write-protecting works.)
Thanks!
Laszlo
- [Qemu-devel] (PAM stuff) reset doesn't work on OVMF + SeaBIOS CSM,
Laszlo Ersek <=
Re: [Qemu-devel] (PAM stuff) reset doesn't work on OVMF + SeaBIOS CSM, David Woodhouse, 2013/02/14