aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2013-03-08 19:33:39 -0500
committerKevin O'Connor <kevin@koconnor.net>2013-03-08 19:55:26 -0500
commitcdbac7f7f105a30d548dba4af41f7d29e2beaa69 (patch)
tree91e564ec1e5a6372f771adf0ae7d85803efb610c
parent96d4c438656b01927a2cb97d395f5e286d6195cf (diff)
downloadseabios-cdbac7f7f105a30d548dba4af41f7d29e2beaa69.tar.gz
smm: Don't use PCIDevices list in smm_setup().
The smm_setup() call is invoked from resume. The PCIDevices list is only valid during POST. Cache the necessary PCI BDF ids so that PCIDevices isn't needed. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/paravirt.c1
-rw-r--r--src/smm.c66
-rw-r--r--src/util.h1
3 files changed, 37 insertions, 31 deletions
diff --git a/src/paravirt.c b/src/paravirt.c
index f061039..4a26c6e 100644
--- a/src/paravirt.c
+++ b/src/paravirt.c
@@ -106,6 +106,7 @@ qemu_platform_setup(void)
// Initialize pci
pci_setup();
+ smm_device_setup();
smm_setup();
// Initialize mtrr and smp
diff --git a/src/smm.c b/src/smm.c
index 490a626..a424a29 100644
--- a/src/smm.c
+++ b/src/smm.c
@@ -6,6 +6,7 @@
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "pci.h" // pci_config_writel
+#include "pci_regs.h" // PCI_DEVICE_ID
#include "util.h" // wbinvd
#include "config.h" // CONFIG_*
#include "ioport.h" // outb
@@ -111,46 +112,30 @@ smm_relocate_and_restore(void)
#define PIIX_APMC_EN (1 << 25)
// This code is hardcoded for PIIX4 Power Management device.
-static void piix4_apmc_smm_setup(struct pci_device *pci, void *arg)
+static void piix4_apmc_smm_setup(int isabdf, int i440_bdf)
{
- struct pci_device *i440_pci = pci_find_device(PCI_VENDOR_ID_INTEL
- , PCI_DEVICE_ID_INTEL_82441);
- if (!i440_pci)
- return;
-
/* check if SMM init is already done */
- u32 value = pci_config_readl(pci->bdf, PIIX_DEVACTB);
+ u32 value = pci_config_readl(isabdf, PIIX_DEVACTB);
if (value & PIIX_APMC_EN)
return;
/* enable the SMM memory window */
- pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x48);
+ pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x48);
smm_save_and_copy();
/* enable SMI generation when writing to the APMC register */
- pci_config_writel(pci->bdf, PIIX_DEVACTB, value | PIIX_APMC_EN);
+ pci_config_writel(isabdf, PIIX_DEVACTB, value | PIIX_APMC_EN);
smm_relocate_and_restore();
/* close the SMM memory window and enable normal SMM */
- pci_config_writeb(i440_pci->bdf, I440FX_SMRAM, 0x02 | 0x08);
+ pci_config_writeb(i440_bdf, I440FX_SMRAM, 0x02 | 0x08);
}
/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */
-void ich9_lpc_apmc_smm_setup(struct pci_device *dev, void *arg)
+void ich9_lpc_apmc_smm_setup(int isabdf, int mch_bdf)
{
- struct pci_device *mch_dev;
- int mch_bdf;
-
- // This code is hardcoded for Q35 Power Management device.
- mch_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_Q35_MCH);
- mch_bdf = mch_dev->bdf;
-
- if (mch_bdf < 0)
- return;
-
/* check if SMM init is already done */
u32 value = inl(PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN);
if (value & ICH9_PMIO_SMI_EN_APMC_EN)
@@ -171,21 +156,40 @@ void ich9_lpc_apmc_smm_setup(struct pci_device *dev, void *arg)
pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x08);
}
-static const struct pci_device_id smm_init_tbl[] = {
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
- piix4_apmc_smm_setup),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC,
- ich9_lpc_apmc_smm_setup),
+static int SMMISADeviceBDF = -1, SMMPMDeviceBDF = -1;
+
+void
+smm_device_setup(void)
+{
+ if (!CONFIG_USE_SMM)
+ return;
- PCI_DEVICE_END,
-};
+ struct pci_device *isapci, *pmpci;
+ isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3);
+ pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
+ if (isapci && pmpci) {
+ SMMISADeviceBDF = isapci->bdf;
+ SMMPMDeviceBDF = pmpci->bdf;
+ return;
+ }
+ isapci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC);
+ pmpci = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH);
+ if (isapci && pmpci) {
+ SMMISADeviceBDF = isapci->bdf;
+ SMMPMDeviceBDF = pmpci->bdf;
+ }
+}
void
smm_setup(void)
{
- if (!CONFIG_USE_SMM)
+ if (!CONFIG_USE_SMM || SMMISADeviceBDF < 0)
return;
dprintf(3, "init smm\n");
- pci_find_init_device(smm_init_tbl, NULL);
+ u16 device = pci_config_readw(SMMISADeviceBDF, PCI_DEVICE_ID);
+ if (device == PCI_DEVICE_ID_INTEL_82371AB_3)
+ piix4_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF);
+ else
+ ich9_lpc_apmc_smm_setup(SMMISADeviceBDF, SMMPMDeviceBDF);
}
diff --git a/src/util.h b/src/util.h
index 306a8bf..af029fc 100644
--- a/src/util.h
+++ b/src/util.h
@@ -314,6 +314,7 @@ extern const u8 pci_irqs[4];
void pci_setup(void);
// smm.c
+void smm_device_setup(void);
void smm_setup(void);
// smp.c