[kvm-unit-tests PATCH 7/7] riscv: Add BRS SBI requirement tests
Xiang W
wangxiang at iscas.ac.cn
Tue Oct 6 06:03:03 PDT 2026
在 2026-09-30三的 13:19 +0200,Andrew Jones写道:
> On Thu, Sep 24, 2026 at 11:39:45AM +0800, Xiang W wrote:
> > Add a riscv-brs unit test for the SBI rules in the RISC-V Boot and
> > Runtime Services specification:
> >
> > SBI_010 spec version must be v2.0 or later
> > SBI_020 HSM must be implemented
> > SBI_030 TIME is required unless Sstc is present
> > SBI_040 IPI is required unless Ssaia is present
> > SBI_050 RFENCE is required unless Ssaia is present
> > SBI_060 PMU is required unless Smcsrind, Sscsrind, Smcdeleg
> > and Ssccfg are all present
> > SBI_070 DBCN is required when ACPI SPCR Interface Type is 0x15
> >
> > Parse the extra ISA names used as skip conditions, and add the RFNC
> > and PMU extension IDs needed to probe those extensions.
> >
> > Signed-off-by: Xiang W <wangxiang at iscas.ac.cn>
> > ---
> > lib/riscv/asm/isa.h | 5 ++
> > lib/riscv/asm/sbi.h | 2 +
> > lib/riscv/isa.c | 14 +++-
> > riscv/Makefile | 1 +
> > riscv/riscv-brs.c | 171 ++++++++++++++++++++++++++++++++++++++++++++
> > riscv/unittests.cfg | 4 ++
> > 6 files changed, 195 insertions(+), 2 deletions(-)
> > create mode 100644 riscv/riscv-brs.c
> >
> > diff --git a/lib/riscv/asm/isa.h b/lib/riscv/asm/isa.h
> > index fb3af67d..8a124881 100644
> > --- a/lib/riscv/asm/isa.h
> > +++ b/lib/riscv/asm/isa.h
> > @@ -13,7 +13,12 @@
> > * by name not tracked here with cpu_has_extension_name()
> > */
> > enum {
> > + ISA_SMCDELEG,
> > + ISA_SMCSRIND,
>
> I'm not sure we should expect machine level ISA extensions to be in the
> S-mode ISA string.
>
> Indeed the spec says
>
> """
> The Performance Monitoring Extension (PMU) MUST be implemented, if the
> counter delegation-related S-Mode ISA extensions (Sscsrind [13] and Ssccfg [14])
> are not present.
> """
>
> So I'm not sure why you're looking for the M-mode extensions at all.
https://github.com/riscv-non-isa/riscv-brs/blob/main/brs_tests.adoc
OE_SBI_060_010:
. If Smcsrind,Sscsrind,Smcdeleg,Ssccfg extensions were present(See ME_HR_010_010). ..
Report Smcsrind,Sscsrind,Smcdeleg,Ssccfg was present and Skip the test. . Else ..
Probe the presence of PMU extension by sbi_probe_extension(). ..
Verify that the result is true.
>
> > + ISA_SSAIA,
> > + ISA_SSCCFG,
> > ISA_SSTC,
> > + ISA_SSCSRIND,
> > ISA_MAX,
> > };
> > __static_assert(ISA_MAX <= __riscv_xlen, "Need to increase thread_info.isa");
> > diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h
> > index 289a6a24..c92a66dc 100644
> > --- a/lib/riscv/asm/sbi.h
> > +++ b/lib/riscv/asm/sbi.h
> > @@ -45,8 +45,10 @@ enum sbi_ext_id {
> > SBI_EXT_BASE = 0x10,
> > SBI_EXT_TIME = 0x54494d45,
> > SBI_EXT_IPI = 0x735049,
> > + SBI_EXT_RFNC = 0x52464E43,
> > SBI_EXT_HSM = 0x48534d,
> > SBI_EXT_SRST = 0x53525354,
> > + SBI_EXT_PMU = 0x504D55,
> > SBI_EXT_DBCN = 0x4442434E,
> > SBI_EXT_SUSP = 0x53555350,
> > SBI_EXT_FWFT = 0x46574654,
> > diff --git a/lib/riscv/isa.c b/lib/riscv/isa.c
> > index b0257979..f5e2a61b 100644
> > --- a/lib/riscv/isa.c
> > +++ b/lib/riscv/isa.c
> > @@ -39,8 +39,18 @@ static void isa_bit(const char *name, int len, void *data)
> > {
> > struct thread_info *info = (struct thread_info *)data;
> >
> > - if (isa_match("sstc", name, len))
> > - set_bit(ISA_SSTC, info->isa);
> > +#define ISA_MATCH_AND_SET(ext) \
> > + if (isa_match(#ext, name, len)) \
> > + set_bit(ISA_##ext, info->isa)
> > +
> > + ISA_MATCH_AND_SET(SMCDELEG);
> > + ISA_MATCH_AND_SET(SMCSRIND);
> > + ISA_MATCH_AND_SET(SSAIA);
> > + ISA_MATCH_AND_SET(SSCCFG);
> > + ISA_MATCH_AND_SET(SSCSRIND);
> > + ISA_MATCH_AND_SET(SSTC);
> > +
> > +#undef ISA_MATCH_AND_SET
> > }
> >
> > static void isa_parse(const char *isa_string, int len, struct isa_info *info)
> > diff --git a/riscv/Makefile b/riscv/Makefile
> > index 348a30a7..7da7526f 100644
> > --- a/riscv/Makefile
> > +++ b/riscv/Makefile
> > @@ -15,6 +15,7 @@ tests += $(TEST_DIR)/sbi.$(exe)
> > tests += $(TEST_DIR)/selftest.$(exe)
> > tests += $(TEST_DIR)/sieve.$(exe)
> > tests += $(TEST_DIR)/isa-dbltrp.$(exe)
> > +tests += $(TEST_DIR)/riscv-brs.$(exe)
> >
> > all: $(tests)
> >
> > diff --git a/riscv/riscv-brs.c b/riscv/riscv-brs.c
> > new file mode 100644
> > index 00000000..0d4a8f47
> > --- /dev/null
> > +++ b/riscv/riscv-brs.c
> > @@ -0,0 +1,171 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * RISC-V BRS SBI requirement tests
> > + *
> > + * Copyright (C) 2026, Institute of Software, CAS., Xiang W <wangxiang at iscas.ac.cn>
> > + */
> > +
> > +#include <libcflat.h>
> > +#include <devicetree.h>
> > +#include <asm/sbi.h>
> > +#include <asm/isa.h>
> > +#include <asm/smp.h>
> > +
> > +#ifdef CONFIG_EFI
> > +#include <acpi.h>
> > +#endif
> > +
> > +static void check_sbi_010(void)
> > +{
> > + struct sbiret ret;
> > +
> > + report_prefix_push("SBI_010");
> > +
> > + ret = sbi_get_spec_version();
> > + if (ret.error) {
> > + report_fail("sbi_get_spec_version failed with %ld", ret.error);
> > + report_prefix_pop();
> > + return;
> > + }
> > +
> > + report_info("SBI spec version %lu.%lu",
> > + (ret.value >> SBI_SPEC_VERSION_MAJOR_SHIFT) &
> > + SBI_SPEC_VERSION_MAJOR_MASK,
> > + ret.value & SBI_SPEC_VERSION_MINOR_MASK);
> > +
> > + report(ret.value >= sbi_mk_version(2, 0),
> > + "SBI spec version is v2.0 or later");
> > +
> > + report_prefix_pop();
> > +}
> > +
> > +static void check_sbi_020(void)
> > +{
> > + report_prefix_push("SBI_020");
> > + report(sbi_probe(SBI_EXT_HSM), "HSM extension is implemented");
> > + report_prefix_pop();
> > +}
> > +
> > +static void check_sbi_030(void)
> > +{
> > + report_prefix_push("SBI_030");
> > +
> > + if (cpu_has_extension(smp_processor_id(), ISA_SSTC)) {
> > + report_skip("Sstc is present, TIME is not mandated");
> > + report_prefix_pop();
> > + return;
> > + }
> > +
> > + report(sbi_probe(SBI_EXT_TIME), "TIME extension is implemented");
> > + report_prefix_pop();
> > +}
> > +
> > +static void check_sbi_040(void)
> > +{
> > + report_prefix_push("SBI_040");
> > +
> > + if (cpu_has_extension(smp_processor_id(), ISA_SSAIA)) {
>
> I'm not sure this is a sufficient check. IIRC, the IMSIC is an optional
> feature of the AIA and the BRS rule states:
>
> """
> The S-Mode IPI Extension (sPI) MUST be implemented, if the Incoming MSI
> Controller (IMSIC, [12]) is not available.
> """
>
> I think we should check both ISA_SSAIA and ensure each hart has a nonzero
> acpi_madt_rintc.imsic_size. (And, unless, I'm mistaken, the BRS SBI rules
> apply to both BRS-I and BRS-B, so we should implement a DT equivalent
> IMSIC check too.)
>
https://github.com/riscv-non-isa/riscv-brs/blob/main/brs_tests.adoc
OE_SBI_040_010:
. If Ssaia extension was present(See ME_HR_010_010) .. Report Ssaia was
present and Skip the test. . Else .. Probe the presence of sPI extension
by sbi_probe_extension(). .. Verify that the result is true.
>
> > + report_skip("Ssaia is present, IPI is not mandated");
> > + report_prefix_pop();
> > + return;
> > + }
> > +
> > + report(sbi_probe(SBI_EXT_IPI), "IPI extension is implemented");
> > + report_prefix_pop();
> > +}
> > +
> > +static void check_sbi_050(void)
> > +{
> > + report_prefix_push("SBI_050");
> > +
> > + if (cpu_has_extension(smp_processor_id(), ISA_SSAIA)) {
> > + report_skip("Ssaia is present, RFENCE is not mandated");
> > + report_prefix_pop();
> > + return;
> > + }
> > +
> > + report(sbi_probe(SBI_EXT_RFNC), "RFENCE extension is implemented");
> > + report_prefix_pop();
> > +}
> > +
> > +static void check_sbi_060(void)
> > +{
> > + int cpu = smp_processor_id();
> > + bool skip = true;
> > + bool has_ext;
> > +
> > + report_prefix_push("SBI_060");
> > +
> > + has_ext = cpu_has_extension(cpu, ISA_SMCSRIND);
> > + if (!has_ext)
> > + report_info("Smcsrind is not present");
> > + skip &= has_ext;
> > +
> > + has_ext = cpu_has_extension(cpu, ISA_SSCSRIND);
> > + if (!has_ext)
> > + report_info("Sscsrind is not present");
> > + skip &= has_ext;
> > +
> > + has_ext = cpu_has_extension(cpu, ISA_SMCDELEG);
> > + if (!has_ext)
> > + report_info("Smcdeleg is not present");
> > + skip &= has_ext;
> > +
> > + has_ext = cpu_has_extension(cpu, ISA_SSCCFG);
> > + if (!has_ext)
> > + report_info("Ssccfg is not present");
> > + skip &= has_ext;
> > +
> > + if (skip) {
> > + report_skip("Smcsrind, Sscsrind, Smcdeleg and Ssccfg are present, PMU is not mandated");
> > + report_prefix_pop();
> > + return;
> > + }
> > +
> > + report(sbi_probe(SBI_EXT_PMU), "PMU extension is implemented");
> > + report_prefix_pop();
> > +}
> > +
> > +static void check_sbi_070(void)
> > +{
> > + report_prefix_push("SBI_070");
> > +
> > +#ifdef CONFIG_EFI
> > + if (!dt_available()) {
> > + struct spcr_descriptor *spcr;
> > +
> > + spcr = find_acpi_table_addr(SPCR_SIGNATURE);
> > + if (spcr) {
> > + report_info("SPCR interface type is %#x", spcr->interface_type);
> > + if (spcr->interface_type == 0x15) {
> > + report(sbi_probe(SBI_EXT_DBCN), "DBCN extension is implemented");
> > + report_prefix_pop();
> > + return;
> > + }
> > + report_skip("SPCR interface type is not 0x15, DBCN is not mandated");
> > + report_prefix_pop();
> > + return;
> > + }
> > + report_skip("SPCR is not present, DBCN is not mandated");
> > + report_prefix_pop();
> > + return;
>
> nit: could use a goto to get rid of the repeated
>
> report_prefix_pop();
> return;
>
> lines.
>
> > + }
> > +#endif
> > + report_skip("ACPI not available, DBCN is not mandated");
> > + report_prefix_pop();
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > + report_prefix_push("riscv-brs");
> > +
> > + check_sbi_010();
> > + check_sbi_020();
> > + check_sbi_030();
> > + check_sbi_040();
> > + check_sbi_050();
> > + check_sbi_060();
> > + check_sbi_070();
> > +
> > + return report_summary();
> > +}
> > diff --git a/riscv/unittests.cfg b/riscv/unittests.cfg
> > index 9e9f58d9..990f03db 100644
> > --- a/riscv/unittests.cfg
> > +++ b/riscv/unittests.cfg
> > @@ -22,3 +22,7 @@ groups = sbi
> > [dbltrp]
> > file = isa-dbltrp.flat
> > groups = isa sbi
> > +
> > +[riscv-brs]
> > +file = riscv-brs.flat
> > +groups = riscv-brs nodefault
> > --
> > 2.47.3
> >
>
> Thanks,
> drew
drew
Sorry, my previous reply went only to you. Resending to the list.
More information about the kvm-riscv
mailing list