Felix Held has submitted this change. ( https://review.coreboot.org/c/coreboot/+/83448?usp=email )
Change subject: soc/amd/common/psp_gen2: use MMIO access again ......................................................................
soc/amd/common/psp_gen2: use MMIO access again
Now that we have a get_psp_mmio_base function that will work on all SoCs that use the psp_gen2 code, we can move back to accessing the PSP registers via their MMIO mapping. This sort-of reverts commit 198cc26e4951 ("soc/amd/common/block/psp/psp_gen2: use SMN access to PSP").
When doing SMN accesses from the SMI handler after the OS has taken over ownership of the platform, there's the possibility to cause trouble by clobbering the SMN access index register from SMM. So that should be either avoided completely or the SMI code needs to save and restore the original contents of the SMN index register.
The PSP MMIO base will be set up by the FSP before the resource allocation in coreboot and be treated like a fixed resource by the allocator. The first SMI where corresponding handler calls 'get_psp_mmio_base' happens when ramstage triggers the APM_CNT_SMMINFO SMI right after mpinit which happens after the resource allocation. So the PSP MMIO base address is expected to be configured and so the 'get_psp_mmio_base' function will cache the base address and won't need to do any SMN access in subsequent calls that might happen after the OS has take over control.
This isn't currently an issue, since the only PSP mailbox command from the SMI handler after coreboot is done and the OS has taken over will be during the S3/S4/S5 entry, and this will be triggered by the OS as the last step after it is done with all its preparations for suspend/ shutdown. There will however be future patches that add SMI-handlers which can send PSP mailbox commands during OS runtime, and so we have to make sure we don't clobber the SMN index register.
TEST=PSP mailbox commands are still sent correctly on Mandolin.
Signed-off-by: Felix Held felix-coreboot@felixheld.de Change-Id: I25f16d575991021d65b7b578956d9f90bfd15f6c Reviewed-on: https://review.coreboot.org/c/coreboot/+/83448 Reviewed-by: Martin Roth martin.roth@amd.corp-partner.google.com Reviewed-by: Matt DeVillier matt.devillier@amd.corp-partner.google.com Tested-by: build bot (Jenkins) no-reply@coreboot.org --- M src/soc/amd/common/block/psp/psb.c M src/soc/amd/common/block/psp/psp_gen2.c 2 files changed, 43 insertions(+), 26 deletions(-)
Approvals: Matt DeVillier: Looks good to me, approved Martin Roth: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/src/soc/amd/common/block/psp/psb.c b/src/soc/amd/common/block/psp/psb.c index a537bff..4ac7aaf 100644 --- a/src/soc/amd/common/block/psp/psb.c +++ b/src/soc/amd/common/block/psp/psb.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */
#include <amdblocks/reset.h> -#include <amdblocks/smn.h> #include <bootstate.h> #include <console/console.h> #include <device/mmio.h> @@ -83,9 +82,16 @@ } }
-static uint32_t get_psb_status(void) +static enum cb_err get_psb_status(uint32_t *psb_status_value) { - return smn_read32(SMN_PSP_PUBLIC_BASE + PSB_STATUS_OFFSET); + const uintptr_t psp_mmio = get_psp_mmio_base(); + + if (!psp_mmio) { + printk(BIOS_WARNING, "PSP: PSP_ADDR_MSR uninitialized\n"); + return CB_ERR; + } + *psb_status_value = read32p(psp_mmio | PSB_STATUS_OFFSET); + return CB_SUCCESS; }
/* @@ -102,7 +108,11 @@ } };
- status = get_psb_status(); + if (get_psb_status(&status) != CB_SUCCESS) { + printk(BIOS_ERR, "PSP: Failed to get base address.\n"); + return CB_ERR; + } + printk(BIOS_INFO, "PSB: Status = %x\n", status);
if (status & FUSE_PLATFORM_SECURE_BOOT_EN) { diff --git a/src/soc/amd/common/block/psp/psp_gen2.c b/src/soc/amd/common/block/psp/psp_gen2.c index 8f0bdcf..bed31c1 100644 --- a/src/soc/amd/common/block/psp/psp_gen2.c +++ b/src/soc/amd/common/block/psp/psp_gen2.c @@ -5,11 +5,11 @@ #include <amdblocks/psp.h> #include <amdblocks/root_complex.h> #include <amdblocks/smn.h> +#include <device/mmio.h> #include "psp_def.h"
#define PSP_MAILBOX_COMMAND_OFFSET 0x10570 /* 4 bytes */ -#define PSP_MAILBOX_BUFFER_L_OFFSET 0x10574 /* 4 bytes */ -#define PSP_MAILBOX_BUFFER_H_OFFSET 0x10578 /* 4 bytes */ +#define PSP_MAILBOX_BUFFER_OFFSET 0x10574 /* 8 bytes */
#define IOHC_MISC_PSP_MMIO_REG 0x2e0
@@ -92,40 +92,37 @@ } __packed fields; };
-static u16 rd_mbox_sts(void) +static u16 rd_mbox_sts(uintptr_t psp_mmio) { union pspv2_mbox_command tmp;
- tmp.val = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET); + tmp.val = read32p(psp_mmio | PSP_MAILBOX_COMMAND_OFFSET); return tmp.fields.mbox_status; }
-static void wr_mbox_cmd(u8 cmd) +static void wr_mbox_cmd(uintptr_t psp_mmio, u8 cmd) { union pspv2_mbox_command tmp = { .val = 0 };
/* Write entire 32-bit area to begin command execution */ tmp.fields.mbox_command = cmd; - smn_write32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET, tmp.val); + write32p(psp_mmio | PSP_MAILBOX_COMMAND_OFFSET, tmp.val); }
-static u8 rd_mbox_recovery(void) +static u8 rd_mbox_recovery(uintptr_t psp_mmio) { union pspv2_mbox_command tmp;
- tmp.val = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET); + tmp.val = read32p(psp_mmio | PSP_MAILBOX_COMMAND_OFFSET); return !!tmp.fields.recovery; }
-static void wr_mbox_buffer_ptr(void *buffer) +static void wr_mbox_buffer_ptr(uintptr_t psp_mmio, void *buffer) { - const uint32_t buf_addr_h = (uint64_t)(uintptr_t)buffer >> 32; - const uint32_t buf_addr_l = (uint64_t)(uintptr_t)buffer & 0xffffffff; - smn_write32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_BUFFER_H_OFFSET, buf_addr_h); - smn_write32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_BUFFER_L_OFFSET, buf_addr_l); + write64p(psp_mmio | PSP_MAILBOX_BUFFER_OFFSET, (uintptr_t)buffer); }
-static int wait_command(bool wait_for_ready) +static int wait_command(uintptr_t psp_mmio, bool wait_for_ready) { union pspv2_mbox_command and_mask = { .val = ~0 }; union pspv2_mbox_command expected = { .val = 0 }; @@ -143,7 +140,7 @@ stopwatch_init_msecs_expire(&sw, PSP_CMD_TIMEOUT);
do { - tmp = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET); + tmp = read32p(psp_mmio | PSP_MAILBOX_COMMAND_OFFSET); tmp &= ~and_mask.val; if (tmp == expected.val) return 0; @@ -154,23 +151,27 @@
int send_psp_command(u32 command, void *buffer) { - if (rd_mbox_recovery()) + const uintptr_t psp_mmio = get_psp_mmio_base(); + if (!psp_mmio) + return -PSPSTS_NOBASE; + + if (rd_mbox_recovery(psp_mmio)) return -PSPSTS_RECOVERY;
- if (wait_command(true)) + if (wait_command(psp_mmio, true)) return -PSPSTS_CMD_TIMEOUT;
/* set address of command-response buffer and write command register */ - wr_mbox_buffer_ptr(buffer); - wr_mbox_cmd(command); + wr_mbox_buffer_ptr(psp_mmio, buffer); + wr_mbox_cmd(psp_mmio, command);
/* PSP clears command register when complete. All commands except * SxInfo set the Ready bit. */ - if (wait_command(command != MBOX_BIOS_CMD_SX_INFO)) + if (wait_command(psp_mmio, command != MBOX_BIOS_CMD_SX_INFO)) return -PSPSTS_CMD_TIMEOUT;
/* check delivery status */ - if (rd_mbox_sts()) + if (rd_mbox_sts(psp_mmio)) return -PSPSTS_SEND_ERROR;
return 0; @@ -178,6 +179,12 @@
enum cb_err soc_read_c2p38(uint32_t *msg_38_value) { - *msg_38_value = smn_read32(SMN_PSP_PUBLIC_BASE + CORE_2_PSP_MSG_38_OFFSET); + const uintptr_t psp_mmio = get_psp_mmio_base(); + + if (!psp_mmio) { + printk(BIOS_WARNING, "PSP: PSP_ADDR_MSR uninitialized\n"); + return CB_ERR; + } + *msg_38_value = read32p(psp_mmio | CORE_2_PSP_MSG_38_OFFSET); return CB_SUCCESS; }