From 33a8782adddacfaf29da0dd6504206c76a313c2c Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Thu, 23 Jul 2026 14:10:15 +0800 Subject: [PATCH 1/2] lib: utils/fdt: Add smepmp validator to ISA extension fixup Add a hardware probe for the Smepmp extension to the ISA validation framework. The validator checks whether the mseccfg RLB bit is writable via write-readback, since CSR_MSECCFG is shared with other extensions (e.g. Zkr) and mere CSR existence does not imply Smepmp support. If the DT claims smepmp but the hardware does not implement the RLB bit, the extension is removed from riscv,isa and riscv,isa-extensions during CPU fixup, preventing the OS from misusing it. Signed-off-by: Chen Pei --- lib/utils/fdt/fdt_fixup.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c index ac75bfef..104153ae 100644 --- a/lib/utils/fdt/fdt_fixup.c +++ b/lib/utils/fdt/fdt_fixup.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -126,8 +128,29 @@ static bool isa_ext_zicbom_validate(void *fdt, int cpu_offset) return fdt_parse_cbom_block_size(fdt, cpu_offset, &block_size) == 0; } +static bool isa_ext_smepmp_validate(void *fdt, int cpu_offset) +{ + struct sbi_trap_info trap = {0}; + unsigned long oldval; + + (void)fdt; + (void)cpu_offset; + + oldval = csr_read_allowed(CSR_MSECCFG, &trap); + if (trap.cause) + return false; + + /* Probe Smepmp-specific RLB bit via write-readback */ + csr_write_allowed(CSR_MSECCFG, &trap, oldval | MSECCFG_RLB); + if (trap.cause) + return false; + + return (csr_swap(CSR_MSECCFG, oldval) & MSECCFG_RLB) == MSECCFG_RLB; +} + static const struct isa_ext_validate_entry isa_ext_validators[] = { { "h", isa_ext_h_validate }, + { "smepmp", isa_ext_smepmp_validate }, { "zicbom", isa_ext_zicbom_validate }, }; From 229691f27ddbf1aeb073a1a26841e7893a522aaa Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Thu, 23 Jul 2026 14:10:33 +0800 Subject: [PATCH 2/2] lib: sbi_hart: Add hardware validation framework for hart extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a table-driven validation framework that verifies DT-claimed ISA extensions against actual hardware capabilities during hart feature detection. Extensions that fail validation are cleared before PMP configuration and subsequent boot stages. This is necessary because fdt_cpu_fixup() runs in generic_final_init(), which is too late — hart_detect_features() has already cached the ISA extensions from DT via fdt_parse_isa_extensions(). The validation must happen inside hart_detect_features(), right after sbi_platform_extensions_init() populates the extension bitmap. Adding future validators requires only implementing a bool callback and appending to hart_ext_validators[]. Smepmp is the first validator: it probes the mseccfg RLB bit via write-readback to confirm hardware support, since CSR_MSECCFG is shared with Zkr and mere CSR existence does not imply Smepmp. Signed-off-by: Chen Pei --- lib/sbi/sbi_hart.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index 2ded1d2d..3d28a804 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -843,6 +843,41 @@ static int hart_mhpm_get_allowed_bits(void) return num_bits; } +struct hart_ext_validate_entry { + enum sbi_hart_extensions ext; + bool (*validate)(void); +}; + +static bool hart_ext_smepmp_validate(void) +{ + struct sbi_trap_info trap = {0}; + unsigned long oldval; + + oldval = csr_read_allowed(CSR_MSECCFG, &trap); + if (trap.cause) + return false; + + csr_write_allowed(CSR_MSECCFG, &trap, oldval | MSECCFG_RLB); + if (trap.cause) + return false; + + return (csr_swap(CSR_MSECCFG, oldval) & MSECCFG_RLB) == MSECCFG_RLB; +} + +static const struct hart_ext_validate_entry hart_ext_validators[] = { + { SBI_HART_EXT_SMEPMP, hart_ext_smepmp_validate }, +}; + +static void hart_ext_validate(struct sbi_hart_features *hfeatures) +{ + for (int i = 0; i < (int)array_size(hart_ext_validators); i++) { + const struct hart_ext_validate_entry *v = &hart_ext_validators[i]; + + if (__test_bit(v->ext, hfeatures->extensions) && !v->validate()) + __sbi_hart_update_extension(hfeatures, v->ext, false); + } +} + static int hart_detect_features(struct sbi_scratch *scratch) { struct sbi_trap_info trap = {0}; @@ -1022,6 +1057,9 @@ static int hart_detect_features(struct sbi_scratch *scratch) if (rc) return rc; + /* Validate DT-claimed extensions against actual hardware */ + hart_ext_validate(hfeatures); + /* Zicntr should only be detected using traps */ __sbi_hart_update_extension(hfeatures, SBI_HART_EXT_ZICNTR, sbi_hart_has_csr(scratch, SBI_HART_CSR_CYCLE) &&