Add an SBI call function and immediately apply it to properly exiting the test (instead of hanging) by invoking SBI shutdown from exit(). Also seed an SBI test file with a simple SBI test that checks mvendorid is correctly extracted. Run with e.g. qemu-system-riscv64 -nographic -M virt \ -kernel riscv/sbi.flat \ -cpu rv64,mvendorid=45 \ -initrd sbi-env and be happy that ctrl-a c q is no longer necessary to return to the shell prompt. sbi-env has MVENDORID=45 in it. Signed-off-by: Andrew Jones <andrew.jones@xxxxxxxxx> Acked-by: Thomas Huth <thuth@xxxxxxxxxx> --- lib/riscv/asm/sbi.h | 32 ++++++++++++++++++++++++++++++++ lib/riscv/io.c | 2 ++ lib/riscv/sbi.c | 35 +++++++++++++++++++++++++++++++++++ riscv/Makefile | 2 ++ riscv/sbi.c | 41 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+) create mode 100644 lib/riscv/asm/sbi.h create mode 100644 lib/riscv/sbi.c create mode 100644 riscv/sbi.c diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h new file mode 100644 index 000000000000..aeff07f6f1a8 --- /dev/null +++ b/lib/riscv/asm/sbi.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _ASMRISCV_SBI_H_ +#define _ASMRISCV_SBI_H_ + +enum sbi_ext_id { + SBI_EXT_BASE = 0x10, + SBI_EXT_SRST = 0x53525354, +}; + +enum sbi_ext_base_fid { + SBI_EXT_BASE_GET_SPEC_VERSION = 0, + SBI_EXT_BASE_GET_IMP_ID, + SBI_EXT_BASE_GET_IMP_VERSION, + SBI_EXT_BASE_PROBE_EXT, + SBI_EXT_BASE_GET_MVENDORID, + SBI_EXT_BASE_GET_MARCHID, + SBI_EXT_BASE_GET_MIMPID, +}; + +struct sbiret { + long error; + long value; +}; + +struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5); + +void sbi_shutdown(void); + +#endif /* _ASMRISCV_SBI_H_ */ diff --git a/lib/riscv/io.c b/lib/riscv/io.c index aeda74be61ee..b3f587bb68ca 100644 --- a/lib/riscv/io.c +++ b/lib/riscv/io.c @@ -9,6 +9,7 @@ #include <config.h> #include <devicetree.h> #include <asm/io.h> +#include <asm/sbi.h> #include <asm/setup.h> #include <asm/spinlock.h> @@ -90,6 +91,7 @@ void halt(int code); void exit(int code) { printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1); + sbi_shutdown(); halt(code); __builtin_unreachable(); } diff --git a/lib/riscv/sbi.c b/lib/riscv/sbi.c new file mode 100644 index 000000000000..fd758555b888 --- /dev/null +++ b/lib/riscv/sbi.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <libcflat.h> +#include <asm/sbi.h> + +struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5) +{ + register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0); + register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1); + register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2); + register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3); + register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4); + register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5); + register uintptr_t a6 asm ("a6") = (uintptr_t)(fid); + register uintptr_t a7 asm ("a7") = (uintptr_t)(ext); + struct sbiret ret; + + asm volatile ( + "ecall" + : "+r" (a0), "+r" (a1) + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) + : "memory"); + ret.error = a0; + ret.value = a1; + + return ret; +} + +void sbi_shutdown(void) +{ + sbi_ecall(SBI_EXT_SRST, 0, 0, 0, 0, 0, 0, 0); + puts("SBI shutdown failed!\n"); +} diff --git a/riscv/Makefile b/riscv/Makefile index ddf2a0e016a8..4e7fcc538ba1 100644 --- a/riscv/Makefile +++ b/riscv/Makefile @@ -11,6 +11,7 @@ exe = flat endif tests = +tests += $(TEST_DIR)/sbi.$(exe) tests += $(TEST_DIR)/selftest.$(exe) #tests += $(TEST_DIR)/sieve.$(exe) @@ -25,6 +26,7 @@ cflatobjs += lib/alloc_phys.o cflatobjs += lib/devicetree.o cflatobjs += lib/riscv/bitops.o cflatobjs += lib/riscv/io.o +cflatobjs += lib/riscv/sbi.o cflatobjs += lib/riscv/setup.o cflatobjs += lib/riscv/smp.o diff --git a/riscv/sbi.c b/riscv/sbi.c new file mode 100644 index 000000000000..ffb07a256ff6 --- /dev/null +++ b/riscv/sbi.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SBI verification + * + * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@xxxxxxxxxxxxxxxx> + */ +#include <libcflat.h> +#include <stdlib.h> +#include <asm/sbi.h> + +static void help(void) +{ + puts("Test SBI\n"); + puts("An environ must be provided where expected values are given.\n"); +} + +int main(int argc, char **argv) +{ + struct sbiret ret; + long expected; + + if (argc > 1 && !strcmp(argv[1], "-h")) { + help(); + exit(0); + } + + report_prefix_push("sbi"); + + if (!getenv("MVENDORID")) { + report_skip("mvendorid: missing MVENDORID environment variable"); + goto done; + } + expected = strtol(getenv("MVENDORID"), NULL, 0); + + ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID, 0, 0, 0, 0, 0, 0); + report(!ret.error, "mvendorid: no error"); + report(ret.value == expected, "mvendorid"); + +done: + return report_summary(); +} -- 2.43.0