[PATCH] platform: generic: spacemit: k3: deny S-mode access to the reset vectors

liutong liutong at iscas.ac.cn
Tue Nov 3 01:44:15 PST 2026


spacemit_k3_pre_init() programs the per-cluster reset vector registers
with the warm boot entry point, so a hart that is powered back on
resumes in M-mode at that address. The registers sit in ordinary MMIO
and the K3 support registers no memory region covering them, so they
fall to the root domain's allow-everything region and S-mode can write
them. S-mode can then point a cluster's reset vector at its own code
and have that code run in M-mode the next time the cluster is powered
up.

Add a root domain region over the naturally aligned 1KB block at
0xd4282c00, which contains all four reset vector register pairs, with
M-mode-only permissions. It sorts before the allow-everything region
and so takes a lower PMP entry index. The APMU registers live below
that block and are left alone, so S-mode keeps the access it uses for
core idle and wakeup.

SpaceMit's own k3-br-v1.0.y branch already protects this address range
in spacemit_k3.c, as part of a larger page; the protection was not
carried over when K3 support was upstreamed.

Signed-off-by: liutong <liutong at iscas.ac.cn>
---

Found while auditing the DBTR shared memory paths; the reset vector
registers turned up because they sit in the same MMIO page the SpaceMit
power management code touches.

Why this range and not the whole page. SpaceMit's k3-br-v1.0.y branch
protects 0xd4282000 .. 0xd4282fff in spacemit_k3.c:

  rc = sbi_domain_root_add_memrange(REGISTER_PRESERVATION_BASE,
                                    REGISTER_PRESERVATION_SIZE, PAGE_SIZE,
                                    SBI_DOMAIN_MEMREGION_M_RWX);

That covers the APMU block at 0xd4282800 as well. Taking only the 1KB
block at 0xd4282c00 keeps every reset vector register inside it:

  C0 0xd4282db0/db4   C1 0xd4282eb0/eb4
  C2 0xd4282fe8/fec   C3 0xd4282e60/e64

while the highest APMU register in use here is PMU_AP_BASE + 0x36c =
0xd4282b6c, below the block. S-mode therefore keeps the APMU access it
needs. That seemed worth preserving after
4c5d9d9f ("lib: utils/andes: add the SMU and LLC registers to the root
domain"), where denying S-mode its power management registers broke
suspend and resume.

The block is naturally aligned, so it needs one PMP entry.

Verified by building for generic (RV64 and RV32) and booting qemu virt,
where the K3 early_init does not run and the root region list is
unchanged. I do not have K3 hardware running an upstream build to
confirm the region appears and that idle and wakeup still work; if
someone on the SpaceMit side can check that, I would appreciate it.

Not addressed here: platform/generic/spacemit/k1.c programs
C0/C1_RVBADDR in spacemit_k1_pre_init() the same way, at addresses in
the same window, and registers no region either. It looks like the same
gap, but the K1 vendor branch is not the one I compared against, so I
have left it for someone who knows that part.

 platform/generic/include/spacemit/k3.h |  9 +++++++++
 platform/generic/spacemit/k3.c         | 16 ++++++++++++++--
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/platform/generic/include/spacemit/k3.h b/platform/generic/include/spacemit/k3.h
index f444d064..e9580ecb 100644
--- a/platform/generic/include/spacemit/k3.h
+++ b/platform/generic/include/spacemit/k3.h
@@ -108,6 +108,15 @@
 						 PMU_CX_IDLE_MP_SCU_SRAM_PWRDWN | \
 						 PMU_CX_IDLE_ACNACTM_HW_CTRL)
 
+/*
+ * All four per-cluster reset vector register pairs fall inside this
+ * naturally aligned 1KB block. The APMU registers sit below it and are
+ * deliberately left out, so S-mode keeps the access it uses for core
+ * idle and wakeup.
+ */
+#define K3_RESET_VECTOR_BASE			0xd4282c00
+#define K3_RESET_VECTOR_SIZE			0x400
+
 /* boot entry for A100 clusters */
 #define C2_RVBADDR_LO_ADDR			(0xd4282c00 + 0x3e8)
 #define C2_RVBADDR_HI_ADDR			(0xd4282c00 + 0x3ec)
diff --git a/platform/generic/spacemit/k3.c b/platform/generic/spacemit/k3.c
index 7922ab11..9048678d 100644
--- a/platform/generic/spacemit/k3.c
+++ b/platform/generic/spacemit/k3.c
@@ -10,6 +10,7 @@
 #include <platform_override.h>
 #include <sbi/riscv_asm.h>
 #include <sbi/riscv_io.h>
+#include <sbi/sbi_domain.h>
 #include <sbi/sbi_hfence.h>
 #include <sbi/sbi_tlb.h>
 #include <spacemit/k3.h>
@@ -96,8 +97,19 @@ static void spacemit_k3_pre_init(void)
 
 static int spacemit_k3_early_init(bool cold_boot)
 {
-	if (cold_boot)
-		spacemit_k3_pre_init();
+	int rc;
+
+	if (!cold_boot)
+		return generic_early_init(cold_boot);
+
+	spacemit_k3_pre_init();
+
+	rc = sbi_domain_root_add_memrange(K3_RESET_VECTOR_BASE,
+					  K3_RESET_VECTOR_SIZE,
+					  K3_RESET_VECTOR_SIZE,
+					  SBI_DOMAIN_MEMREGION_M_RWX);
+	if (rc)
+		return rc;
 
 	return generic_early_init(cold_boot);
 }

base-commit: 2c7788e4c3efa63d670ee90402dac2a9799d0bd7
-- 
2.34.1




More information about the opensbi mailing list