SMM: don't overwrite SMM memory on resume

Overwriting the SMM Area on resume leaves us with
all variables cleared out, i.e., the GNVS pointer
is no longer available, which makes SMIF function
calls impossible.

Change-Id: I08ab4ffd41df0922d63c017822de1f89a3ff254d
Signed-off-by: Sven Schnelle <svens@stackframe.org>
Reviewed-on: http://review.coreboot.org/34
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Sven Schnelle 2011-06-14 20:55:54 +02:00
parent b629d14bec
commit bfe8e5186e
4 changed files with 31 additions and 7 deletions

View File

@ -46,7 +46,7 @@ static int smi_obtain_lock(void)
return (ret == SMI_UNLOCKED); return (ret == SMI_UNLOCKED);
} }
static void smi_release_lock(void) void smi_release_lock(void)
{ {
asm volatile ( asm volatile (
"movb %1, %%al\n" "movb %1, %%al\n"

View File

@ -272,3 +272,4 @@ void __attribute__((weak)) southbridge_smi_handler(unsigned int node, smm_state_
void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts); void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts);
int __attribute__((weak)) mainboard_apm_cnt(u8 data); int __attribute__((weak)) mainboard_apm_cnt(u8 data);
void smi_release_lock(void);

View File

@ -320,6 +320,16 @@ static void smm_relocate(void)
static int smm_handler_copied = 0; static int smm_handler_copied = 0;
static int is_wakeup(void)
{
device_t dev0 = dev_find_slot(0, PCI_DEVFN(0,0));
if (!dev0)
return 0;
return pci_read_config32(dev0, 0xdc) == SKPAD_ACPI_S3_MAGIC;
}
static void smm_install(void) static void smm_install(void)
{ {
/* The first CPU running this gets to copy the SMM handler. But not all /* The first CPU running this gets to copy the SMM handler. But not all
@ -329,6 +339,11 @@ static void smm_install(void)
return; return;
smm_handler_copied = 1; smm_handler_copied = 1;
/* if we're resuming from S3, the SMM code is already in place,
* so don't copy it again to keep the current SMM state */
if (!is_wakeup()) {
/* enable the SMM memory window */ /* enable the SMM memory window */
pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
D_OPEN | G_SMRAME | C_BASE_SEG); D_OPEN | G_SMRAME | C_BASE_SEG);
@ -336,6 +351,7 @@ static void smm_install(void)
/* copy the real SMM handler */ /* copy the real SMM handler */
memcpy((void *)0xa0000, &_binary_smm_start, (size_t)&_binary_smm_size); memcpy((void *)0xa0000, &_binary_smm_start, (size_t)&_binary_smm_size);
wbinvd(); wbinvd();
}
/* close the SMM memory window and enable normal SMM */ /* close the SMM memory window and enable normal SMM */
pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM, pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,

View File

@ -328,6 +328,13 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
default: printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); break; default: printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); break;
} }
/* Unlock the SMI semaphore. We're currently in SMM, and the semaphore
* will never be unlocked because the next outl will switch off the CPU.
* This might open a small race between the smi_release_lock() and the outl()
* for other SMI handlers. Not sure if this could cause trouble. */
if (slp_typ == 5)
smi_release_lock();
/* Write back to the SLP register to cause the originally intended /* Write back to the SLP register to cause the originally intended
* event again. We need to set BIT13 (SLP_EN) though to make the * event again. We need to set BIT13 (SLP_EN) though to make the
* sleep happen. * sleep happen.