Kyösti Mälkki has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/74741 )
Change subject: [WIP] cpu/x86/smm: Poll for SMI delivery completion ......................................................................
[WIP] cpu/x86/smm: Poll for SMI delivery completion
Change-Id: Ifc3cc23b8ec492291521319f0a2de44a45b39520 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- M src/cpu/x86/smi_trigger.c M src/include/cpu/x86/smm.h 2 files changed, 61 insertions(+), 9 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/41/74741/1
diff --git a/src/cpu/x86/smi_trigger.c b/src/cpu/x86/smi_trigger.c index 470ecde..cafb121 100644 --- a/src/cpu/x86/smi_trigger.c +++ b/src/cpu/x86/smi_trigger.c @@ -5,9 +5,11 @@ #include <cpu/x86/smm.h> #include <stdint.h>
-static void apmc_log(const char *fn, u8 cmd) +#define TIMEOUT_COUNT 100 + +static void prepare_smi_entry(const char *fn, const u32 cmd, const u32 params, int *timeout) { - switch (cmd) { + switch (cmd & 0xff) { case APM_CNT_ACPI_DISABLE: printk(BIOS_DEBUG, "%s: Disabling ACPI.\n", fn); break; @@ -18,37 +20,76 @@ printk(BIOS_DEBUG, "%s: Finalizing SMM.\n", fn); break; case APM_CNT_ELOG_GSMI: + *timeout = TIMEOUT_COUNT; break; case APM_CNT_SMMSTORE: + *timeout = TIMEOUT_COUNT; break; case APM_CNT_SMMINFO: break; default: - printk(BIOS_DEBUG, "%s: Unknown APMC 0x%02x.\n", fn, cmd); + printk(BIOS_ERR, "%s: Unknown APMC (eax = 0x%08x, ebx = 0x%08x)\n", + fn, cmd, params); break; } }
-int apm_control(u8 cmd) +/* SMI handler is entered with commands in %eax, params in %ebx. */ +int raise_io_smi(u32 cmd, const u32 params) { + const u16 io_port = APM_CNT; + int set_timeout = 0, retries; + /* Never proceed inside SMI handler or without one. */ if (ENV_SMM || !CONFIG(HAVE_SMI_HANDLER)) return -1;
- apmc_log(__func__, cmd); + prepare_smi_entry(__func__, cmd, params, &set_timeout); + retries = set_timeout;
/* Now raise the SMI. */ - outb(cmd, APM_CNT); + __asm__ __volatile__ ( + " mov %0, %%eax\n\t" + " outb %%al, %3\n\t" + "1: cmp %%eax, %0\n\t" + " jne 3f\n\t" + " test %1, %1\n\t" + " jz 3f\n\t" + "2: pause\n\t" + " dec %1\n\t" + " jmp 1b\n\t" + "3:\n\t" + : "+r" (cmd), "+r" (retries) + : "b" (params), "d" (io_port) + : "%eax", "memory");
- printk(BIOS_DEBUG, "APMC done.\n"); + if (!set_timeout) { + printk(BIOS_DEBUG, "APMC done.\n"); + return 0; + } + + if (cmd & 0xff) { + printk(BIOS_ERR, "APMC timed out (%d latency).\n", set_timeout - retries); + return -1; + } + + printk(BIOS_DEBUG, "APMC done (%d latency).\n", set_timeout - retries); return 0; }
+void apm_control(u8 cmd) +{ + /* Now raise the SMI. */ + raise_io_smi(cmd, 0); +} + u8 apm_get_apmc(void) { + int timeout_dummy; + /* Emulate B2 register as the FADT / Linux expects it */ u8 cmd = inb(APM_CNT);
- apmc_log("SMI#", cmd); + prepare_smi_entry("SMI#", cmd, 0, &timeout_dummy); return cmd; } diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index 4c97f21..667b17a 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -34,7 +34,8 @@ #define SMM_PCI_RESOURCE_STORE_NUM_RESOURCES 6
/* Send cmd to APM_CNT with HAVE_SMI_HANDLER checking. */ -int apm_control(u8 cmd); +int raise_io_smi(u32 cmd, const u32 params); +void apm_control(u8 cmd); u8 apm_get_apmc(void);
void io_trap_handler(int smif);