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>
This commit is contained in:
Duncan Laurie 2012-10-03 18:22:16 -07:00 committed by Ronald G. Minnich
parent 11290c49b0
commit d396a77b4d
1 changed files with 42 additions and 26 deletions

View File

@ -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));
if (io_smi->io_misc_info == io_want_info &&
((u8)io_smi->rax == ELOG_GSMI_APM_CNT))
break;
/* 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 != 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 */