diff options
-rw-r--r-- | src/soc/intel/apollolake/cpu.c | 2 | ||||
-rw-r--r-- | src/soc/intel/apollolake/smihandler.c | 10 | ||||
-rw-r--r-- | src/soc/intel/cannonlake/cpu.c | 3 | ||||
-rw-r--r-- | src/soc/intel/cannonlake/smihandler.c | 10 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/smihandler.h | 11 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/smm.h | 2 | ||||
-rw-r--r-- | src/soc/intel/common/block/smm/smihandler.c | 42 | ||||
-rw-r--r-- | src/soc/intel/common/block/smm/smm.c | 4 |
8 files changed, 76 insertions, 8 deletions
diff --git a/src/soc/intel/apollolake/cpu.c b/src/soc/intel/apollolake/cpu.c index 96c37f1518..d093acc06a 100644 --- a/src/soc/intel/apollolake/cpu.c +++ b/src/soc/intel/apollolake/cpu.c @@ -238,7 +238,7 @@ static void relocation_handler(int cpu, uintptr_t curr_smbase, static void post_mp_init(void) { - smm_southbridge_enable(); + smm_southbridge_enable(PWRBTN_EN | GBL_EN); if (IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_SGX)) mp_run_on_all_cpus(sgx_configure, 2000); diff --git a/src/soc/intel/apollolake/smihandler.c b/src/soc/intel/apollolake/smihandler.c index 37d63a1ba5..f42ae012dc 100644 --- a/src/soc/intel/apollolake/smihandler.c +++ b/src/soc/intel/apollolake/smihandler.c @@ -34,6 +34,16 @@ const struct smm_save_state_ops *get_smm_save_state_ops(void) return &em64t100_smm_ops; } +/* SMI handlers that should be serviced in SCI mode too. */ +uint32_t smi_handler_get_sci_mask(void) +{ + uint32_t sci_mask = + SMI_HANDLER_SCI_EN(APM_SMI_STS) | + SMI_HANDLER_SCI_EN(SLP_SMI_STS); + + return sci_mask; +} + const smi_handler_t southbridge_smi[32] = { [SLP_SMI_STS] = smihandler_southbridge_sleep, [APM_SMI_STS] = smihandler_southbridge_apmc, diff --git a/src/soc/intel/cannonlake/cpu.c b/src/soc/intel/cannonlake/cpu.c index 2dffccb923..728ab9c379 100644 --- a/src/soc/intel/cannonlake/cpu.c +++ b/src/soc/intel/cannonlake/cpu.c @@ -26,6 +26,7 @@ #include <soc/cpu.h> #include <soc/msr.h> #include <soc/pci_devs.h> +#include <soc/pm.h> #include <soc/smm.h> static void soc_fsp_load(void) @@ -216,7 +217,7 @@ static void post_mp_init(void) * Now that all APs have been relocated as well as the BSP let SMIs * start flowing. */ - smm_southbridge_enable(); + smm_southbridge_enable(PWRBTN_EN | GBL_EN); /* Lock down the SMRAM space. */ smm_lock(); diff --git a/src/soc/intel/cannonlake/smihandler.c b/src/soc/intel/cannonlake/smihandler.c index 0653e9f3a2..8c55ce7892 100644 --- a/src/soc/intel/cannonlake/smihandler.c +++ b/src/soc/intel/cannonlake/smihandler.c @@ -23,6 +23,16 @@ const struct smm_save_state_ops *get_smm_save_state_ops(void) return &em64t101_smm_ops; } +/* SMI handlers that should be serviced in SCI mode too. */ +uint32_t smi_handler_get_sci_mask(void) +{ + uint32_t sci_mask = + SMI_HANDLER_SCI_EN(APM_STS_BIT) | + SMI_HANDLER_SCI_EN(SMI_ON_SLP_EN_STS_BIT); + + return sci_mask; +} + const smi_handler_t southbridge_smi[SMI_STS_BITS] = { [SMI_ON_SLP_EN_STS_BIT] = smihandler_southbridge_sleep, [APM_STS_BIT] = smihandler_southbridge_apmc, diff --git a/src/soc/intel/common/block/include/intelblocks/smihandler.h b/src/soc/intel/common/block/include/intelblocks/smihandler.h index 5df5552685..f1e3ecf9cb 100644 --- a/src/soc/intel/common/block/include/intelblocks/smihandler.h +++ b/src/soc/intel/common/block/include/intelblocks/smihandler.h @@ -60,6 +60,11 @@ const struct smm_save_state_ops *get_smm_save_state_ops(void); */ extern const smi_handler_t southbridge_smi[32]; +#define SMI_HANDLER_SCI_EN(__bit) (1 << (__bit)) + +/* SMI handlers that should be serviced in SCI mode too. */ +uint32_t smi_handler_get_sci_mask(void); + /* * This function should be implemented in SOC specific code to handle * the SMI event on SLP_EN. The default functionality is provided in @@ -145,6 +150,12 @@ void smihandler_southbridge_espi( int smihandler_disable_busmaster(device_t dev); /* + * SoC needs to implement the mechanism to know if an illegal attempt + * has been made to write to the BIOS area. + */ +void smihandler_check_illegal_access(uint32_t tco_sts); + +/* * Returns gnvs pointer within SMM context */ struct global_nvs_t *smm_get_gnvs(void); diff --git a/src/soc/intel/common/block/include/intelblocks/smm.h b/src/soc/intel/common/block/include/intelblocks/smm.h index 84f34a5a7b..f560f24e2b 100644 --- a/src/soc/intel/common/block/include/intelblocks/smm.h +++ b/src/soc/intel/common/block/include/intelblocks/smm.h @@ -29,7 +29,7 @@ * SMIs. */ void smm_southbridge_clear_state(void); -void smm_southbridge_enable(void); +void smm_southbridge_enable(uint16_t pm1_events); /* API to get SMM region start and size based on Host Bridge register */ void smm_region_info(void **start, size_t *size); diff --git a/src/soc/intel/common/block/smm/smihandler.c b/src/soc/intel/common/block/smm/smihandler.c index 7821dbaddc..9a4ee7cf96 100644 --- a/src/soc/intel/common/block/smm/smihandler.c +++ b/src/soc/intel/common/block/smm/smihandler.c @@ -21,6 +21,7 @@ #include <cpu/x86/smm.h> #include <device/pci_def.h> #include <elog.h> +#include <intelblocks/fast_spi.h> #include <intelblocks/pmclib.h> #include <intelblocks/smihandler.h> #include <intelblocks/uart.h> @@ -35,11 +36,28 @@ /* GNVS needs to be set by coreboot initiating a software SMI. */ static struct global_nvs_t *gnvs; +/* SoC overrides. */ + __attribute__((weak)) int smihandler_disable_busmaster(device_t dev) { return 1; } +/* SMI handlers that should be serviced in SCI mode too. */ +__attribute__((weak)) uint32_t smi_handler_get_sci_mask(void) +{ + return 0; /* No valid SCI mask for SMI handler */ +} + +/* + * Needs to implement the mechanism to know if an illegal attempt + * has been made to write to the BIOS area. + */ +__attribute__((weak)) void smihandler_check_illegal_access(uint32_t tco_sts) +{ + return; +} + static void *find_save_state(const struct smm_save_state_ops *save_state_ops, int cmd) { @@ -175,6 +193,8 @@ void smihandler_southbridge_sleep( /* Disable all GPE */ pmc_disable_all_gpe(); + /* Set which state system will be after power reapplied */ + pmc_soc_restore_power_failure(); /* also iterates over all bridges on bus 0 */ busmaster_disable_on_bus(0); break; @@ -201,8 +221,7 @@ void smihandler_southbridge_sleep( * the line above. However, if we entered sleep state S1 and wake * up again, we will continue to execute code in this function. */ - reg32 = inl(ACPI_BASE_ADDRESS + PM1_CNT); - if (reg32 & SCI_EN) { + if (pmc_read_pm1_control() & SCI_EN) { /* The OS is not an ACPI OS, so we set the state to S0 */ pmc_disable_pm1_control(SLP_EN | SLP_TYP); } @@ -240,6 +259,9 @@ static void finalize(void) } finalize_done = 1; + if (IS_ENABLED(CONFIG_SPI_FLASH_SMM)) + /* Re-init SPI driver to handle locked BAR */ + fast_spi_init(); } void smihandler_southbridge_apmc( @@ -308,12 +330,13 @@ void smihandler_southbridge_pm1( const struct smm_save_state_ops *save_state_ops) { uint16_t pm1_sts = pmc_clear_pm1_status(); + u16 pm1_en = pmc_read_pm1_enable(); /* * While OSPM is not active, poweroff immediately * on a power button event. */ - if (pm1_sts & PWRBTN_STS) { + if ((pm1_sts & PWRBTN_STS) && (pm1_en & PWRBTN_EN)) { /* power button pressed */ if (IS_ENABLED(CONFIG_ELOG_GSMI)) elog_add_event(ELOG_TYPE_POWER_BUTTON); @@ -337,6 +360,8 @@ void smihandler_southbridge_tco( if (!tco_sts) return; + smihandler_check_illegal_access(tco_sts); + if (tco_sts & TCO_TIMEOUT) { /* TIMEOUT */ /* Handle TCO timeout */ printk(BIOS_DEBUG, "TCO Timeout.\n"); @@ -391,6 +416,17 @@ void southbridge_smi_handler(void) */ smi_sts = pmc_clear_smi_status(); + /* + * In SCI mode, execute only those SMI handlers that have + * declared themselves as available for service in that mode + * using smi_handler_get_sci_mask. + */ + if (pmc_read_pm1_control() & SCI_EN) + smi_sts &= smi_handler_get_sci_mask(); + + if (!smi_sts) + return; + save_state_ops = get_smm_save_state_ops(); /* Call SMI sub handler for each of the status bits */ diff --git a/src/soc/intel/common/block/smm/smm.c b/src/soc/intel/common/block/smm/smm.c index d5f42a76e6..e8c52459a1 100644 --- a/src/soc/intel/common/block/smm/smm.c +++ b/src/soc/intel/common/block/smm/smm.c @@ -38,11 +38,11 @@ void smm_southbridge_clear_state(void) pmc_clear_all_gpe_status(); } -void smm_southbridge_enable(void) +void smm_southbridge_enable(uint16_t pm1_events) { printk(BIOS_DEBUG, "Enabling SMIs.\n"); /* Configure events */ - pmc_enable_pm1(PWRBTN_EN | GBL_EN); + pmc_enable_pm1(pm1_events); pmc_disable_std_gpe(PME_B0_EN); /* |