cpu/x86/smm: reserve SMRAM for OPAL S3 state
Reserve a small persistent SMRAM subregion for OPAL S3 unlock state, so the payload-provided OPAL secret can survive SMM handler reload on S3 resume. Expose the region base/size to SMM via smm_runtime and provide an accessor for SMM code. Clear the region on cold boot/reboot, but preserve it when waking from S3. TEST=tested with rest of patch train Change-Id: Ib1e92edb31c845367afe6185e5fa18ab1bc71108 Signed-off-by: Sean Rhodes <sean@starlabs.systems> Reviewed-on: https://review.coreboot.org/c/coreboot/+/91414 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
9422dacdb8
commit
ce1db1f54a
5 changed files with 62 additions and 1 deletions
|
|
@ -196,6 +196,21 @@ config SMM_MODULE_STACK_SIZE
|
|||
This option determines the size of the stack within the SMM handler
|
||||
modules.
|
||||
|
||||
config SMM_OPAL_S3_STATE_SMRAM
|
||||
bool
|
||||
help
|
||||
Reserve a small persistent region in SMRAM for OPAL S3 state so the
|
||||
OPAL secret survives SMM handler reload on S3 resume.
|
||||
|
||||
config SMM_OPAL_S3_STATE_SMRAM_SIZE
|
||||
hex
|
||||
default 0x1000 if SMM_OPAL_S3_STATE_SMRAM
|
||||
default 0x0
|
||||
help
|
||||
Size in bytes of the persistent SMRAM region reserved for OPAL S3
|
||||
secret/state. Must be large enough to store the OPAL S3 state
|
||||
structure and should be kept minimal to reduce SMRAM pressure.
|
||||
|
||||
config SMM_OPAL_S3_SCRATCH_CBMEM
|
||||
bool
|
||||
depends on HAVE_ACPI_RESUME
|
||||
|
|
|
|||
|
|
@ -74,6 +74,14 @@ void smm_get_opal_s3_scratch_buffer(uintptr_t *base, size_t *size)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG(SMM_OPAL_S3_STATE_SMRAM)
|
||||
void smm_get_opal_s3_state_buffer(uintptr_t *base, size_t *size)
|
||||
{
|
||||
*base = smm_runtime.opal_s3_state_base;
|
||||
*size = smm_runtime.opal_s3_state_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
void smm_get_cbmemc_buffer(void **buffer_out, size_t *size_out)
|
||||
{
|
||||
*buffer_out = smm_runtime.cbmemc;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpi_gnvs.h>
|
||||
#include <cbmem.h>
|
||||
#include <commonlib/helpers.h>
|
||||
|
|
@ -386,6 +387,23 @@ static void setup_smihandler_params(struct smm_runtime *mod_params,
|
|||
mod_params->opal_s3_scratch_size = opal_s3_scratch_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG(SMM_OPAL_S3_STATE_SMRAM)
|
||||
uintptr_t state_base = 0;
|
||||
size_t state_size = 0;
|
||||
if (smm_subregion(SMM_SUBREGION_OPAL_S3_STATE, &state_base, &state_size)) {
|
||||
printk(BIOS_ERR, "SMM: Failed to locate OPAL S3 state SMRAM region\n");
|
||||
mod_params->opal_s3_state_base = 0;
|
||||
mod_params->opal_s3_state_size = 0;
|
||||
} else {
|
||||
mod_params->opal_s3_state_base = state_base;
|
||||
mod_params->opal_s3_state_size = state_size;
|
||||
|
||||
/* Clear any stale state on cold boot/reboot, but preserve it on S3 resume. */
|
||||
if (!acpi_is_wakeup_s3())
|
||||
memset((void *)state_base, 0, state_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_region(const char *name, const struct region region)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
* +-------------------------+
|
||||
* | External Stage Cache | SMM_RESERVED_SIZE
|
||||
* +-------------------------+
|
||||
* | OPAL S3 State (opt) | SMM_OPAL_S3_STATE_SMRAM_SIZE
|
||||
* +-------------------------+
|
||||
* | code and data |
|
||||
* | (TSEG) |
|
||||
* +-------------------------+ TSEG
|
||||
|
|
@ -25,6 +27,7 @@ int smm_subregion(int sub, uintptr_t *start, size_t *size)
|
|||
size_t sub_size;
|
||||
const size_t ied_size = CONFIG_IED_REGION_SIZE;
|
||||
const size_t cache_size = CONFIG_SMM_RESERVED_SIZE;
|
||||
const size_t opal_state_size = CONFIG_SMM_OPAL_S3_STATE_SMRAM_SIZE;
|
||||
|
||||
if (CONFIG(SMM_TSEG))
|
||||
smm_region(&sub_base, &sub_size);
|
||||
|
|
@ -34,13 +37,21 @@ int smm_subregion(int sub, uintptr_t *start, size_t *size)
|
|||
return -1;
|
||||
|
||||
ASSERT(IS_ALIGNED(sub_base, sub_size));
|
||||
ASSERT(sub_size > (cache_size + ied_size));
|
||||
ASSERT(sub_size > (cache_size + ied_size + opal_state_size));
|
||||
|
||||
switch (sub) {
|
||||
case SMM_SUBREGION_HANDLER:
|
||||
/* Handler starts at the base of TSEG. */
|
||||
sub_size -= ied_size;
|
||||
sub_size -= cache_size;
|
||||
sub_size -= opal_state_size;
|
||||
break;
|
||||
case SMM_SUBREGION_OPAL_S3_STATE:
|
||||
if (!opal_state_size)
|
||||
return -1;
|
||||
/* Persistent OPAL S3 state lives below the external stage cache. */
|
||||
sub_base += sub_size - (ied_size + cache_size + opal_state_size);
|
||||
sub_size = opal_state_size;
|
||||
break;
|
||||
case SMM_SUBREGION_CACHE:
|
||||
/* External cache is in the middle of TSEG. */
|
||||
|
|
|
|||
|
|
@ -100,6 +100,10 @@ struct smm_runtime {
|
|||
uintptr_t opal_s3_scratch_base;
|
||||
size_t opal_s3_scratch_size;
|
||||
#endif
|
||||
#if CONFIG(SMM_OPAL_S3_STATE_SMRAM)
|
||||
uintptr_t opal_s3_state_base;
|
||||
size_t opal_s3_state_size;
|
||||
#endif
|
||||
} __packed;
|
||||
|
||||
struct smm_module_params {
|
||||
|
|
@ -206,6 +210,8 @@ static inline void aseg_region(uintptr_t *start, size_t *size)
|
|||
enum {
|
||||
/* SMM handler area. */
|
||||
SMM_SUBREGION_HANDLER,
|
||||
/* Persistent OPAL S3 state area. */
|
||||
SMM_SUBREGION_OPAL_S3_STATE,
|
||||
/* SMM cache region. */
|
||||
SMM_SUBREGION_CACHE,
|
||||
/* Chipset specific area. */
|
||||
|
|
@ -245,5 +251,8 @@ void smm_get_smmstore_com_buffer(uintptr_t *base, size_t *size);
|
|||
#if CONFIG(SMM_OPAL_S3_SCRATCH_CBMEM)
|
||||
void smm_get_opal_s3_scratch_buffer(uintptr_t *base, size_t *size);
|
||||
#endif
|
||||
#if CONFIG(SMM_OPAL_S3_STATE_SMRAM)
|
||||
void smm_get_opal_s3_state_buffer(uintptr_t *base, size_t *size);
|
||||
#endif
|
||||
|
||||
#endif /* CPU_X86_SMM_H */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue