resume: restore piix pm config registers after resume
On resume, the OS queries the power management event that
caused it. In order to complete this task, it executes some
reads to the piix pm io space. This all happens before the
OS has a chance to restore the PCI config space for devices,
so it is bios's responsibility to make sure the pm IO space
is configured correctly. (During suspend, the piix pm
configuration space is lost).
Note: For 'ordinary' pci devices the config space is
saved by the OS on sleep and restored on resume.
Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index a24b8ff..11c92ae 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -230,10 +230,8 @@
pci_set_io_region_addr(pci, 0, 0x80800000, 0);
}
-/* PIIX4 Power Management device (for ACPI) */
-static void piix4_pm_setup(struct pci_device *pci, void *arg)
+static void piix4_pm_config_setup(u16 bdf)
{
- u16 bdf = pci->bdf;
// acpi sci is hardwired to 9
pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
@@ -241,6 +239,15 @@
pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
+}
+
+static int PiixPmBDF = -1;
+
+/* PIIX4 Power Management device (for ACPI) */
+static void piix4_pm_setup(struct pci_device *pci, void *arg)
+{
+ PiixPmBDF = pci->bdf;
+ piix4_pm_config_setup(pci->bdf);
acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04;
pmtimer_setup(PORT_ACPI_PM_BASE + 0x08);
@@ -295,6 +302,17 @@
PCI_DEVICE_END,
};
+void pci_resume(void)
+{
+ if (!CONFIG_QEMU) {
+ return;
+ }
+
+ if (PiixPmBDF >= 0) {
+ piix4_pm_config_setup(PiixPmBDF);
+ }
+}
+
static void pci_bios_init_device(struct pci_device *pci)
{
u16 bdf = pci->bdf;
diff --git a/src/resume.c b/src/resume.c
index d69429c..9ad2e4f 100644
--- a/src/resume.c
+++ b/src/resume.c
@@ -101,6 +101,8 @@
pic_setup();
smm_setup();
+ pci_resume();
+
s3_resume_vga();
make_bios_readonly();
diff --git a/src/util.h b/src/util.h
index 1b7d525..b8acbfa 100644
--- a/src/util.h
+++ b/src/util.h
@@ -99,6 +99,7 @@
// fw/pciinit.c
extern const u8 pci_irqs[4];
void pci_setup(void);
+void pci_resume(void);
// fw/pirtable.c
extern struct pir_header *PirAddr;