<p>Subrata Banik would like Brandon Breitenstein to <strong>review</strong> this change.</p><p><a href="https://review.coreboot.org/22826">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">soc/intel/skylake: Make use of common SMM code for SKL<br><br>This patch ensures skylake soc is using common SMM code<br>from intel common block.<br><br>TEST=Build and boot soraka/eve<br><br>Change-Id: I8163dc7e18bb417e8c18a12628988959c128b3df<br>Signed-off-by: Subrata Banik <subrata.banik@intel.com><br>Signed-off-by: Brandon Breitenstein <brandon.breitenstein@intel.com><br>---<br>M src/soc/intel/skylake/Kconfig<br>M src/soc/intel/skylake/Makefile.inc<br>M src/soc/intel/skylake/cpu.c<br>M src/soc/intel/skylake/include/soc/nvs.h<br>M src/soc/intel/skylake/include/soc/pm.h<br>M src/soc/intel/skylake/include/soc/smbus.h<br>M src/soc/intel/skylake/memmap.c<br>M src/soc/intel/skylake/pei_data.c<br>D src/soc/intel/skylake/smi.c<br>M src/soc/intel/skylake/smihandler.c<br>M src/soc/intel/skylake/smmrelocate.c<br>11 files changed, 39 insertions(+), 654 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/22826/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig<br>index 2dbf4a2..156f942 100644<br>--- a/src/soc/intel/skylake/Kconfig<br>+++ b/src/soc/intel/skylake/Kconfig<br>@@ -76,6 +76,8 @@<br> select SOC_INTEL_COMMON_BLOCK_SCS<br> select SOC_INTEL_COMMON_BLOCK_SGX<br> select SOC_INTEL_COMMON_BLOCK_SMBUS<br>+ select SOC_INTEL_COMMON_BLOCK_SMM<br>+ select SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP<br> select SOC_INTEL_COMMON_BLOCK_SPI<br> select SOC_INTEL_COMMON_BLOCK_TIMER<br> select SOC_INTEL_COMMON_BLOCK_UART<br>diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc<br>index 16f8c06..ef95cf7 100644<br>--- a/src/soc/intel/skylake/Makefile.inc<br>+++ b/src/soc/intel/skylake/Makefile.inc<br>@@ -59,7 +59,6 @@<br> ramstage-y += pmutil.c<br> ramstage-$(CONFIG_PLATFORM_USES_FSP2_0) += reset.c<br> ramstage-y += sd.c<br>-ramstage-y += smi.c<br> ramstage-y += smmrelocate.c<br> ramstage-y += spi.c<br> ramstage-y += systemagent.c<br>diff --git a/src/soc/intel/skylake/cpu.c b/src/soc/intel/skylake/cpu.c<br>index ca844df..8f9f5d1 100644<br>--- a/src/soc/intel/skylake/cpu.c<br>+++ b/src/soc/intel/skylake/cpu.c<br>@@ -38,6 +38,7 @@<br> #include <intelblocks/fast_spi.h><br> #include <intelblocks/mp_init.h><br> #include <intelblocks/sgx.h><br>+#include <intelblocks/smm.h><br> #include <pc80/mc146818rtc.h><br> #include <soc/cpu.h><br> #include <soc/msr.h><br>@@ -436,7 +437,7 @@<br> * Now that all APs have been relocated as well as the BSP let SMIs<br> * start flowing.<br> */<br>- southbridge_smm_enable_smi();<br>+ smm_southbridge_enable();<br> <br> /* Lock down the SMRAM space. */<br> #if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)<br>diff --git a/src/soc/intel/skylake/include/soc/nvs.h b/src/soc/intel/skylake/include/soc/nvs.h<br>index da6b2af..8bc4d8d 100644<br>--- a/src/soc/intel/skylake/include/soc/nvs.h<br>+++ b/src/soc/intel/skylake/include/soc/nvs.h<br>@@ -69,9 +69,4 @@<br> } __packed global_nvs_t;<br> check_member(global_nvs_t, chromeos, 0x100);<br> <br>-#if ENV_SMM<br>-/* Used in SMM to find the ACPI GNVS address */<br>-global_nvs_t *smm_get_gnvs(void);<br>-#endif<br>-<br> #endif<br>diff --git a/src/soc/intel/skylake/include/soc/pm.h b/src/soc/intel/skylake/include/soc/pm.h<br>index 0057818..7fdc327 100644<br>--- a/src/soc/intel/skylake/include/soc/pm.h<br>+++ b/src/soc/intel/skylake/include/soc/pm.h<br>@@ -23,6 +23,7 @@<br> #include <soc/gpe.h><br> #include <soc/iomap.h><br> #include <soc/pmc.h><br>+#include <soc/smbus.h><br> <br> /* ACPI_BASE_ADDRESS / PMBASE */<br> <br>@@ -135,6 +136,19 @@<br> <br> #define GBLRST_CAUSE0_THERMTRIP (1 << 5)<br> <br>+/*<br>+ * Enable SMI generation:<br>+ * - on APMC writes (io 0xb2)<br>+ * - on writes to SLP_EN (sleep states)<br>+ * - on writes to GBL_RLS (bios commands)<br>+ * - on eSPI events (does nothing on LPC systems)<br>+ * No SMIs:<br>+ * - on microcontroller writes (io 0x62/0x66)<br>+ * - on TCO events<br>+ */<br>+#define ENABLE_SMI_PARAMS \<br>+ (APMC_EN | SLP_SMI_EN | GBL_SMI_EN | ESPI_SMI_EN | EOS)<br>+<br> #define MAINBOARD_POWER_OFF 0<br> #define MAINBOARD_POWER_ON 1<br> #define MAINBOARD_POWER_KEEP 2<br>diff --git a/src/soc/intel/skylake/include/soc/smbus.h b/src/soc/intel/skylake/include/soc/smbus.h<br>index ad5ae26..aeaf1d9 100644<br>--- a/src/soc/intel/skylake/include/soc/smbus.h<br>+++ b/src/soc/intel/skylake/include/soc/smbus.h<br>@@ -4,7 +4,7 @@<br> * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com><br> * Copyright (C) 2009 coresystems GmbH<br> * Copyright (C) 2014 Google Inc.<br>- * Copyright (C) 2015 Intel Corporation.<br>+ * Copyright (C) 2015-2017 Intel Corporation.<br> *<br> * This program is free software; you can redistribute it and/or modify<br> * it under the terms of the GNU General Public License as published by<br>@@ -29,6 +29,7 @@<br> <br> /* TCO registers and fields live behind TCOBASE I/O bar in SMBus device. */<br> #define TCO1_STS 0x04<br>+#define TCO_TIMEOUT (1 << 3)<br> #define TCO2_STS 0x06<br> #define TCO2_STS_SECOND_TO 0x02<br> #define TCO2_STS_BOOT 0x04<br>diff --git a/src/soc/intel/skylake/memmap.c b/src/soc/intel/skylake/memmap.c<br>index b7be21a..c5dc8ac 100644<br>--- a/src/soc/intel/skylake/memmap.c<br>+++ b/src/soc/intel/skylake/memmap.c<br>@@ -21,11 +21,11 @@<br> #include <console/console.h><br> #include <device/device.h><br> #include <device/pci.h><br>+#include <fsp/memmap.h><br> #include <intelblocks/ebda.h><br> #include <intelblocks/systemagent.h><br> #include <soc/msr.h><br> #include <soc/pci_devs.h><br>-#include <soc/smm.h><br> #include <soc/systemagent.h><br> #include <stdlib.h><br> <br>diff --git a/src/soc/intel/skylake/pei_data.c b/src/soc/intel/skylake/pei_data.c<br>index 43409ef..8b840c9 100644<br>--- a/src/soc/intel/skylake/pei_data.c<br>+++ b/src/soc/intel/skylake/pei_data.c<br>@@ -25,7 +25,6 @@<br> #include <soc/pci_devs.h><br> #include <soc/pei_data.h><br> #include <soc/pei_wrapper.h><br>-#include <soc/smm.h><br> <br> static void ABI_X86 send_to_console(unsigned char b)<br> {<br>diff --git a/src/soc/intel/skylake/smi.c b/src/soc/intel/skylake/smi.c<br>deleted file mode 100644<br>index f11a9d8..0000000<br>--- a/src/soc/intel/skylake/smi.c<br>+++ /dev/null<br>@@ -1,107 +0,0 @@<br>-/*<br>- * This file is part of the coreboot project.<br>- *<br>- * Copyright (C) 2008-2009 coresystems GmbH<br>- * Copyright (C) 2014 Google Inc.<br>- * Copyright (C) 2015 Intel Corporation.<br>- *<br>- * This program is free software; you can redistribute it and/or modify<br>- * it under the terms of the GNU General Public License as published by<br>- * the Free Software Foundation; version 2 of the License.<br>- *<br>- * This program is distributed in the hope that it will be useful,<br>- * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>- * GNU General Public License for more details.<br>- */<br>-<br>-#include <bootstate.h><br>-#include <device/device.h><br>-#include <device/pci.h><br>-#include <console/console.h><br>-#include <arch/io.h><br>-#include <cpu/cpu.h><br>-#include <cpu/x86/cache.h><br>-#include <cpu/x86/smm.h><br>-#include <intelblocks/pmclib.h><br>-#include <string.h><br>-#include <soc/iomap.h><br>-#include <soc/pch.h><br>-#include <soc/pm.h><br>-#include <soc/smm.h><br>-<br>-void southbridge_smm_clear_state(void)<br>-{<br>- u32 smi_en;<br>-<br>- printk(BIOS_DEBUG, "Initializing Southbridge SMI...");<br>- printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", ACPI_BASE_ADDRESS);<br>-<br>- smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);<br>- if (smi_en & APMC_EN) {<br>- printk(BIOS_INFO, "SMI# handler already enabled?\n");<br>- return;<br>- }<br>-<br>- printk(BIOS_DEBUG, "\n");<br>-<br>- /* Dump and clear status registers */<br>- pmc_clear_smi_status();<br>- pmc_clear_pm1_status();<br>- pmc_clear_tco_status();<br>- pmc_clear_all_gpe_status();<br>-}<br>-<br>-void southbridge_smm_enable_smi(void)<br>-{<br>- printk(BIOS_DEBUG, "Enabling SMIs.\n");<br>- /* Configure events */<br>- pmc_enable_pm1(GBL_EN);<br>- pmc_disable_std_gpe(PME_B0_EN);<br>-<br>- /*<br>- * Enable SMI generation:<br>- * - on APMC writes (io 0xb2)<br>- * - on writes to SLP_EN (sleep states)<br>- * - on writes to GBL_RLS (bios commands)<br>- * - on eSPI events (does nothing on LPC systems)<br>- * No SMIs:<br>- * - on microcontroller writes (io 0x62/0x66)<br>- * - on TCO events<br>- */<br>- pmc_enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | ESPI_SMI_EN | EOS);<br>-}<br>-<br>-void smm_setup_structures(void *gnvs, void *tcg, void *smi1)<br>-{<br>- /*<br>- * Issue SMI to set the gnvs pointer in SMM.<br>- * tcg and smi1 are unused.<br>- *<br>- * EAX = APM_CNT_GNVS_UPDATE<br>- * EBX = gnvs pointer<br>- * EDX = APM_CNT<br>- */<br>- asm volatile (<br>- "outb %%al, %%dx\n\t"<br>- : /* ignore result */<br>- : "a" (APM_CNT_GNVS_UPDATE),<br>- "b" ((u32)gnvs),<br>- "d" (APM_CNT)<br>- );<br>-}<br>-<br>-static void pm1_enable_pwrbtn_smi(void *unused)<br>-{<br>- /*<br>- * Enable power button SMI only before jumping to payload. This ensures<br>- * that:<br>- * 1. Power button SMI is enabled only after coreboot is done.<br>- * 2. On resume path, power button SMI is not enabled and thus avoids<br>- * any shutdowns because of power button presses due to power button<br>- * press in resume path.<br>- */<br>- pmc_update_pm1_enable(PWRBTN_EN);<br>-}<br>-<br>-BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, pm1_enable_pwrbtn_smi, NULL);<br>diff --git a/src/soc/intel/skylake/smihandler.c b/src/soc/intel/skylake/smihandler.c<br>index 211432c..f438d4e 100644<br>--- a/src/soc/intel/skylake/smihandler.c<br>+++ b/src/soc/intel/skylake/smihandler.c<br>@@ -3,7 +3,7 @@<br> *<br> * Copyright (C) 2008-2009 coresystems GmbH<br> * Copyright (C) 2014 Google Inc.<br>- * Copyright (C) 2015 Intel Corporation.<br>+ * Copyright (C) 2015-2017 Intel Corporation.<br> *<br> * This program is free software; you can redistribute it and/or modify<br> * it under the terms of the GNU General Public License as published by<br>@@ -15,543 +15,23 @@<br> * GNU General Public License for more details.<br> */<br> <br>-#include <arch/hlt.h><br>-#include <arch/io.h><br>-#include <console/console.h><br>-#include <cpu/x86/cache.h><br>-#include <cpu/x86/smm.h><br>-#include <device/pci_def.h><br>-#include <elog.h><br>-#include <intelblocks/fast_spi.h><br>-#include <intelblocks/pcr.h><br>-#include <intelblocks/uart.h><br>-#include <intelblocks/pmclib.h><br>-#include <delay.h><br>-#include <device/pci_def.h><br>-#include <elog.h><br>-#include <pc80/mc146818rtc.h><br>-#include <spi-generic.h><br>-#include <soc/iomap.h><br>-#include <soc/nvs.h><br>-#include <soc/pci_devs.h><br>-#include <soc/pch.h><br>-#include <soc/pcr_ids.h><br> #include <soc/pm.h><br>-#include <soc/pmc.h><br>-#include <soc/smm.h><br>-#include <types.h><br>+#include <intelblocks/smihandler.h><br> <br>-/* IO Trap PCRs */<br>-/* Trap status Register */<br>-#define PCR_PSTH_TRPST 0x1E00<br>-/* Trapped cycle */<br>-#define PCR_PSTH_TRPC 0x1E10<br>-/* Trapped write data */<br>-#define PCR_PSTH_TRPD 0x1E18<br>-<br>-static u8 smm_initialized = 0;<br>-<br>-/*<br>- * GNVS needs to be updated by an 0xEA PM Trap (B2) after it has been located<br>- * by coreboot.<br>- */<br>-static global_nvs_t *gnvs;<br>-global_nvs_t *smm_get_gnvs(void)<br>+const struct smm_save_state_ops *get_smm_save_state_ops(void)<br> {<br>- return gnvs;<br>+ return &em64t101_smm_ops;<br> }<br> <br>-int southbridge_io_trap_handler(int smif)<br>-{<br>- switch (smif) {<br>- case 0x32:<br>- printk(BIOS_DEBUG, "OS Init\n");<br>- /*<br>- * gnvs->smif:<br>- * - On success, the IO Trap Handler returns 0<br>- * - On failure, the IO Trap Handler returns a value != 0<br>- */<br>- gnvs->smif = 0;<br>- return 1; /* IO trap handled */<br>- }<br>-<br>- /* Not handled */<br>- return 0;<br>-}<br>-<br>-/* Set the EOS bit */<br>-void southbridge_smi_set_eos(void)<br>-{<br>- pmc_enable_smi(EOS);<br>-}<br>-<br>-static void busmaster_disable_on_bus(int bus)<br>-{<br>- int slot, func;<br>- unsigned int val;<br>- unsigned char hdr;<br>-<br>- for (slot = 0; slot < 0x20; slot++) {<br>- for (func = 0; func < 8; func++) {<br>- u32 reg32;<br>- device_t dev = PCI_DEV(bus, slot, func);<br>-<br>- val = pci_read_config32(dev, PCI_VENDOR_ID);<br>-<br>- if (val == 0xffffffff || val == 0x00000000 ||<br>- val == 0x0000ffff || val == 0xffff0000)<br>- continue;<br>-<br>- /* Disable Bus Mastering for this one device */<br>- reg32 = pci_read_config32(dev, PCI_COMMAND);<br>- reg32 &= ~PCI_COMMAND_MASTER;<br>- pci_write_config32(dev, PCI_COMMAND, reg32);<br>-<br>- /* If this is a bridge, then follow it. */<br>- hdr = pci_read_config8(dev, PCI_HEADER_TYPE);<br>- hdr &= 0x7f;<br>- if (hdr == PCI_HEADER_TYPE_BRIDGE ||<br>- hdr == PCI_HEADER_TYPE_CARDBUS) {<br>- unsigned int buses;<br>- buses = pci_read_config32(dev, PCI_PRIMARY_BUS);<br>- busmaster_disable_on_bus((buses >> 8) & 0xff);<br>- }<br>- }<br>- }<br>-}<br>-<br>-<br>-static void southbridge_smi_sleep(void)<br>-{<br>- u8 reg8;<br>- u32 reg32;<br>- u8 slp_typ;<br>- u8 s5pwr = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;<br>-<br>- /* save and recover RTC port values */<br>- u8 tmp70, tmp72;<br>- tmp70 = inb(0x70);<br>- tmp72 = inb(0x72);<br>- get_option(&s5pwr, "power_on_after_fail");<br>- outb(tmp70, 0x70);<br>- outb(tmp72, 0x72);<br>-<br>- /* First, disable further SMIs */<br>- pmc_disable_smi(SLP_SMI_EN);<br>-<br>- /* Figure out SLP_TYP */<br>- reg32 = pmc_read_pm1_control();<br>- printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);<br>- slp_typ = acpi_sleep_from_pm1(reg32);<br>-<br>- /* Do any mainboard sleep handling */<br>- mainboard_smi_sleep(slp_typ);<br>-<br>- if (IS_ENABLED(CONFIG_ELOG_GSMI))<br>- /* Log S3, S4, and S5 entry */<br>- if (slp_typ >= ACPI_S3)<br>- elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ);<br>-<br>- /* Clear pending GPE events */<br>- pmc_clear_all_gpe_status();<br>-<br>- /* Next, do the deed. */<br>- switch (slp_typ) {<br>- case ACPI_S0:<br>- printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");<br>- break;<br>- case ACPI_S1:<br>- printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n");<br>- break;<br>- case ACPI_S3:<br>- printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");<br>-<br>- gnvs->uior = uart_debug_controller_is_initialized();<br>-<br>- /* Invalidate the cache before going to S3 */<br>- wbinvd();<br>- break;<br>- case ACPI_S5:<br>- printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");<br>- /*TODO: cmos_layout.bin need to verify; cause wrong CMOS setup*/<br>- s5pwr = MAINBOARD_POWER_ON;<br>- /* Disable all GPE */<br>- pmc_disable_all_gpe();<br>-<br>- /*<br>- * Always set the flag in case CMOS was changed on runtime. For<br>- * "KEEP", switch to "OFF" - KEEP is software emulated<br>- */<br>- reg8 = pci_read_config8(PCH_DEV_PMC, GEN_PMCON_B);<br>- if (s5pwr == MAINBOARD_POWER_ON)<br>- reg8 &= ~1;<br>- else<br>- reg8 |= 1;<br>- pci_write_config8(PCH_DEV_PMC, GEN_PMCON_B, reg8);<br>-<br>- /* also iterates over all bridges on bus 0 */<br>- busmaster_disable_on_bus(0);<br>- break;<br>- default:<br>- printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");<br>- break;<br>- }<br>-<br>- /*<br>- * Write back to the SLP register to cause the originally intended<br>- * event again. We need to set BIT13 (SLP_EN) though to make the<br>- * sleep happen.<br>- */<br>- pmc_enable_pm1_control(SLP_EN);<br>-<br>- /* Make sure to stop executing code here for S3/S4/S5 */<br>- if (slp_typ >= ACPI_S3)<br>- hlt();<br>-<br>- /*<br>- * In most sleep states, the code flow of this function ends at<br>- * the line above. However, if we entered sleep state S1 and wake<br>- * up again, we will continue to execute code in this function.<br>- */<br>- if (pmc_read_pm1_control() & SCI_EN) {<br>- /* The OS is not an ACPI OS, so we set the state to S0 */<br>- pmc_disable_pm1_control(SLP_EN | SLP_TYP);<br>- }<br>-}<br>-<br>-/*<br>- * Look for Synchronous IO SMI and use save state from that<br>- * core in case we are not running on the same core that<br>- * initiated the IO transaction.<br>- */<br>-static em64t101_smm_state_save_area_t *smi_apmc_find_state_save(u8 cmd)<br>-{<br>- em64t101_smm_state_save_area_t *state;<br>- int node;<br>-<br>- /* Check all nodes looking for the one that issued the IO */<br>- for (node = 0; node < CONFIG_MAX_CPUS; node++) {<br>- state = smm_get_save_state(node);<br>-<br>- /* Check for Synchronous IO (bit0==1) */<br>- if (!(state->io_misc_info & (1 << 0)))<br>- continue;<br>-<br>- /* Make sure it was a write (bit4==0) */<br>- if (state->io_misc_info & (1 << 4))<br>- continue;<br>-<br>- /* Check for APMC IO port */<br>- if (((state->io_misc_info >> 16) & 0xff) != APM_CNT)<br>- continue;<br>-<br>- /* Check AX against the requested command */<br>- if ((state->rax & 0xff) != cmd)<br>- continue;<br>-<br>- return state;<br>- }<br>-<br>- return NULL;<br>-}<br>-<br>-static void southbridge_smi_gsmi(void)<br>-{<br>-#if IS_ENABLED(CONFIG_ELOG_GSMI)<br>- u32 *ret, *param;<br>- u8 sub_command;<br>- em64t101_smm_state_save_area_t *io_smi =<br>- smi_apmc_find_state_save(ELOG_GSMI_APM_CNT);<br>-<br>- if (!io_smi)<br>- return;<br>-<br>- /* Command and return value in EAX */<br>- ret = (u32 *)&io_smi->rax;<br>- sub_command = (u8)(*ret >> 8);<br>-<br>- /* Parameter buffer in EBX */<br>- param = (u32 *)&io_smi->rbx;<br>-<br>- /* drivers/elog/gsmi.c */<br>- *ret = gsmi_exec(sub_command, param);<br>-#endif<br>-}<br>-<br>-static void finalize(void)<br>-{<br>- static int finalize_done;<br>-<br>- if (finalize_done) {<br>- printk(BIOS_DEBUG, "SMM already finalized.\n");<br>- return;<br>- }<br>- finalize_done = 1;<br>-<br>- if (IS_ENABLED(CONFIG_SPI_FLASH_SMM))<br>- /* Re-init SPI driver to handle locked BAR */<br>- fast_spi_init();<br>-}<br>-<br>-static void southbridge_smi_apmc(void)<br>-{<br>- u8 reg8;<br>- em64t101_smm_state_save_area_t *state;<br>-<br>- /* Emulate B2 register as the FADT / Linux expects it */<br>-<br>- reg8 = inb(APM_CNT);<br>- switch (reg8) {<br>- case APM_CNT_PST_CONTROL:<br>- printk(BIOS_DEBUG, "P-state control\n");<br>- break;<br>- case APM_CNT_ACPI_DISABLE:<br>- pmc_disable_pm1_control(SCI_EN);<br>- printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");<br>- break;<br>- case APM_CNT_ACPI_ENABLE:<br>- pmc_enable_pm1_control(SCI_EN);<br>- printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");<br>- break;<br>- case APM_CNT_FINALIZE:<br>- finalize();<br>- break;<br>- case APM_CNT_GNVS_UPDATE:<br>- if (smm_initialized) {<br>- printk(BIOS_DEBUG,<br>- "SMI#: SMM structures already initialized!\n");<br>- return;<br>- }<br>- state = smi_apmc_find_state_save(reg8);<br>- if (state) {<br>- /* EBX in the state save contains the GNVS pointer */<br>- gnvs = (global_nvs_t *)((u32)state->rbx);<br>- smm_initialized = 1;<br>- printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);<br>- }<br>- break;<br>- case ELOG_GSMI_APM_CNT:<br>- if (IS_ENABLED(CONFIG_ELOG_GSMI))<br>- southbridge_smi_gsmi();<br>- break;<br>- }<br>-<br>- mainboard_smi_apmc(reg8);<br>-}<br>-<br>-static void southbridge_smi_pm1(void)<br>-{<br>- u16 pm1_sts = pmc_clear_pm1_status();<br>- u16 pm1_en = pmc_read_pm1_enable();<br>-<br>- /*<br>- * While OSPM is not active, poweroff immediately on a power button<br>- * event.<br>- */<br>- if ((pm1_sts & PWRBTN_STS) && (pm1_en & PWRBTN_EN)) {<br>- /* power button pressed */<br>- if (IS_ENABLED(CONFIG_ELOG_GSMI))<br>- elog_add_event(ELOG_TYPE_POWER_BUTTON);<br>- pmc_disable_pm1_control(-1UL);<br>- pmc_enable_pm1_control(SLP_EN | (SLP_TYP_S5 << 10));<br>- }<br>-}<br>-<br>-static void southbridge_smi_gpe0(void)<br>-{<br>- pmc_clear_all_gpe_status();<br>-}<br>-<br>-void __attribute__((weak))<br>-mainboard_smi_gpi_handler(const struct gpi_status *sts) { }<br>-<br>-static void southbridge_smi_gpi(void)<br>-{<br>- struct gpi_status smi_sts;<br>-<br>- gpi_clear_get_smi_status(&smi_sts);<br>- mainboard_smi_gpi_handler(&smi_sts);<br>-<br>- /* Clear again after mainboard handler */<br>- gpi_clear_get_smi_status(&smi_sts);<br>-}<br>-<br>-void __attribute__((weak)) mainboard_smi_espi_handler(void) { }<br>-static void southbridge_smi_espi(void)<br>-{<br>- mainboard_smi_espi_handler();<br>-}<br>-<br>-static void southbridge_smi_mc(void)<br>-{<br>- u32 reg32 = inl(ACPI_BASE_ADDRESS + SMI_EN);<br>-<br>- /* Are microcontroller SMIs enabled? */<br>- if ((reg32 & MCSMI_EN) == 0)<br>- return;<br>-<br>- printk(BIOS_DEBUG, "Microcontroller SMI.\n");<br>-}<br>-<br>-static void southbridge_smi_tco(void)<br>-{<br>- u32 tco_sts = pmc_clear_tco_status();<br>-<br>- /* Any TCO event? */<br>- if (!tco_sts)<br>- return;<br>-<br>- if (tco_sts & (1 << 8)) { /* BIOSWR */<br>- if (IS_ENABLED(CONFIG_SPI_FLASH_SMM)) {<br>- if (fast_spi_wpd_status()) {<br>- /*<br>- * BWE is RW, so the SMI was caused by a<br>- * write to BWE, not by a write to the BIOS<br>- *<br>- * This is the place where we notice someone<br>- * is trying to tinker with the BIOS. We are<br>- * trying to be nice and just ignore it. A more<br>- * resolute answer would be to power down the<br>- * box.<br>- */<br>- printk(BIOS_DEBUG, "Switching back to RO\n");<br>- fast_spi_enable_wp();<br>- } /* No else for now? */<br>- }<br>- } else if (tco_sts & (1 << 3)) { /* TIMEOUT */<br>- /* Handle TCO timeout */<br>- printk(BIOS_DEBUG, "TCO Timeout.\n");<br>- }<br>-}<br>-<br>-static void southbridge_smi_periodic(void)<br>-{<br>- u32 reg32 = inl(ACPI_BASE_ADDRESS + SMI_EN);<br>-<br>- /* Are periodic SMIs enabled? */<br>- if ((reg32 & PERIODIC_EN) == 0)<br>- return;<br>-<br>- printk(BIOS_DEBUG, "Periodic SMI.\n");<br>-}<br>-<br>-static void southbridge_smi_monitor(void)<br>-{<br>-#define IOTRAP(x) (trap_sts & (1 << x))<br>- u32 trap_cycle;<br>- u32 data, mask = 0;<br>- u8 trap_sts;<br>- int i;<br>- /* TRSR - Trap Status Register */<br>- trap_sts = pcr_read8(PID_PSTH, PCR_PSTH_TRPST);<br>- /* Clear trap(s) in TRSR */<br>- pcr_write8(PID_PSTH, PCR_PSTH_TRPST, trap_sts);<br>-<br>- /* TRPC - Trapped cycle */<br>- trap_cycle = pcr_read32(PID_PSTH, PCR_PSTH_TRPC);<br>- for (i = 16; i < 20; i++) {<br>- if (trap_cycle & (1 << i))<br>- mask |= (0xff << ((i - 16) << 2));<br>- }<br>-<br>-<br>- /* IOTRAP(3) SMI function call */<br>- if (IOTRAP(3)) {<br>- if (gnvs && gnvs->smif)<br>- io_trap_handler(gnvs->smif); /* call function smif */<br>- return;<br>- }<br>-<br>- /*<br>- * IOTRAP(2) currently unused<br>- * IOTRAP(1) currently unused<br>- */<br>-<br>- /* IOTRAP(0) SMIC */<br>- if (IOTRAP(0)) {<br>- if (!(trap_cycle & (1 << 24))) { /* It's a write */<br>- printk(BIOS_DEBUG, "SMI1 command\n");<br>- /* Trapped write data */<br>- data = pcr_read32(PID_PSTH, PCR_PSTH_TRPD);<br>- data &= mask;<br>- }<br>- }<br>-<br>- printk(BIOS_DEBUG, " trapped io address = 0x%x\n",<br>- trap_cycle & 0xfffc);<br>- for (i = 0; i < 4; i++)<br>- if (IOTRAP(i))<br>- printk(BIOS_DEBUG, " TRAP = %d\n", i);<br>- printk(BIOS_DEBUG, " AHBE = %x\n", (trap_cycle >> 16) & 0xf);<br>- printk(BIOS_DEBUG, " MASK = 0x%08x\n", mask);<br>- printk(BIOS_DEBUG, " read/write: %s\n",<br>- (trap_cycle & (1 << 24)) ? "read" : "write");<br>-<br>- if (!(trap_cycle & (1 << 24))) {<br>- /* Write Cycle */<br>- data = pcr_read32(PID_PSTH, PCR_PSTH_TRPD);<br>- printk(BIOS_DEBUG, " iotrap written data = 0x%08x\n", data);<br>- }<br>-#undef IOTRAP<br>-}<br>-<br>-typedef void (*smi_handler_t)(void);<br>-<br>-static smi_handler_t southbridge_smi[SMI_STS_BITS] = {<br>- [SMI_ON_SLP_EN_STS_BIT] = southbridge_smi_sleep,<br>- [APM_STS_BIT] = southbridge_smi_apmc,<br>- [PM1_STS_BIT] = southbridge_smi_pm1,<br>- [GPE0_STS_BIT] = southbridge_smi_gpe0,<br>- [GPIO_STS_BIT] = southbridge_smi_gpi,<br>- [ESPI_SMI_STS_BIT] = southbridge_smi_espi,<br>- [MCSMI_STS_BIT] = southbridge_smi_mc,<br>- [TCO_STS_BIT] = southbridge_smi_tco,<br>- [PERIODIC_STS_BIT] = southbridge_smi_periodic,<br>- [MONITOR_STS_BIT] = southbridge_smi_monitor,<br>-};<br>-<br>-#define SMI_HANDLER_SCI_EN(__bit) (1 << (__bit))<br>-<br>-/* SMI handlers that should be serviced in SCI mode too. */<br>-uint32_t smi_handler_sci_mask =<br>- SMI_HANDLER_SCI_EN(APM_STS_BIT) |<br>- SMI_HANDLER_SCI_EN(SMI_ON_SLP_EN_STS_BIT);<br>-<br>-/*<br>- * Interrupt handler for SMI#<br>- */<br>-void southbridge_smi_handler(void)<br>-{<br>- int i;<br>- u32 smi_sts;<br>-<br>- /*<br>- * We need to clear the SMI status registers, or we won't see what's<br>- * happening in the following calls.<br>- */<br>- smi_sts = pmc_clear_smi_status();<br>-<br>- /*<br>- * In SCI mode, execute only those SMI handlers that have<br>- * declared themselves as available for service in that mode<br>- * using smi_handler_sci_mask.<br>- */<br>- if (pmc_read_pm1_control() & SCI_EN)<br>- smi_sts &= smi_handler_sci_mask;<br>-<br>- if (!smi_sts)<br>- return;<br>-<br>- /* Call SMI sub handler for each of the status bits */<br>- for (i = 0; i < ARRAY_SIZE(southbridge_smi); i++) {<br>- if (smi_sts & (1 << i)) {<br>- if (southbridge_smi[i]) {<br>- southbridge_smi[i]();<br>- } else {<br>- printk(BIOS_DEBUG,<br>- "SMI_STS[%d] occurred, but no handler available.\n",<br>- i);<br>- }<br>- }<br>- }<br>-}<br>+const smi_handler_t southbridge_smi[SMI_STS_BITS] = {<br>+ [SMI_ON_SLP_EN_STS_BIT] = smihandler_southbridge_sleep,<br>+ [APM_STS_BIT] = smihandler_southbridge_apmc,<br>+ [PM1_STS_BIT] = smihandler_southbridge_pm1,<br>+ [GPE0_STS_BIT] = smihandler_southbridge_gpe0,<br>+ [GPIO_STS_BIT] = smihandler_southbridge_gpi,<br>+ [ESPI_SMI_STS_BIT] = smihandler_southbridge_espi,<br>+ [MCSMI_STS_BIT] = smihandler_southbridge_mc,<br>+ [TCO_STS_BIT] = smihandler_southbridge_tco,<br>+ [PERIODIC_STS_BIT] = smihandler_southbridge_periodic,<br>+ [MONITOR_STS_BIT] = smihandler_southbridge_monitor,<br>+};<br>\ No newline at end of file<br>diff --git a/src/soc/intel/skylake/smmrelocate.c b/src/soc/intel/skylake/smmrelocate.c<br>index dbe0c94..b477b11 100644<br>--- a/src/soc/intel/skylake/smmrelocate.c<br>+++ b/src/soc/intel/skylake/smmrelocate.c<br>@@ -26,6 +26,7 @@<br> #include <cpu/x86/mtrr.h><br> #include <cpu/x86/smm.h><br> #include <console/console.h><br>+#include <intelblocks/smm.h><br> #include <soc/cpu.h><br> #include <soc/msr.h><br> #include <soc/pci_devs.h><br>@@ -281,7 +282,7 @@<br> void smm_initialize(void)<br> {<br> /* Clear the SMM state in the southbridge. */<br>- southbridge_smm_clear_state();<br>+ smm_southbridge_clear_state();<br> <br> /*<br> * Run the relocation handler for on the BSP to check and set up<br></pre><p>To view, visit <a href="https://review.coreboot.org/22826">change 22826</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/22826"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I8163dc7e18bb417e8c18a12628988959c128b3df </div>
<div style="display:none"> Gerrit-Change-Number: 22826 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Subrata Banik <subrata.banik@intel.com> </div>
<div style="display:none"> Gerrit-Reviewer: Brandon Breitenstein <brandon.breitenstein@intel.com> </div>