diff options
author | Felix Held <felix-coreboot@felixheld.de> | 2024-07-13 02:50:03 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-07-25 22:56:37 +0000 |
commit | 331cb328c29dee5cb4053059fd21f134176ca96f (patch) | |
tree | 8939494792c2a4dcb863871949c43caa619e2169 | |
parent | 645203a28052b78c524bf101df960ae59f5828b0 (diff) |
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>
-rw-r--r-- | src/soc/amd/common/block/psp/psb.c | 18 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp_gen2.c | 51 |
2 files changed, 43 insertions, 26 deletions
diff --git a/src/soc/amd/common/block/psp/psb.c b/src/soc/amd/common/block/psp/psb.c index a537bff37b..4ac7aaf08c 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 const char *fuse_status_to_string(u32 status) } } -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 @@ static enum cb_err psb_enable(void) } }; - 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 8f0bdcf9a1..bed31c1e8e 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 @@ union pspv2_mbox_command { } __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 @@ static int wait_command(bool wait_for_ready) 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 @@ static int wait_command(bool wait_for_ready) 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 @@ int send_psp_command(u32 command, void *buffer) 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; } |