]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
riscv: hwprobe: Add thead vendor extension probing
authorCharlie Jenkins <charlie@rivosinc.com>
Thu, 14 Nov 2024 02:21:16 +0000 (18:21 -0800)
committerPalmer Dabbelt <palmer@rivosinc.com>
Sat, 18 Jan 2025 20:33:35 +0000 (12:33 -0800)
Add a new hwprobe key "RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0" which
allows userspace to probe for the new RISCV_ISA_VENDOR_EXT_XTHEADVECTOR
vendor extension.

This new key will allow userspace code to probe for which thead vendor
extensions are supported. This API is modeled to be consistent with
RISCV_HWPROBE_KEY_IMA_EXT_0. The bitmask returned will have each bit
corresponding to a supported thead vendor extension of the cpumask set.
Just like RISCV_HWPROBE_KEY_IMA_EXT_0, this allows a userspace program
to determine all of the supported thead vendor extensions in one call.

Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Evan Green <evan@rivosinc.com>
Tested-by: Yangyu Chen <cyy@cyyself.name>
Link: https://lore.kernel.org/r/20241113-xtheadvector-v11-10-236c22791ef9@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/hwprobe.h
arch/riscv/include/asm/vendor_extensions/thead_hwprobe.h [new file with mode: 0644]
arch/riscv/include/asm/vendor_extensions/vendor_hwprobe.h [new file with mode: 0644]
arch/riscv/include/uapi/asm/hwprobe.h
arch/riscv/include/uapi/asm/vendor/thead.h [new file with mode: 0644]
arch/riscv/kernel/sys_hwprobe.c
arch/riscv/kernel/vendor_extensions/Makefile
arch/riscv/kernel/vendor_extensions/thead_hwprobe.c [new file with mode: 0644]

index 1ce1df6d0ff3c6f80a0221ec0c1755d30c425445..dd624523981c89ec196345369dfec5b58840b5cc 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
- * Copyright 2023 Rivos, Inc
+ * Copyright 2023-2024 Rivos, Inc
  */
 
 #ifndef _ASM_HWPROBE_H
@@ -8,7 +8,7 @@
 
 #include <uapi/asm/hwprobe.h>
 
-#define RISCV_HWPROBE_MAX_KEY 10
+#define RISCV_HWPROBE_MAX_KEY 11
 
 static inline bool riscv_hwprobe_key_is_valid(__s64 key)
 {
@@ -21,6 +21,7 @@ static inline bool hwprobe_key_is_bitmask(__s64 key)
        case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
        case RISCV_HWPROBE_KEY_IMA_EXT_0:
        case RISCV_HWPROBE_KEY_CPUPERF_0:
+       case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0:
                return true;
        }
 
