summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 08:06:13 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-01 08:06:13 -0400
commit801d2051e464dbda44af94ff60587f9101314a4d (patch)
tree9dd2518900139da7ad4b390ff215821b491b8219
parent5ae79a735bb9c76e66a9fec3622fd410232f5dd0 (diff)
downloadopen-iov-801d2051e464dbda44af94ff60587f9101314a4d.tar.gz
open-iov-801d2051e464dbda44af94ff60587f9101314a4d.zip
gsp-phys: fix booter-unload teardown (WPR meta/args) so WPR2 is cleared on release
-rw-r--r--kernel/gsp_phys_fwsec.c65
1 files changed, 60 insertions, 5 deletions
diff --git a/kernel/gsp_phys_fwsec.c b/kernel/gsp_phys_fwsec.c
index dc8c979..3c63a95 100644
--- a/kernel/gsp_phys_fwsec.c
+++ b/kernel/gsp_phys_fwsec.c
@@ -138,6 +138,19 @@ bool gsp_phys_fwsec_dryrun_enabled(void)
#define GSP_PHYS_GFW_BOOT 0x118234
#define GSP_PHYS_GFW_BOOT_PROGRESS_MASK 0xff
#define GSP_PHYS_GFW_BOOT_COMPLETED 0xff
+/*
+ * VPR secure scratch 14. The Booter ucodes gate on the booter binary version
+ * (31:28) and on four sequence-handoff bits (27:24): Booter Load, AHESASC ->
+ * Booter Reload, Booter Reload -> ACR Unload and ACR Unload -> Booter Unload.
+ * Booter Unload requires all four DONE and the version field equal to its own
+ * build version (0 on TU102/TU104/TU106).
+ */
+#define GSP_PHYS_BSI_VPR_SECURE_SCRATCH_14 0x001180f8
+#define GSP_PHYS_SCRATCH14_BOOTER_VERSION_MASK 0xf0000000u
+#define GSP_PHYS_SCRATCH14_BOOTER_VERSION_SHIFT 28
+#define GSP_PHYS_SCRATCH14_HANDOFF_MASK 0x0f000000u
+#define GSP_PHYS_SCRATCH14_HANDOFF_SHIFT 24
+#define GSP_PHYS_SCRATCH14_BOOTER_VERSION_TU10X 0u
#define GSP_PHYS_GFW_PLM 0x118128
#define GSP_PHYS_GFW_PLM_LEVEL0 BIT(0)
#define GSP_PHYS_RISCV_STATUS 0x111240
@@ -961,13 +974,48 @@ static void gsp_phys_fwsec_ucode_free(struct pci_dev *pdev,
}
/*
- * Booter unload on SEC2: reset, load the unload image in direct mode and run
- * it with mailbox0/1 = 0xff. Success leaves WPR2 down.
+ * Seed the VPR secure-scratch sequence state the Booter Unload ucode gates on
+ * at entry. In the reference lifecycle those bits are produced by Booter Load,
+ * AHESASC, Booter Reload and ACR Unload; a FWSEC-only WPR2 carve (stage 3c)
+ * never runs those ucodes, so the unload refuses with its sequence/handoff
+ * error (observed SEC2 M0=0x29) before it touches WPR2 and WPR2 stays up.
+ * Setting the four handoff bits DONE and the Booter binary version to the
+ * Turing build version (0) restores the state Booter Load would have left so
+ * the unload can run; the unload itself clears both fields on completion.
+ * The WPR meta is not consumed by the unload path at all (it only resets the
+ * GSP engine, invalidates the sub-WPRs and locks WPR2 down).
+ */
+static void gsp_phys_booter_seed_sequence_state(void __iomem *bar0)
+{
+ u32 before, after;
+
+ before = readl(bar0 + GSP_PHYS_BSI_VPR_SECURE_SCRATCH_14);
+ after = before & ~(GSP_PHYS_SCRATCH14_BOOTER_VERSION_MASK |
+ GSP_PHYS_SCRATCH14_HANDOFF_MASK);
+ after |= GSP_PHYS_SCRATCH14_BOOTER_VERSION_TU10X <<
+ GSP_PHYS_SCRATCH14_BOOTER_VERSION_SHIFT;
+ after |= GSP_PHYS_SCRATCH14_HANDOFF_MASK;
+ writel(after, bar0 + GSP_PHYS_BSI_VPR_SECURE_SCRATCH_14);
+
+ pr_info("gsp-phys-fwsec: booter sequence seed: scratch14 0x%08x -> 0x%08x (booterVersion=%u want %u, handoffs 0x%x)\n",
+ before, readl(bar0 + GSP_PHYS_BSI_VPR_SECURE_SCRATCH_14),
+ (readl(bar0 + GSP_PHYS_BSI_VPR_SECURE_SCRATCH_14) &
+ GSP_PHYS_SCRATCH14_BOOTER_VERSION_MASK) >>
+ GSP_PHYS_SCRATCH14_BOOTER_VERSION_SHIFT,
+ GSP_PHYS_SCRATCH14_BOOTER_VERSION_TU10X,
+ (readl(bar0 + GSP_PHYS_BSI_VPR_SECURE_SCRATCH_14) &
+ GSP_PHYS_SCRATCH14_HANDOFF_MASK) >>
+ GSP_PHYS_SCRATCH14_HANDOFF_SHIFT);
+}
+
+/*
+ * Booter unload on SEC2: seed the sequence state, reset, load the unload image
+ * in direct mode and run it with mailbox0/1 = 0xff. Success leaves WPR2 down.
*/
static int gsp_phys_booter_unload(void __iomem *bar0)
{
const u8 *img = gsp_phys_booter_unload_image;
- u32 m0, m1;
+ u32 m0, m1, scratch;
int ret;
pr_info("gsp-phys-fwsec: booter unload: resetting SEC2 falcon\n");
@@ -977,6 +1025,7 @@ static int gsp_phys_booter_unload(void __iomem *bar0)
gsp_phys_falcon_disable_ctx_req(bar0, GSP_PHYS_SEC2_BASE,
GSP_PHYS_SEC2_FBIF_BASE);
+ gsp_phys_booter_seed_sequence_state(bar0);
gsp_phys_falcon_imem_copy(bar0, GSP_PHYS_SEC2_BASE,
GSP_PHYS_BOOTER_UNLOAD_NS_CODE_OFF,
img + GSP_PHYS_BOOTER_UNLOAD_NS_CODE_OFF,
@@ -1008,11 +1057,17 @@ static int gsp_phys_booter_unload(void __iomem *bar0)
if (ret)
return ret;
+ scratch = readl(bar0 + GSP_PHYS_BSI_VPR_SECURE_SCRATCH_14);
m0 = readl(bar0 + GSP_PHYS_SEC2_BASE + GSP_PHYS_FALCON_MAILBOX0);
m1 = readl(bar0 + GSP_PHYS_SEC2_BASE + GSP_PHYS_FALCON_MAILBOX1);
- pr_info("gsp-phys-fwsec: booter unload done: SEC2 M0=0x%08x M1=0x%08x WPR2_LO=0x%08x WPR2_HI=0x%08x\n",
+ pr_info("gsp-phys-fwsec: booter unload done: SEC2 M0=0x%08x M1=0x%08x WPR2_LO=0x%08x WPR2_HI=0x%08x scratch14=0x%08x\n",
m0, m1, readl(bar0 + GSP_PHYS_WPR2_ADDR_LO),
- readl(bar0 + GSP_PHYS_WPR2_ADDR_HI));
+ readl(bar0 + GSP_PHYS_WPR2_ADDR_HI), scratch);
+ pr_info("gsp-phys-fwsec: booter unload scratch14: booterVersion=%u handoffs=0x%x (unload clears both)\n",
+ (scratch & GSP_PHYS_SCRATCH14_BOOTER_VERSION_MASK) >>
+ GSP_PHYS_SCRATCH14_BOOTER_VERSION_SHIFT,
+ (scratch & GSP_PHYS_SCRATCH14_HANDOFF_MASK) >>
+ GSP_PHYS_SCRATCH14_HANDOFF_SHIFT);
if (m0 != 0) {
pr_err("gsp-phys-fwsec: booter unload reported error 0x%x\n",