On Tue, Feb 14, 2017 at 07:52:01PM +0100, Laszlo Ersek wrote:
On 02/14/17 19:43, Kevin O'Connor wrote:
On Tue, Feb 14, 2017 at 07:04:05PM +0100, Laszlo Ersek wrote:
On 02/14/17 18:16, Kevin O'Connor wrote:
Also, the PAM registers on real hardware support a mode where reads to 0xf0000 return the pristine copy of the bios while writes update memory. I didn't think there was any interest in implementing that on QEMU (nor do I think it would be particularly helpful to have).
Hmmm, I thought this was implemented with the four modes visible in init_pam() and switched by pam_update(), in "hw/pci-host/pam.c".
Based on the remaining "XXX" comments though, and the wording of commit 175f099b30d47 ("pam: partly fix write-only mode"), it seems that the emulation is not complete just yet?...
Perhaps this helps Dave identify what should be fixed in QEMU...
I don't think anything in QEMU needs to be "fixed" - the bug is definitely in SeaBIOS. The QEMU pam stuff is definitely quirky, but even if we updated qemu we'd still have to fix seabios for old versions of qemu.
Just for historical perspective - the reason I think qemu didn't implement the pam "read from rom and write to memory" mode is that I don't think there's a good way to emulate that with page tables (and the range needs to be executable so just making it all device memory isn't practical). Even if it were implemented, though, I doubt it would help much.
There are two questions here, AIUI: (1) resetting the PAM config on qemu system reset, (2) implementing all four PAM modes in QEMU, faithfully to phys hw.
I agree that item (2) is not important.
However, in order to fix SeaBIOS, item (1) should be fixed in QEMU, shouldn't it? You wrote,
The root of the problem is that QEMU does not reset the f-segment on a reboot signal and so SeaBIOS must manually reset that memory. [...]
Sorry, I didn't word that paragraph well. I was trying to give context for why the seabios code was memcpy'ing over itself.
If item (1) is fixed in QEMU, then the above "root cause" goes away, and the workaround in SeaBIOS can be conditionalized. Am I wrong?
I'm not sure. If I recall correctly, there are different resets on the x86 - some only reset the cpu and some do a "full machine reset". SeaBIOS attempts a variety of different reset mechanisms to reboot and I'm not sure which are supposed to do the full reset. If seabios does a "reset cpu" mechanism before a "reset machine" mechanism, then qemu resetting the pam may not help.
Thinking about this further, I think the real problem is that after seabios copies over itself it goes back into its generic reboot handling code. The udelay() is actually fine on real hardware - it's just not okay after seabios has memcpy'd itself. So, I think if seabios immediately did a reboot after the memcpy this problem would go away. Something like the patch below.
What's the best way to force a reboot on QEMU? The mechanism really should reset all cpus in a multi-cpu machine, ideally it would work on different machine types (piix4, q35, isapc, etc.), and ideally it would reset the hardware as well.
-Kevin
--- a/src/fw/shadow.c +++ b/src/fw/shadow.c @@ -187,4 +187,8 @@ qemu_prep_reset(void) memcpy(hrp + 4, hrp + 4 + BIOS_SRC_OFFSET, cend - (hrp + 4)); barrier(); HaveRunPost = 0; + barrier(); + + // Force QEMU reboot + asm volatile("int3"); }