diff --git a/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h b/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h index 0431626f2c..df0e0d0b67 100644 --- a/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h +++ b/src/commonlib/bsd/include/commonlib/bsd/cbmem_id.h @@ -7,6 +7,7 @@ #define CBMEM_ID_ACPI_BERT 0x42455254 #define CBMEM_ID_ACPI_CNVS 0x434e5653 #define CBMEM_ID_ACPI_GNVS 0x474e5653 +#define CBMEM_ID_OPAL_S3_SCRATCH 0x3353504f /* 'OPS3' */ #define CBMEM_ID_ACPI_HEST 0x48455354 #define CBMEM_ID_ACPI_UCSI 0x55435349 #define CBMEM_ID_AFTER_CAR 0xc4787a93 @@ -100,6 +101,7 @@ { CBMEM_ID_ACPI_BERT, "ACPI BERT " }, \ { CBMEM_ID_ACPI_CNVS, "CHROMEOS NVS" }, \ { CBMEM_ID_ACPI_GNVS, "ACPI GNVS " }, \ + { CBMEM_ID_OPAL_S3_SCRATCH, "OPAL S3 SCR" }, \ { CBMEM_ID_ACPI_HEST, "ACPI HEST " }, \ { CBMEM_ID_ACPI_UCSI, "ACPI UCSI " }, \ { CBMEM_ID_AGESA_RUNTIME, "AGESA RSVD " }, \ diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 7a701bb9d6..c049d4b124 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -196,6 +196,24 @@ config SMM_MODULE_STACK_SIZE This option determines the size of the stack within the SMM handler modules. +config SMM_OPAL_S3_SCRATCH_CBMEM + bool + depends on HAVE_ACPI_RESUME + default n + help + Allocate a coreboot-managed CBMEM region that can be used as a + persistent (across S3) scratch buffer by SMM code performing OPAL/NVMe + unlock on resume. The region is in CBMEM and therefore reserved from + the OS via the memory map. + +config SMM_OPAL_S3_SCRATCH_SIZE + hex "OPAL S3 scratch size (bytes)" + depends on SMM_OPAL_S3_SCRATCH_CBMEM + default 0x4000 + help + Size of the CBMEM scratch buffer provided to the OPAL S3 unlock SMM + handler. This buffer must be DMA-safe and persistent across S3. + endif config SMM_LAPIC_REMAP_MITIGATION diff --git a/src/cpu/x86/smm/smm_module_handler.c b/src/cpu/x86/smm/smm_module_handler.c index 8bcda32b33..3f14d970d8 100644 --- a/src/cpu/x86/smm/smm_module_handler.c +++ b/src/cpu/x86/smm/smm_module_handler.c @@ -66,6 +66,14 @@ void smm_get_smmstore_com_buffer(uintptr_t *base, size_t *size) *size = smm_runtime.smmstore_com_buffer_size; } +#if CONFIG(SMM_OPAL_S3_SCRATCH_CBMEM) +void smm_get_opal_s3_scratch_buffer(uintptr_t *base, size_t *size) +{ + *base = smm_runtime.opal_s3_scratch_base; + *size = smm_runtime.opal_s3_scratch_size; +} +#endif + void smm_get_cbmemc_buffer(void **buffer_out, size_t *size_out) { *buffer_out = smm_runtime.cbmemc; diff --git a/src/cpu/x86/smm/smm_module_loader.c b/src/cpu/x86/smm/smm_module_loader.c index dff2dde857..4946fe5a0f 100644 --- a/src/cpu/x86/smm/smm_module_loader.c +++ b/src/cpu/x86/smm/smm_module_loader.c @@ -366,6 +366,26 @@ static void setup_smihandler_params(struct smm_runtime *mod_params, mod_params->smmstore_com_buffer_base = (uintptr_t)ptr; mod_params->smmstore_com_buffer_size = info.block_size; } + +#if CONFIG(SMM_OPAL_S3_SCRATCH_CBMEM) + /* + * Provide a small, coreboot-managed CBMEM scratch region for SMM code. + * CBMEM is reserved in the memory map, and persists across S3, making + * it suitable for firmware-owned DMA buffers on resume. SMRAM is not + * accessible to devices for DMA, so this scratch buffer must live + * outside SMRAM. + */ + const size_t opal_s3_scratch_size = CONFIG_SMM_OPAL_S3_SCRATCH_SIZE; + void *scratch = cbmem_add(CBMEM_ID_OPAL_S3_SCRATCH, opal_s3_scratch_size); + if (!scratch) { + printk(BIOS_ERR, "SMM: Failed to allocate OPAL S3 scratch\n"); + mod_params->opal_s3_scratch_base = 0; + mod_params->opal_s3_scratch_size = 0; + } else { + mod_params->opal_s3_scratch_base = (uintptr_t)scratch; + mod_params->opal_s3_scratch_size = opal_s3_scratch_size; + } +#endif } static void print_region(const char *name, const struct region region) diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index 8c41623817..913bd37205 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -96,6 +96,10 @@ struct smm_runtime { int smm_log_level; uintptr_t smmstore_com_buffer_base; size_t smmstore_com_buffer_size; +#if CONFIG(SMM_OPAL_S3_SCRATCH_CBMEM) + uintptr_t opal_s3_scratch_base; + size_t opal_s3_scratch_size; +#endif } __packed; struct smm_module_params { @@ -238,5 +242,8 @@ bool smm_pci_resource_store_fill_resources(struct smm_pci_resource_info *slots, void smm_pci_resource_store_init(struct smm_runtime *smm_runtime); 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 #endif /* CPU_X86_SMM_H */