resume: Don't attempt to use generic reboot mechanisms on QEMU
On QEMU it's necessary to manually reset the BIOS memory region between 0xc0000-0x100000 on a reboot. After this manual memory reset is completed, it's not valid to use the generic reset mechanisms. Rename qemu_prep_reset() to qemu_reboot() and change the function to immediately reboot after the code memcpy. This fixes a bug that could cause code corruption on reboots - calling the udelay() function (as invoked by i8042_reboot and/or pci_reboot) was not valid after the BIOS was memcpy'd. Reported-by: "Dr. David Alan Gilbert" <dgilbert@redhat.com> Tested-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
1415d46dc8
commit
c68aff57ce
|
@ -167,7 +167,7 @@ make_bios_readonly(void)
|
|||
}
|
||||
|
||||
void
|
||||
qemu_prep_reset(void)
|
||||
qemu_reboot(void)
|
||||
{
|
||||
if (!CONFIG_QEMU || runningOnXen())
|
||||
return;
|
||||
|
@ -187,4 +187,16 @@ qemu_prep_reset(void)
|
|||
memcpy(hrp + 4, hrp + 4 + BIOS_SRC_OFFSET, cend - (hrp + 4));
|
||||
barrier();
|
||||
HaveRunPost = 0;
|
||||
barrier();
|
||||
|
||||
// Request a QEMU system reset. Do the reset in this function as
|
||||
// the BIOS code was overwritten above and not all BIOS
|
||||
// functionality may be available.
|
||||
|
||||
// Attempt PCI style reset
|
||||
outb(0x02, PORT_PCI_REBOOT);
|
||||
outb(0x06, PORT_PCI_REBOOT);
|
||||
|
||||
// Next try triple faulting the CPU to force a reset
|
||||
asm volatile("int3");
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "x86.h" // outl
|
||||
|
||||
#define PORT_PCI_CMD 0x0cf8
|
||||
#define PORT_PCI_REBOOT 0x0cf9
|
||||
#define PORT_PCI_DATA 0x0cfc
|
||||
|
||||
void pci_config_writel(u16 bdf, u32 addr, u32 val)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "types.h" // u32
|
||||
|
||||
#define PORT_PCI_REBOOT 0x0cf9
|
||||
|
||||
static inline u8 pci_bdf_to_bus(u16 bdf) {
|
||||
return bdf >> 8;
|
||||
}
|
||||
|
|
|
@ -125,8 +125,8 @@ tryReboot(void)
|
|||
{
|
||||
dprintf(1, "Attempting a hard reboot\n");
|
||||
|
||||
// Setup for reset on qemu.
|
||||
qemu_prep_reset();
|
||||
// Use a QEMU specific reboot on QEMU
|
||||
qemu_reboot();
|
||||
|
||||
// Reboot using ACPI RESET_REG
|
||||
acpi_reboot();
|
||||
|
|
|
@ -123,7 +123,7 @@ void pirtable_setup(void);
|
|||
// fw/shadow.c
|
||||
void make_bios_writable(void);
|
||||
void make_bios_readonly(void);
|
||||
void qemu_prep_reset(void);
|
||||
void qemu_reboot(void);
|
||||
|
||||
// fw/smbios.c
|
||||
void smbios_legacy_setup(void);
|
||||
|
|
Loading…
Reference in New Issue