[coreboot-gerrit] Patch set updated for coreboot: dcaea21 intel/i82801gx: SMM: Pass the ACPI GNVS pointer via state save map
Paul Menzel (paulepanter@users.sourceforge.net)
gerrit at coreboot.org
Tue Jan 6 18:10:28 CET 2015
Paul Menzel (paulepanter at users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8139
-gerrit
commit dcaea212bff31e53f65b37656611be6a8513033a
Author: Paul Menzel <paulepanter at users.sourceforge.net>
Date: Tue Jan 6 17:12:26 2015 +0100
intel/i82801gx: SMM: Pass the ACPI GNVS pointer via state save map
Currently on older Intel systems, during resume the coreboot table is
overwritten by the code in `smm_setup_structures()` called by
`acpi_resume()` in `src/arch/x86/boot/acpi.c`. As a result, `cbmem`
does not work anymore.
Port commit 7978e3a3 (SMM: Pass the ACPI GNVS pointer via state save
map), applied to Intel BD82x6x and the explanation below, to the other
Intel southbridges too.
Instead of hijacking some random memory addresses to relay the GNVS
pointer to SMM we can use EBX register during the write to APM_CNT
register when the SMI is triggered.
More or less also copy
commit d396a77b4d144a89a98240541945111280106de6
Author: Duncan Laurie <dlaurie at chromium.org>
Date: Wed Oct 3 18:22:16 2012 -0700
SMM: Extract function for finding save state node
Change-Id: I60013cc6c441ba2696ea3623722d4b0afe2dd2cc
Signed-off-by: Paul Menzel <paulepanter at users.sourceforge.net>
---
src/southbridge/intel/i82801gx/smi.c | 18 ++++++++---
src/southbridge/intel/i82801gx/smihandler.c | 49 +++++++++++++++++++++++++++--
2 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/src/southbridge/intel/i82801gx/smi.c b/src/southbridge/intel/i82801gx/smi.c
index 134c232..84714af 100644
--- a/src/southbridge/intel/i82801gx/smi.c
+++ b/src/southbridge/intel/i82801gx/smi.c
@@ -383,9 +383,19 @@ void smm_lock(void)
void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
{
- /* The GDT or coreboot table is going to live here. But a long time
- * after we relocated the GNVS, so this is not troublesome.
+ /*
+ * Issue SMI to set the gnvs pointer in SMM.
+ * tcg and smi1 are unused.
+ *
+ * EAX = APM_CNT_GNVS_UPDATE
+ * EBX = gnvs pointer
+ * EDX = APM_CNT
*/
- *(u32 *)0x500 = (u32)gnvs;
- outb(0xea, 0xb2);
+ asm volatile (
+ "outb %%al, %%dx\n\t"
+ : /* ignore result */
+ : "a" (APM_CNT_GNVS_UPDATE),
+ "b" ((u32)gnvs),
+ "d" (APM_CNT)
+ );
}
diff --git a/src/southbridge/intel/i82801gx/smihandler.c b/src/southbridge/intel/i82801gx/smihandler.c
index e2505ce..58679ff 100644
--- a/src/southbridge/intel/i82801gx/smihandler.c
+++ b/src/southbridge/intel/i82801gx/smihandler.c
@@ -361,10 +361,49 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
}
}
+/*
+ * Look for Synchronous IO SMI and use save state from that
+ * core in case we are not running on the same core that
+ * initiated the IO transaction.
+ */
+static em64t101_smm_state_save_area_t *smi_apmc_find_state_save(u8 cmd)
+{
+ em64t101_smm_state_save_area_t *state;
+ u32 base = smi_get_tseg_base() + SMM_EM64T101_SAVE_STATE_OFFSET;
+ int node;
+
+ /* Check all nodes looking for the one that issued the IO */
+ for (node = 0; node < CONFIG_MAX_CPUS; node++) {
+ state = (em64t101_smm_state_save_area_t *)
+ (base - (node * 0x400));
+
+ /* Check for Synchronous IO (bit0==1) */
+ if (!(state->io_misc_info & (1 << 0)))
+ continue;
+
+ /* Make sure it was a write (bit4==0) */
+ if (state->io_misc_info & (1 << 4))
+ continue;
+
+ /* Check for APMC IO port */
+ if (((state->io_misc_info >> 16) & 0xff) != APM_CNT)
+ continue;
+
+ /* Check AX against the requested command */
+ if ((state->rax & 0xff) != cmd)
+ continue;
+
+ return state;
+ }
+
+ return NULL;
+}
+
static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state_save)
{
u32 pmctrl;
u8 reg8;
+ em64t101_smm_state_save_area_t *state;
/* Emulate B2 register as the FADT / Linux expects it */
@@ -404,9 +443,13 @@ static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state
printk(BIOS_DEBUG, "SMI#: SMM structures already initialized!\n");
return;
}
- gnvs = *(global_nvs_t **)0x500;
- smm_initialized = 1;
- printk(BIOS_DEBUG, "SMI#: Setting up structures to %p\n", gnvs);
+ state = smi_apmc_find_state_save(reg8);
+ if (state) {
+ /* EBX in the state save contains the GNVS pointer */
+ gnvs = (global_nvs_t *)((u32)state->rbx);
+ smm_initialized = 1;
+ printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);
+ }
break;
default:
printk(BIOS_DEBUG, "SMI#: Unknown function APM_CNT=%02x\n", reg8);
More information about the coreboot-gerrit
mailing list