new file mode 100644
@@ -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_ */
@@ -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();
}
new file mode 100644
@@ -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");
+}
@@ -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
new file mode 100644
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SBI verification
+ *
+ * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com>
+ */
+#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();
+}