diff options
author | Duncan Laurie <dlaurie@chromium.org> | 2012-10-03 18:22:16 -0700 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2012-11-14 05:42:19 +0100 |
commit | d396a77b4d144a89a98240541945111280106de6 (patch) | |
tree | 174c01db1da91cdbd92baccdce8f1f846e63971c | |
parent | 11290c49b0e7f8c13e0128b0e2005b5466b49f5d (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.c | 68 |
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 */ |