diff --git a/arch/riscv/include/asm/vendor_extensions/thead_hwprobe.h b/arch/riscv/include/asm/vendor_extensions/thead_hwprobe.h
new file mode 100644 (file)
index 0000000..65a9c56
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RISCV_VENDOR_EXTENSIONS_THEAD_HWPROBE_H
+#define _ASM_RISCV_VENDOR_EXTENSIONS_THEAD_HWPROBE_H
+
+#include <linux/cpumask.h>
+
+#include <uapi/asm/hwprobe.h>
+
+#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_THEAD
+void hwprobe_isa_vendor_ext_thead_0(struct riscv_hwprobe *pair, const struct cpumask *cpus);
+#else
+static inline void hwprobe_isa_vendor_ext_thead_0(struct riscv_hwprobe *pair,
+                                                 const struct cpumask *cpus)
+{
+       pair->value = 0;
+}
+#endif
+
+#endif
diff --git a/arch/riscv/include/asm/vendor_extensions/vendor_hwprobe.h b/arch/riscv/include/asm/vendor_extensions/vendor_hwprobe.h
new file mode 100644 (file)
index 0000000..6b9293e
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2024 Rivos, Inc
+ */
+
+#ifndef _ASM_RISCV_SYS_HWPROBE_H
+#define _ASM_RISCV_SYS_HWPROBE_H
+
+#include <asm/cpufeature.h>
+
+#define VENDOR_EXT_KEY(ext)                                                            \
+       do {                                                                            \
+               if (__riscv_isa_extension_available(isainfo->isa, RISCV_ISA_VENDOR_EXT_##ext)) \
+                       pair->value |= RISCV_HWPROBE_VENDOR_EXT_##ext;                  \
+               else                                                                    \
+                       missing |= RISCV_HWPROBE_VENDOR_EXT_##ext;                      \
+       } while (false)
+
+/*
+ * Loop through and record extensions that 1) anyone has, and 2) anyone
+ * doesn't have.
+ *
+ * _extension_checks is an arbitrary C block to set the values of pair->value
+ * and missing. It should be filled with VENDOR_EXT_KEY expressions.
+ */
+#define VENDOR_EXTENSION_SUPPORTED(pair, cpus, per_hart_vendor_bitmap, _extension_checks)      \
+       do {                                                                                    \
+               int cpu;                                                                        \
+               u64 missing = 0;                                                                \
+               for_each_cpu(cpu, (cpus)) {                                                     \
+                       struct riscv_isavendorinfo *isainfo = &(per_hart_vendor_bitmap)[cpu];   \
+                       _extension_checks                                                       \
+               }                                                                               \
+               (pair)->value &= ~missing;                                                      \
+       } while (false)                                                                         \
+
+#endif /* _ASM_RISCV_SYS_HWPROBE_H */
index 3af142b99f778b3dfa7ebf3ed201b8be038aea51..c3c1cc951cb9426f923de88939949d613657cd50 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
- * Copyright 2023 Rivos, Inc
+ * Copyright 2023-2024 Rivos, Inc
  */
 
 #ifndef _UAPI_ASM_HWPROBE_H
@@ -94,6 +94,7 @@ struct riscv_hwprobe {
 #define                RISCV_HWPROBE_MISALIGNED_VECTOR_SLOW            2
 #define                RISCV_HWPROBE_MISALIGNED_VECTOR_FAST            3
 #define                RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED     4
+#define RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0   11
 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
 
 /* Flags */
diff --git a/arch/riscv/include/uapi/asm/vendor/thead.h b/arch/riscv/include/uapi/asm/vendor/thead.h
new file mode 100644 (file)
index 0000000..43790eb
--- /dev/null
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#define                RISCV_HWPROBE_VENDOR_EXT_XTHEADVECTOR   (1 << 0)
index 9050f324626457b688f8fad3d922f51c640c1f0f..13eff75d78a8b5d2cd9c34a0e21f0b9ae8ed9109 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/vector.h>
+#include <asm/vendor_extensions/thead_hwprobe.h>
 #include <vdso/vsyscall.h>
 
 
@@ -286,6 +287,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
                pair->value = riscv_timebase;
                break;
 
+       case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0:
+               hwprobe_isa_vendor_ext_thead_0(pair, cpus);
+               break;
+
        /*
         * For forward compatibility, unknown keys don't fail the whole
         * call, but get their element key set to -1 and value set to 0
index 353522cb3bf09790d6138a26c549d716d760e668..866414c81a9f5e7a34043918daba46e3aa54f0ec 100644 (file)
@@ -2,3 +2,4 @@
 
 obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_ANDES)       += andes.o
 obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_THEAD)       += thead.o
+obj-$(CONFIG_RISCV_ISA_VENDOR_EXT_THEAD)       += thead_hwprobe.o
diff --git a/arch/riscv/kernel/vendor_extensions/thead_hwprobe.c b/arch/riscv/kernel/vendor_extensions/thead_hwprobe.c
new file mode 100644 (file)
index 0000000..2eba340
--- /dev/null
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <asm/vendor_extensions/thead.h>
+#include <asm/vendor_extensions/thead_hwprobe.h>
+#include <asm/vendor_extensions/vendor_hwprobe.h>
+
+#include <linux/cpumask.h>
+#include <linux/types.h>
+
+#include <uapi/asm/hwprobe.h>
+#include <uapi/asm/vendor/thead.h>
+
+void hwprobe_isa_vendor_ext_thead_0(struct riscv_hwprobe *pair, const struct cpumask *cpus)
+{
+       VENDOR_EXTENSION_SUPPORTED(pair, cpus,
+                                  riscv_isa_vendor_ext_list_thead.per_hart_isa_bitmap, {
+               VENDOR_EXT_KEY(XTHEADVECTOR);
+       });
+}