[PATCH] platform: generic: spacemit: k3: deny S-mode access to the reset vectors
Xiang W
wxjstz at 126.com
Wed Nov 11 23:59:32 PST 2026
在 2026-11-03二的 09:44 +0000,liutong写道:
> 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);
Hi,
I have a question regarding this patch.
My colleague Han Gao <gaohan at iscas.ac.cn> has access to a K3
platform and tested it. The PMP granularity on K3 is 4 KiB,
so a mapping size smaller than that will be ignored.
Could you clarify how this case should be handled?
Best regards,
Xiang W
> + if (rc)
> + return rc;
>
> return generic_early_init(cold_boot);
> }
>
> base-commit: 2c7788e4c3efa63d670ee90402dac2a9799d0bd7
> --
> 2.34.1
>
More information about the opensbi
mailing list