[PATCH 1/3] RISC-V: Framework for vendor extensions

Charlie Jenkins
2023-07-06T03:32:54Z

Create Kconfig files, Makefiles, and functions to enable vendors to
provide information via the riscv_hwprobe syscall about which vendor
extensions are available.

Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
---
arch/riscv/Kbuild | 1 +
arch/riscv/Kconfig | 1 +
arch/riscv/Kconfig.vendor | 3 +++
arch/riscv/include/asm/hwprobe.h | 1 +
arch/riscv/kernel/sys_riscv.c | 40 ++++++++++++++++++++++++++++++++---
arch/riscv/vendor_extensions/Makefile | 3 +++
6 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/Kbuild b/arch/riscv/Kbuild
index afa83e307a2e..bea38010d9db 100644
--- a/arch/riscv/Kbuild
+++ b/arch/riscv/Kbuild
@@ -3,6 +3,7 @@
obj-y += kernel/ mm/ net/
obj-$(CONFIG_BUILTIN_DTB) += boot/dts/
obj-y += errata/
+obj-y += vendor_extensions/
obj-$(CONFIG_KVM) += kvm/

obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += purgatory/
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index c1505c7729ec..19404ede0ee3 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -276,6 +276,7 @@ config AS_HAS_OPTION_ARCH

source "arch/riscv/Kconfig.socs"
source "arch/riscv/Kconfig.errata"
+source "arch/riscv/Kconfig.vendor"

menu "Platform type"

diff --git a/arch/riscv/Kconfig.vendor b/arch/riscv/Kconfig.vendor
new file mode 100644
index 000000000000..213ac3e6fed5
--- /dev/null
+++ b/arch/riscv/Kconfig.vendor
@@ -0,0 +1,3 @@
+menu "Vendor extensions selection"
+
+endmenu # "Vendor extensions selection"
diff --git a/arch/riscv/include/asm/hwprobe.h b/arch/riscv/include/asm/hwprobe.h
index 78936f4ff513..fadb38b83243 100644
--- a/arch/riscv/include/asm/hwprobe.h
+++ b/arch/riscv/include/asm/hwprobe.h
@@ -9,5 +9,6 @@
#include <uapi/asm/hwprobe.h>

#define RISCV_HWPROBE_MAX_KEY 5
+#define RISCV_HWPROBE_VENDOR_EXTENSION_SPACE (UL(1)<<63)

#endif
diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c
index 26ef5526bfb4..2351a5f7b8b1 100644
--- a/arch/riscv/kernel/sys_riscv.c
+++ b/arch/riscv/kernel/sys_riscv.c
@@ -188,9 +188,35 @@ static u64 hwprobe_misaligned(const struct cpumask *cpus)
return perf;
}

+static int hwprobe_vendor(__u64 mvendorid, struct riscv_hwprobe *pair,
+ const struct cpumask *cpus)
+{
+ switch (mvendorid) {
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
static void hwprobe_one_pair(struct riscv_hwprobe *pair,
const struct cpumask *cpus)
{
+ int err;
+
+ if (((unsigned long) pair->key) >= RISCV_HWPROBE_VENDOR_EXTENSION_SPACE) {
+ struct riscv_hwprobe mvendorid = {
+ .key = RISCV_HWPROBE_KEY_MVENDORID,
+ .value = 0
+ };
+
+ hwprobe_arch_id(&mvendorid, cpus);
+ if (mvendorid.value != -1ULL)
+ err = hwprobe_vendor(mvendorid.value, pair, cpus);
+ else
+ err = -1;
+ }
+
switch (pair->key) {
case RISCV_HWPROBE_KEY_MVENDORID:
case RISCV_HWPROBE_KEY_MARCHID:
@@ -217,13 +243,21 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,

/*
* For forward compatibility, unknown keys don't fail the whole
- * call, but get their element key set to -1 and value set to 0
- * indicating they're unrecognized.
+ * call, instead an error is raised to indicate the element key
+ * is unrecognized.
*/
default:
+ err = -1;
+ break;
+ }
+
+ /*
+ * Setting the element key to -1 and value to 0 indicates that
+ * hwprobe was unable to find the requested key.
+ */
+ if (err != 0) {
pair->key = -1;
pair->value = 0;
- break;
}
}

diff --git a/arch/riscv/vendor_extensions/Makefile b/arch/riscv/vendor_extensions/Makefile
new file mode 100644
index 000000000000..e815895e9372
--- /dev/null
+++ b/arch/riscv/vendor_extensions/Makefile
@@ -0,0 +1,3 @@
+ifdef CONFIG_RELOCATABLE
+KBUILD_CFLAGS += -fno-pie
+endif

--
2.41.0