Message ID | 20250317101956.526834-5-cleger@rivosinc.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | riscv: add SBI SSE extension tests | expand |
On Mon, Mar 17, 2025 at 11:19:50AM +0100, Clément Léger wrote: > Version checking was done using some custom hardcoded values, backport a > few SBI function and defines from Linux to do that cleanly. > > Signed-off-by: Clément Léger <cleger@rivosinc.com> > --- > lib/riscv/asm/sbi.h | 15 +++++++++++++++ > lib/riscv/sbi.c | 9 +++++++-- > 2 files changed, 22 insertions(+), 2 deletions(-) > > diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h > index 2f4d91ef..197288c7 100644 > --- a/lib/riscv/asm/sbi.h > +++ b/lib/riscv/asm/sbi.h > @@ -18,6 +18,12 @@ > #define SBI_ERR_IO -13 > #define SBI_ERR_DENIED_LOCKED -14 > > +/* SBI spec version fields */ > +#define SBI_SPEC_VERSION_DEFAULT 0x1 We don't need this define, since we don't support version 0.1. But there is another mask we should add. See below. > +#define SBI_SPEC_VERSION_MAJOR_SHIFT 24 > +#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f > +#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff > + > #ifndef __ASSEMBLER__ > #include <cpumask.h> > > @@ -110,6 +116,14 @@ struct sbiret { > long value; > }; > > +/* Make SBI version */ > +static inline unsigned long sbi_mk_version(unsigned long major, unsigned long minor) > +{ > + return ((major & SBI_SPEC_VERSION_MAJOR_MASK) << SBI_SPEC_VERSION_MAJOR_SHIFT) > + | (minor & SBI_SPEC_VERSION_MINOR_MASK); > +} > + > + Extra blank, but I see it goes away with the next patch. > struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0, > unsigned long arg1, unsigned long arg2, > unsigned long arg3, unsigned long arg4, > @@ -124,6 +138,7 @@ struct sbiret sbi_send_ipi_cpu(int cpu); > struct sbiret sbi_send_ipi_cpumask(const cpumask_t *mask); > struct sbiret sbi_send_ipi_broadcast(void); > struct sbiret sbi_set_timer(unsigned long stime_value); > +struct sbiret sbi_get_spec_version(void); > long sbi_probe(int ext); > > #endif /* !__ASSEMBLER__ */ > diff --git a/lib/riscv/sbi.c b/lib/riscv/sbi.c > index 02dd338c..3c395cff 100644 > --- a/lib/riscv/sbi.c > +++ b/lib/riscv/sbi.c > @@ -107,12 +107,17 @@ struct sbiret sbi_set_timer(unsigned long stime_value) > return sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0, 0, 0, 0, 0); > } > > +struct sbiret sbi_get_spec_version(void) > +{ > + return sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0, 0, 0, 0, 0, 0); > +} > + > long sbi_probe(int ext) > { > struct sbiret ret; > > - ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0, 0, 0, 0, 0, 0); > - assert(!ret.error && (ret.value & 0x7ffffffful) >= 2); > + ret = sbi_get_spec_version(); > + assert(!ret.error && ret.value >= sbi_mk_version(2, 0)); This changes the check from >= 0.2 to >= 2.0. Also, before, we were more tolerant with the return value potentially having upper bits set, since the spec only recently added "When XLEN is greater than 32, bits 32 and above are also reserved and must be 0." and we can leave it to the SBI tests to check those bits. IOW, this should be #define SBI_SPEC_VERSION_MASK 0x7fffffff assert(!ret.error && (ret.value & SBI_SPEC_VERSION_MASK) >= sbi_mk_version(0, 2)); > > ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, ext, 0, 0, 0, 0, 0); > assert(!ret.error); > -- > 2.47.2 > Thanks, drew
diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h index 2f4d91ef..197288c7 100644 --- a/lib/riscv/asm/sbi.h +++ b/lib/riscv/asm/sbi.h @@ -18,6 +18,12 @@ #define SBI_ERR_IO -13 #define SBI_ERR_DENIED_LOCKED -14 +/* SBI spec version fields */ +#define SBI_SPEC_VERSION_DEFAULT 0x1 +#define SBI_SPEC_VERSION_MAJOR_SHIFT 24 +#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f +#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff + #ifndef __ASSEMBLER__ #include <cpumask.h> @@ -110,6 +116,14 @@ struct sbiret { long value; }; +/* Make SBI version */ +static inline unsigned long sbi_mk_version(unsigned long major, unsigned long minor) +{ + return ((major & SBI_SPEC_VERSION_MAJOR_MASK) << SBI_SPEC_VERSION_MAJOR_SHIFT) + | (minor & SBI_SPEC_VERSION_MINOR_MASK); +} + + struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, @@ -124,6 +138,7 @@ struct sbiret sbi_send_ipi_cpu(int cpu); struct sbiret sbi_send_ipi_cpumask(const cpumask_t *mask); struct sbiret sbi_send_ipi_broadcast(void); struct sbiret sbi_set_timer(unsigned long stime_value); +struct sbiret sbi_get_spec_version(void); long sbi_probe(int ext); #endif /* !__ASSEMBLER__ */ diff --git a/lib/riscv/sbi.c b/lib/riscv/sbi.c index 02dd338c..3c395cff 100644 --- a/lib/riscv/sbi.c +++ b/lib/riscv/sbi.c @@ -107,12 +107,17 @@ struct sbiret sbi_set_timer(unsigned long stime_value) return sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0, 0, 0, 0, 0); } +struct sbiret sbi_get_spec_version(void) +{ + return sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0, 0, 0, 0, 0, 0); +} + long sbi_probe(int ext) { struct sbiret ret; - ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0, 0, 0, 0, 0, 0); - assert(!ret.error && (ret.value & 0x7ffffffful) >= 2); + ret = sbi_get_spec_version(); + assert(!ret.error && ret.value >= sbi_mk_version(2, 0)); ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, ext, 0, 0, 0, 0, 0); assert(!ret.error);
Version checking was done using some custom hardcoded values, backport a few SBI function and defines from Linux to do that cleanly. Signed-off-by: Clément Léger <cleger@rivosinc.com> --- lib/riscv/asm/sbi.h | 15 +++++++++++++++ lib/riscv/sbi.c | 9 +++++++-- 2 files changed, 22 insertions(+), 2 deletions(-)