summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/common/block/cpu/Kconfig9
-rw-r--r--src/soc/amd/common/block/cpu/smm/finalize.c22
-rw-r--r--src/soc/amd/common/block/cpu/smm/smm_helper.c14
-rw-r--r--src/soc/amd/common/block/cpu/smm/smm_relocate.c15
-rw-r--r--src/soc/amd/common/block/include/amdblocks/smm.h2
5 files changed, 52 insertions, 10 deletions
diff --git a/src/soc/amd/common/block/cpu/Kconfig b/src/soc/amd/common/block/cpu/Kconfig
index f926887cf5..1ffaece9dd 100644
--- a/src/soc/amd/common/block/cpu/Kconfig
+++ b/src/soc/amd/common/block/cpu/Kconfig
@@ -85,6 +85,15 @@ config SOC_AMD_COMMON_BLOCK_SMM
Add common SMM relocation, finalization and handler functionality to
the build.
+config SOC_AMD_COMMON_LATE_SMM_LOCKING
+ bool
+ depends on SOC_AMD_COMMON_BLOCK_SMM
+ help
+ Select this option to perform SMM locking late in soc_finalize(), rather than earlier
+ in smm_relocation_handler(). This is required for pre-Zen SoCs like Stoneyridge which
+ call into an AGESA binary as part of S3 resume, and require SMM to still be unlocked
+ at that time.
+
config SOC_AMD_COMMON_BLOCK_SVI2
bool
help
diff --git a/src/soc/amd/common/block/cpu/smm/finalize.c b/src/soc/amd/common/block/cpu/smm/finalize.c
index b81b9bcd1d..a3ba188d9e 100644
--- a/src/soc/amd/common/block/cpu/smm/finalize.c
+++ b/src/soc/amd/common/block/cpu/smm/finalize.c
@@ -9,8 +9,30 @@
#include <cpu/x86/msr.h>
#include <types.h>
+static void late_smm_lock(void *unused)
+{
+ /* Finalize SMM settings */
+ if (is_smm_locked()) /* Skip if already locked, avoid GPF */
+ return;
+
+ if (CONFIG(HAVE_SMI_HANDLER))
+ tseg_valid();
+
+ lock_smm();
+}
+
+static void late_smm_finalize(void)
+{
+ printk(BIOS_SPEW, "Lock SMM configuration\n");
+ if (mp_run_on_all_cpus(late_smm_lock, NULL) != CB_SUCCESS)
+ printk(BIOS_WARNING, "Failed to finalize all cores\n");
+}
+
static void soc_finalize(void *unused)
{
+ if (CONFIG(SOC_AMD_COMMON_LATE_SMM_LOCKING))
+ late_smm_finalize();
+
if (!acpi_is_wakeup_s3()) {
acpi_clear_pm_gpe_status();
diff --git a/src/soc/amd/common/block/cpu/smm/smm_helper.c b/src/soc/amd/common/block/cpu/smm/smm_helper.c
index a6e7d2dac5..e87d12c641 100644
--- a/src/soc/amd/common/block/cpu/smm/smm_helper.c
+++ b/src/soc/amd/common/block/cpu/smm/smm_helper.c
@@ -30,6 +30,20 @@ void clear_tvalid(void)
wrmsr(SMM_MASK_MSR, mask);
}
+void tseg_valid(void)
+{
+ msr_t mask = rdmsr(SMM_MASK_MSR);
+ mask.lo |= SMM_TSEG_VALID;
+
+ wrmsr(SMM_MASK_MSR, mask);
+}
+
+bool is_smm_locked(void)
+{
+ msr_t hwcr = rdmsr(HWCR_MSR);
+ return hwcr.lo & SMM_LOCK ? true : false;
+}
+
void lock_smm(void)
{
msr_t hwcr = rdmsr(HWCR_MSR);
diff --git a/src/soc/amd/common/block/cpu/smm/smm_relocate.c b/src/soc/amd/common/block/cpu/smm/smm_relocate.c
index ae008853bd..d01f4c3e2d 100644
--- a/src/soc/amd/common/block/cpu/smm/smm_relocate.c
+++ b/src/soc/amd/common/block/cpu/smm/smm_relocate.c
@@ -52,14 +52,6 @@ static void get_smm_info(uintptr_t *perm_smbase, size_t *perm_smsize,
*smm_save_state_size = sizeof(amd64_smm_state_save_area_t);
}
-static void tseg_valid(void)
-{
- msr_t mask = rdmsr(SMM_MASK_MSR);
- mask.lo |= SMM_TSEG_VALID;
-
- wrmsr(SMM_MASK_MSR, mask);
-}
-
static void smm_relocation_handler(void)
{
uintptr_t tseg_base;
@@ -87,8 +79,11 @@ static void smm_relocation_handler(void)
};
wrmsr(SMM_BASE_MSR, smm_base);
- tseg_valid();
- lock_smm();
+
+ if (!CONFIG(SOC_AMD_COMMON_LATE_SMM_LOCKING)) {
+ tseg_valid();
+ lock_smm();
+ }
}
static void post_mp_init(void)
diff --git a/src/soc/amd/common/block/include/amdblocks/smm.h b/src/soc/amd/common/block/include/amdblocks/smm.h
index 97b11be609..bcd30f8ed2 100644
--- a/src/soc/amd/common/block/include/amdblocks/smm.h
+++ b/src/soc/amd/common/block/include/amdblocks/smm.h
@@ -11,6 +11,8 @@ void handle_smi_gsmi(void);
void handle_smi_store(void);
void fch_apmc_smi_handler(void);
void clear_tvalid(void);
+void tseg_valid(void);
+bool is_smm_locked(void);
void lock_smm(void);
/* See SMITYPE_* for list possible of events. GEVENTS are handled with mainboard_smi_gpi. */
void mainboard_handle_smi(int event);