diff options
author | Marshall Dawson <marshall.dawson@amd.corp-partner.google.com> | 2020-03-16 19:20:20 -0600 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2020-04-16 23:15:09 +0000 |
commit | e8ffa9ffd3cf5cb9fcade12e1f1e0dea5fc3fcf2 (patch) | |
tree | 7599bd33ad59b015afe080744905af2b97b42c78 /src/soc/amd | |
parent | e26da8ba16d4b87669524871b85a211a75f0eec4 (diff) |
soc/amd/psp: Add SmmInfo command
Implement the MboxBiosCmdSmmInfo function to inform the PSP of the SoC's
SMM configuration. Once the BootDone command is sent, the PSP only
responds to commands where the buffer is in SMM memory.
Set aside a region for the core-to-PSP command buffer and the
PSP-to-core mailbox. Also add an SMM flag, which the PSP expects to read
as non-zero during an SMI.
Add calls to soc functions for the soc to populate the trigger info and
register info (v2 only).
Add functions to set up the structures needed for the SmmInfo function
in Picasso support. Issue a SW SMI, and add a new handler to call the
new PSP function.
BUG=b:153677737
Change-Id: I10088a53e786db788740e4b388650641339dae75
Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com>
Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/40295
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
Diffstat (limited to 'src/soc/amd')
-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 | ||||
-rw-r--r-- | src/soc/amd/picasso/include/soc/smi.h | 3 | ||||
-rw-r--r-- | src/soc/amd/picasso/psp.c | 39 | ||||
-rw-r--r-- | src/soc/amd/picasso/smi.c | 3 | ||||
-rw-r--r-- | src/soc/amd/picasso/smihandler.c | 4 |
8 files changed, 192 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; +} diff --git a/src/soc/amd/picasso/include/soc/smi.h b/src/soc/amd/picasso/include/soc/smi.h index e890e1319a..fb8061ca16 100644 --- a/src/soc/amd/picasso/include/soc/smi.h +++ b/src/soc/amd/picasso/include/soc/smi.h @@ -86,6 +86,7 @@ #define SMITYPE_NB_GPP_HOT_PLUG 30 /* 31 Reserved */ #define SMITYPE_WAKE_L2 32 +#define SMITYPE_PSP 33 /* 33 - 38 Reserved */ #define SMITYPE_AZPME 39 #define SMITYPE_USB_PD_I2C4 40 @@ -186,6 +187,8 @@ #define SMI_REG_CONTROL8 0xc0 #define SMI_REG_CONTROL9 0xc4 +#define SMI_MODE_MASK 0x03 + enum smi_mode { SMI_MODE_DISABLE = 0, SMI_MODE_SMI = 1, diff --git a/src/soc/amd/picasso/psp.c b/src/soc/amd/picasso/psp.c index d6eb7d31a3..88b25b88b0 100644 --- a/src/soc/amd/picasso/psp.c +++ b/src/soc/amd/picasso/psp.c @@ -3,6 +3,8 @@ #include <console/console.h> #include <cpu/x86/msr.h> +#include <soc/smi.h> +#include <amdblocks/acpimmio_map.h> #include <amdblocks/psp.h> #define PSP_MAILBOX_OFFSET 0x10570 @@ -20,3 +22,40 @@ void *soc_get_mbox_address(void) return (void *)(psp_mmio + PSP_MAILBOX_OFFSET); } + +void soc_fill_smm_trig_info(struct smm_trigger_info *trig) +{ + if (!trig) + return; + + trig->address = 0xfed802a8; + trig->address_type = SMM_TRIGGER_MEM; + trig->value_width = SMM_TRIGGER_DWORD; + trig->value_and_mask = 0xfdffffff; + trig->value_or_mask = 0x02000000; +} + +void soc_fill_smm_reg_info(struct smm_register_info *reg) +{ + if (!reg) + return; + + reg->smi_enb.address = ACPIMMIO_SMI_BASE + SMI_REG_SMITRIG0; + reg->smi_enb.address_type = SMM_TRIGGER_MEM; + reg->smi_enb.value_width = SMM_TRIGGER_DWORD; + reg->smi_enb.reg_bit_mask = SMITRG0_SMIENB; + reg->smi_enb.expect_value = 0; + + reg->eos.address = ACPIMMIO_SMI_BASE + SMI_REG_SMITRIG0; + reg->eos.address_type = SMM_TRIGGER_MEM; + reg->eos.value_width = SMM_TRIGGER_DWORD; + reg->eos.reg_bit_mask = SMITRG0_EOS; + reg->eos.expect_value = SMITRG0_EOS; + + reg->psp_smi_en.address = ACPIMMIO_SMI_BASE + SMI_REG_CONTROL0; + reg->psp_smi_en.address += sizeof(uint32_t) * SMITYPE_PSP / 16; + reg->psp_smi_en.address_type = SMM_TRIGGER_MEM; + reg->psp_smi_en.value_width = SMM_TRIGGER_DWORD; + reg->psp_smi_en.reg_bit_mask = SMI_MODE_MASK << (2 * SMITYPE_PSP % 16); + reg->psp_smi_en.expect_value = SMI_MODE_SMI << (2 * SMITYPE_PSP % 16); +} diff --git a/src/soc/amd/picasso/smi.c b/src/soc/amd/picasso/smi.c index ab8f405e59..273c55b635 100644 --- a/src/soc/amd/picasso/smi.c +++ b/src/soc/amd/picasso/smi.c @@ -17,6 +17,7 @@ * Utilities for SMM setup */ +#include <arch/io.h> #include <console/console.h> #include <cpu/x86/smm.h> #include <amdblocks/acpimmio.h> @@ -35,4 +36,6 @@ void enable_smi_generation(void) reg &= ~SMITRG0_SMIENB; /* Enable SMI generation */ reg |= SMITRG0_EOS; /* Set EOS bit */ smi_write32(SMI_REG_SMITRIG0, reg); + + outb(APM_CNT_SMMINFO, APM_CNT); } diff --git a/src/soc/amd/picasso/smihandler.c b/src/soc/amd/picasso/smihandler.c index 55493776dd..e4d1c86f57 100644 --- a/src/soc/amd/picasso/smihandler.c +++ b/src/soc/amd/picasso/smihandler.c @@ -26,6 +26,7 @@ #include <soc/southbridge.h> #include <amdblocks/acpimmio.h> #include <amdblocks/acpi.h> +#include <amdblocks/psp.h> #include <elog.h> /* bits in smm_io_trap */ @@ -125,6 +126,9 @@ static void sb_apmc_smi_handler(void) if (CONFIG(SMMSTORE)) southbridge_smi_store(); break; + case APM_CNT_SMMINFO: + psp_notify_smm(); + break; } mainboard_smi_apmc(cmd); |