summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2012-10-03 18:22:16 -0700
committerRonald G. Minnich <rminnich@gmail.com>2012-11-14 05:42:19 +0100
commitd396a77b4d144a89a98240541945111280106de6 (patch)
tree174c01db1da91cdbd92baccdce8f1f846e63971c
parent11290c49b0e7f8c13e0128b0e2005b5466b49f5d (diff)
SMM: Extract function for finding save state node
This is currently used by the ELOG GSMI interface but is a good way to pass data to SMM so move the current searching code to a separate function and make it a bit more versatile with the checks it does to find a match so it can be used in other situations. Change-Id: I5b6f92169f77c7707448ec38684cdd53c02fe0a5 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/1763 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
-rw-r--r--src/southbridge/intel/bd82x6x/smihandler.c68
1 files changed, 42 insertions, 26 deletions
diff --git a/src/southbridge/intel/bd82x6x/smihandler.c b/src/southbridge/intel/bd82x6x/smihandler.c
index 1f8b44846e..250035c4c3 100644
--- a/src/southbridge/intel/bd82x6x/smihandler.c
+++ b/src/southbridge/intel/bd82x6x/smihandler.c
@@ -419,38 +419,54 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
}
#if CONFIG_ELOG_GSMI
-static void southbridge_smi_gsmi(void)
+/*
+ * 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(u64 cmd)
{
- em64t101_smm_state_save_area_t *io_smi;
- u32 base = smi_get_tseg_base() + 0x8000;
- u32 *ret, *param;
- u8 sub_command, node;
+ em64t101_smm_state_save_area_t *state;
+ u32 base = smi_get_tseg_base() + 0x8000 + 0x7d00;
+ int node;
- /*
- * Check 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.
- */
+ /* Check all nodes looking for the one that issued the IO */
for (node = 0; node < CONFIG_MAX_CPUS; node++) {
- /*
- * Look for IO Misc Info:
- * Synchronous bit[0]=1
- * Byte bit[3:1]=1
- * Output bit[7:4]=0
- * APMC port bit[31:16]=0xb2
- * RAX[7:0] == 0xEF
- */
- u32 io_want_info = (APM_CNT << 16) | 0x3;
- io_smi = (em64t101_smm_state_save_area_t *)
- (base + 0x7d00 - (node * 0x400));
+ 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;
- if (io_smi->io_misc_info == io_want_info &&
- ((u8)io_smi->rax == ELOG_GSMI_APM_CNT))
- break;
+ /* Check AX against the requested command */
+ if (state->rax != cmd)
+ continue;
+
+ return state;
}
- /* Did not find matching CPU Save State */
- if (node == CONFIG_MAX_CPUS)
+ return NULL;
+}
+#endif
+
+#if CONFIG_ELOG_GSMI
+static void southbridge_smi_gsmi(void)
+{
+ u32 *ret, *param;
+ u8 sub_command;
+ em64t101_smm_state_save_area_t *io_smi =
+ smi_apmc_find_state_save(ELOG_GSMI_APM_CNT);
+
+ if (!io_smi)
return;
/* Command and return value in EAX */