[PATCH 07/12] RISC-V: add SBI based cpuinfo

Ahmad Fatoum a.fatoum at pengutronix.de
Tue Apr 27 21:23:04 BST 2021


SBI appeared to be especially useful to implement a generic console
driver. However, SBI v0.2 removes these services without substitute.

We might find other use for it later, but for now, add the bare minimum
of querying the version of the running SBI implementation.

The cpuinfo command is intentionally kept generic. It can later be
extended to support CONFIG_RISCV_M_MODE as well.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/riscv/include/asm/sbi.h | 32 +++++++++++++++----
 arch/riscv/lib/Makefile      |  2 ++
 arch/riscv/lib/cpuinfo.c     | 45 ++++++++++++++++++++++++++
 arch/riscv/lib/sbi.c         | 62 ++++++++++++++++++++++++++++++++++++
 commands/Kconfig             |  7 ++++
 5 files changed, 142 insertions(+), 6 deletions(-)
 create mode 100644 arch/riscv/lib/cpuinfo.c
 create mode 100644 arch/riscv/lib/sbi.c

diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index 99895d9c3bdd..ab1fc9a128e5 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -89,11 +89,32 @@ struct sbiret {
 	long value;
 };
 
-void sbi_init(void);
-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);
+static inline 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)
+{
+	struct sbiret ret;
+
+	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);
+	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;
+}
+
+long __sbi_base_ecall(int fid);
 
 void sbi_console_putchar(int ch);
 int sbi_console_getchar(void);
@@ -148,6 +169,5 @@ static inline unsigned long sbi_minor_version(void)
 int sbi_err_map_linux_errno(int err);
 #else /* CONFIG_RISCV_SBI */
 static inline int sbi_remote_fence_i(const unsigned long *hart_mask) { return -1; }
-static inline void sbi_init(void) {}
 #endif /* CONFIG_RISCV_SBI */
 #endif /* _ASM_RISCV_SBI_H */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index a4eaa1005d44..49750d576ae1 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -6,3 +6,5 @@ obj-y += dtb.o
 obj-pbl-y += sections.o setupc.o reloc.o sections.o runtime-offset.o
 obj-$(CONFIG_HAS_ARCH_SJLJ) += setjmp.o longjmp.o
 obj-$(CONFIG_RISCV_OPTIMZED_STRING_FUNCTIONS) += memcpy.o memset.o memmove.o
+obj-$(CONFIG_RISCV_SBI) += sbi.o
+obj-$(CONFIG_CMD_RISCV_CPUINFO) += cpuinfo.o
diff --git a/arch/riscv/lib/cpuinfo.c b/arch/riscv/lib/cpuinfo.c
new file mode 100644
index 000000000000..21b99a990a1a
--- /dev/null
+++ b/arch/riscv/lib/cpuinfo.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <common.h>
+#include <command.h>
+#include <asm/sbi.h>
+
+static const char *implementations[] = {
+	[0] = "\"Berkeley Boot Loader (BBL)\" ",
+	[1] = "\"OpenSBI\" ",
+	[2] = "\"Xvisor\" ",
+	[3] = "\"KVM\" ",
+	[4] = "\"RustSBI\" ",
+	[5] = "\"Diosix\" ",
+};
+
+static int do_cpuinfo(int argc, char *argv[])
+{
+	const char *implementation = "";
+	unsigned long impid;
+
+	printf("SBI specification v%lu.%lu detected\n",
+	       sbi_major_version(), sbi_minor_version());
+
+	if (sbi_spec_is_0_1())
+		return 0;
+
+	impid = __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_ID);
+	if (impid < ARRAY_SIZE(implementations))
+		implementation = implementations[impid];
+
+	printf("SBI implementation ID=0x%lx %sVersion=0x%lx\n",
+	       impid, implementation, __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_VERSION));
+
+	printf("SBI Machine VENDORID=0x%lx ARCHID=0x%lx MIMPID=0x%lx\n",
+	       __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID),
+	       __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID),
+	       __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID));
+
+	return 0;
+}
+
+BAREBOX_CMD_START(cpuinfo)
+	.cmd            = do_cpuinfo,
+BAREBOX_CMD_DESC("show CPU information")
+BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+	BAREBOX_CMD_END
diff --git a/arch/riscv/lib/sbi.c b/arch/riscv/lib/sbi.c
new file mode 100644
index 000000000000..973c9d9d0f1e
--- /dev/null
+++ b/arch/riscv/lib/sbi.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SBI initialilization and all extension implementation.
+ *
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+
+#include <asm/sbi.h>
+#include <linux/export.h>
+#include <errno.h>
+#include <init.h>
+
+/* default SBI version is 0.1 */
+unsigned long sbi_spec_version = SBI_SPEC_VERSION_DEFAULT;
+EXPORT_SYMBOL(sbi_spec_version);
+
+int sbi_err_map_linux_errno(int err)
+{
+	switch (err) {
+	case SBI_SUCCESS:
+		return 0;
+	case SBI_ERR_DENIED:
+		return -EPERM;
+	case SBI_ERR_INVALID_PARAM:
+		return -EINVAL;
+	case SBI_ERR_INVALID_ADDRESS:
+		return -EFAULT;
+	case SBI_ERR_NOT_SUPPORTED:
+	case SBI_ERR_FAILURE:
+	default:
+		return -ENOTSUPP;
+	};
+}
+EXPORT_SYMBOL(sbi_err_map_linux_errno);
+
+long __sbi_base_ecall(int fid)
+{
+	struct sbiret ret;
+
+	ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0);
+	if (!ret.error)
+		return ret.value;
+	else
+		return sbi_err_map_linux_errno(ret.error);
+}
+
+static inline long sbi_get_spec_version(void)
+{
+	return __sbi_base_ecall(SBI_EXT_BASE_GET_SPEC_VERSION);
+}
+
+static int sbi_init(void)
+{
+	int ret;
+
+	ret = sbi_get_spec_version();
+	if (ret > 0)
+		sbi_spec_version = ret;
+	return 0;
+
+}
+core_initcall(sbi_init);
diff --git a/commands/Kconfig b/commands/Kconfig
index b3937fdd8df8..5ae3cb3dd145 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -44,6 +44,13 @@ config CMD_ARM_CPUINFO
 	  D-cache: 8192 bytes (linelen = 8)
 	  Control register: M C W P D L I V RR DT IT U XP
 
+config CMD_RISCV_CPUINFO
+	bool "cpuinfo command"
+	default y
+	depends on RISCV_SBI
+	help
+	  Show SBI info about RISC-V CPU
+
 config CMD_DEVINFO
 	tristate
 	default y
-- 
2.29.2




More information about the barebox mailing list