diff options
Diffstat (limited to 'src/soc/amd/common')
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/psp.h | 55 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp_def.h | 19 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp_smm.c | 78 |
4 files changed, 143 insertions, 10 deletions
diff --git a/src/soc/amd/common/block/include/amdblocks/psp.h b/src/soc/amd/common/block/include/amdblocks/psp.h index 53946fb8d2..a1c1152af9 100644 --- a/src/soc/amd/common/block/include/amdblocks/psp.h +++ b/src/soc/amd/common/block/include/amdblocks/psp.h @@ -7,21 +7,56 @@ /* Get the mailbox base address - specific to family of device. */ void *soc_get_mbox_address(void); +#define SMM_TRIGGER_IO 0 +#define SMM_TRIGGER_MEM 1 + +#define SMM_TRIGGER_BYTE 0 +#define SMM_TRIGGER_WORD 1 +#define SMM_TRIGGER_DWORD 2 + +struct smm_trigger_info { + uint64_t address; /* Memory or IO address */ + uint32_t address_type; /* 0=I/O, 1=memory */ + uint32_t value_width; /* 0=byte, 1=word, 2=qword */ + uint32_t value_and_mask; + uint32_t value_or_mask; +} __packed; + +struct smm_register { + uint64_t address; /* Memory or IO address */ + uint32_t address_type; /* 0=I/O, 1=memory */ + uint32_t value_width; /* 0=byte, 1=word, 2=qword */ + uint32_t reg_bit_mask; + uint32_t expect_value; +} __packed; + +struct smm_register_info { + struct smm_register smi_enb; + struct smm_register eos; + struct smm_register psp_smi_en; + struct smm_register reserved[5]; +} __packed; + +void soc_fill_smm_trig_info(struct smm_trigger_info *trig); +void soc_fill_smm_reg_info(struct smm_register_info *reg); /* v2 only */ + /* BIOS-to-PSP functions return 0 if successful, else negative value */ -#define PSPSTS_SUCCESS 0 -#define PSPSTS_NOBASE 1 -#define PSPSTS_HALTED 2 -#define PSPSTS_RECOVERY 3 -#define PSPSTS_SEND_ERROR 4 -#define PSPSTS_INIT_TIMEOUT 5 -#define PSPSTS_CMD_TIMEOUT 6 +#define PSPSTS_SUCCESS 0 +#define PSPSTS_NOBASE 1 +#define PSPSTS_HALTED 2 +#define PSPSTS_RECOVERY 3 +#define PSPSTS_SEND_ERROR 4 +#define PSPSTS_INIT_TIMEOUT 5 +#define PSPSTS_CMD_TIMEOUT 6 /* other error codes */ -#define PSPSTS_UNSUPPORTED 7 -#define PSPSTS_INVALID_NAME 8 -#define PSPSTS_INVALID_BLOB 9 +#define PSPSTS_UNSUPPORTED 7 +#define PSPSTS_INVALID_NAME 8 +#define PSPSTS_INVALID_BLOB 9 int psp_notify_dram(void); +int psp_notify_smm(void); + /* * type: identical to the corresponding PSP command, e.g. pass * MBOX_BIOS_CMD_SMU_FW2 to load SMU FW2 blob. diff --git a/src/soc/amd/common/block/psp/Makefile.inc b/src/soc/amd/common/block/psp/Makefile.inc index dc9a385e39..c2a33354ad 100644 --- a/src/soc/amd/common/block/psp/Makefile.inc +++ b/src/soc/amd/common/block/psp/Makefile.inc @@ -11,5 +11,6 @@ ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN1) += psp_gen1.c ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2) += psp_gen2.c smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c +smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp_smm.c smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN1) += psp_gen1.c smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2) += psp_gen2.c diff --git a/src/soc/amd/common/block/psp/psp_def.h b/src/soc/amd/common/block/psp/psp_def.h index f3ac5c2181..63ca3abb0a 100644 --- a/src/soc/amd/common/block/psp/psp_def.h +++ b/src/soc/amd/common/block/psp/psp_def.h @@ -6,6 +6,7 @@ #include <types.h> #include <commonlib/helpers.h> +#include <amdblocks/psp.h> /* x86 to PSP commands */ #define MBOX_BIOS_CMD_DRAM_INFO 0x01 @@ -81,6 +82,24 @@ struct mbox_default_buffer { /* command-response buffer unused by command */ struct mbox_buffer_header header; } __attribute__((packed, aligned(32))); +struct smm_req_buffer { + uint64_t smm_base; /* TSEG base */ + uint64_t smm_mask; /* TSEG mask */ + uint64_t psp_smm_data_region; /* PSP region in SMM space */ + uint64_t psp_smm_data_length; /* PSP region length in SMM space */ + struct smm_trigger_info smm_trig_info; +#if CONFIG(SOC_AMD_COMMON_BLOCK_PSP_GEN2) + struct smm_register_info smm_reg_info; +#endif + uint64_t psp_mbox_smm_buffer_address; + uint64_t psp_mbox_smm_flag_address; +} __packed; + +struct mbox_cmd_smm_info_buffer { + struct mbox_buffer_header header; + struct smm_req_buffer req; +} __attribute__((packed, aligned(32))); + struct mbox_cmd_sx_info_buffer { struct mbox_buffer_header header; u8 sleep_type; diff --git a/src/soc/amd/common/block/psp/psp_smm.c b/src/soc/amd/common/block/psp/psp_smm.c new file mode 100644 index 0000000000..cc15738881 --- /dev/null +++ b/src/soc/amd/common/block/psp/psp_smm.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#include <device/mmio.h> +#include <cpu/x86/msr.h> +#include <cpu/amd/msr.h> +#include <cbfs.h> +#include <region_file.h> +#include <timer.h> +#include <bootstate.h> +#include <rules.h> +#include <console/console.h> +#include <amdblocks/psp.h> +#include <soc/iomap.h> +#include <soc/northbridge.h> +#include "psp_def.h" + +#define C2P_BUFFER_MAXSIZE 0xc00 /* Core-to-PSP buffer */ +#define P2C_BUFFER_MAXSIZE 0xc00 /* PSP-to-core buffer */ + +struct { + u8 buffer[C2P_BUFFER_MAXSIZE]; +} __attribute__((aligned(32))) c2p_buffer; + +struct { + u8 buffer[P2C_BUFFER_MAXSIZE]; +} __attribute__((aligned(32))) p2c_buffer; + +static uint32_t smm_flag; /* Non-zero for SMM, clear when not */ + +static void set_smm_flag(void) +{ + smm_flag = 1; +} + +static void clear_smm_flag(void) +{ + smm_flag = 0; +} + +int psp_notify_smm(void) +{ + msr_t msr; + int cmd_status; + struct mbox_cmd_smm_info_buffer buffer = { + .header = { + .size = sizeof(buffer) + }, + .req = { + .psp_smm_data_region = (uintptr_t)p2c_buffer.buffer, + .psp_smm_data_length = sizeof(p2c_buffer), + .psp_mbox_smm_buffer_address = (uintptr_t)c2p_buffer.buffer, + .psp_mbox_smm_flag_address = (uintptr_t)&smm_flag, + } + }; + + msr = rdmsr(SMM_ADDR_MSR); + buffer.req.smm_base = ((uint64_t)msr.hi << 32) | msr.lo; + msr = rdmsr(SMM_MASK_MSR); + msr.lo &= 0xffff0000; /* mask SMM_LOCK and SMM_TSEG_VALID and reserved bits */ + buffer.req.smm_mask = ((uint64_t)msr.hi << 32) | msr.lo; + + soc_fill_smm_trig_info(&buffer.req.smm_trig_info); +#if (CONFIG(SOC_AMD_COMMON_BLOCK_PSP_GEN2)) + soc_fill_smm_reg_info(&buffer.req.smm_reg_info); +#endif + + printk(BIOS_DEBUG, "PSP: Notify SMM info... "); + + set_smm_flag(); + cmd_status = send_psp_command(MBOX_BIOS_CMD_SMM_INFO, &buffer); + clear_smm_flag(); + + /* buffer's status shouldn't change but report it if it does */ + psp_print_cmd_status(cmd_status, (struct mbox_default_buffer *)&buffer); + + return cmd_status; +} |