Commit 16252e01 authored by Palmer Dabbelt's avatar Palmer Dabbelt

Merge patch series "RISC-V: Export Zba, Zbb to usermode via hwprobe"

Evan Green <evan@rivosinc.com> says:

This change detects the presence of Zba, Zbb, and Zbs extensions and exports
them per-hart to userspace via the hwprobe mechanism. Glibc can then use
these in setting up hwcaps-based library search paths.

There's a little bit of extra housekeeping here: the first change adds
Zba and Zbs to the set of extensions the kernel recognizes, and the second
change starts tracking ISA features per-hart (in addition to the ANDed
mask of features across all harts which the kernel uses to make
decisions). Now that we track the ISA information per-hart, we could
even fix up /proc/cpuinfo to accurately report extension per-hart,
though I've left that out of this series for now.

* b4-shazam-merge:
  RISC-V: hwprobe: Expose Zba, Zbb, and Zbs
  RISC-V: Track ISA extensions per hart
  RISC-V: Add Zba, Zbs extension probing

Link: https://lore.kernel.org/r/20230509182504.2997252-1-evan@rivosinc.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parents f2023385 c0baf321
...@@ -67,6 +67,16 @@ The following keys are defined: ...@@ -67,6 +67,16 @@ The following keys are defined:
* :c:macro:`RISCV_HWPROBE_IMA_V`: The V extension is supported, as defined by * :c:macro:`RISCV_HWPROBE_IMA_V`: The V extension is supported, as defined by
version 1.0 of the RISC-V Vector extension manual. version 1.0 of the RISC-V Vector extension manual.
* :c:macro:`RISCV_HWPROBE_EXT_ZBA`: The Zba address generation extension is
supported, as defined in version 1.0 of the Bit-Manipulation ISA
extensions.
* :c:macro:`RISCV_HWPROBE_EXT_ZBB`: The Zbb extension is supported, as defined
in version 1.0 of the Bit-Manipulation ISA extensions.
* :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined
in version 1.0 of the Bit-Manipulation ISA extensions.
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance * :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance
information about the selected set of processors. information about the selected set of processors.
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#ifndef _ASM_CPUFEATURE_H #ifndef _ASM_CPUFEATURE_H
#define _ASM_CPUFEATURE_H #define _ASM_CPUFEATURE_H
#include <linux/bitmap.h>
#include <asm/hwcap.h>
/* /*
* These are probed via a device_initcall(), via either the SBI or directly * These are probed via a device_initcall(), via either the SBI or directly
* from the corresponding CSRs. * from the corresponding CSRs.
...@@ -16,8 +19,15 @@ struct riscv_cpuinfo { ...@@ -16,8 +19,15 @@ struct riscv_cpuinfo {
unsigned long mimpid; unsigned long mimpid;
}; };
struct riscv_isainfo {
DECLARE_BITMAP(isa, RISCV_ISA_EXT_MAX);
};
DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
DECLARE_PER_CPU(long, misaligned_access_speed); DECLARE_PER_CPU(long, misaligned_access_speed);
/* Per-cpu ISA extensions. */
extern struct riscv_isainfo hart_isa[NR_CPUS];
#endif #endif
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#define RISCV_ISA_EXT_ZICBOZ 34 #define RISCV_ISA_EXT_ZICBOZ 34
#define RISCV_ISA_EXT_SMAIA 35 #define RISCV_ISA_EXT_SMAIA 35
#define RISCV_ISA_EXT_SSAIA 36 #define RISCV_ISA_EXT_SSAIA 36
#define RISCV_ISA_EXT_ZBA 37
#define RISCV_ISA_EXT_ZBS 38
#define RISCV_ISA_EXT_MAX 64 #define RISCV_ISA_EXT_MAX 64
#define RISCV_ISA_EXT_NAME_LEN_MAX 32 #define RISCV_ISA_EXT_NAME_LEN_MAX 32
......
...@@ -26,6 +26,9 @@ struct riscv_hwprobe { ...@@ -26,6 +26,9 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_IMA_FD (1 << 0) #define RISCV_HWPROBE_IMA_FD (1 << 0)
#define RISCV_HWPROBE_IMA_C (1 << 1) #define RISCV_HWPROBE_IMA_C (1 << 1)
#define RISCV_HWPROBE_IMA_V (1 << 2) #define RISCV_HWPROBE_IMA_V (1 << 2)
#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
#define RISCV_HWPROBE_KEY_CPUPERF_0 5 #define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) #define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
......
...@@ -187,7 +187,9 @@ static struct riscv_isa_ext_data isa_ext_arr[] = { ...@@ -187,7 +187,9 @@ static struct riscv_isa_ext_data isa_ext_arr[] = {
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM), __RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
__RISCV_ISA_EXT_DATA(zicboz, RISCV_ISA_EXT_ZICBOZ), __RISCV_ISA_EXT_DATA(zicboz, RISCV_ISA_EXT_ZICBOZ),
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE), __RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
__RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA),
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB), __RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
__RISCV_ISA_EXT_DATA(zbs, RISCV_ISA_EXT_ZBS),
__RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA), __RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA),
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA), __RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
......
...@@ -30,6 +30,9 @@ unsigned long elf_hwcap __read_mostly; ...@@ -30,6 +30,9 @@ unsigned long elf_hwcap __read_mostly;
/* Host ISA bitmap */ /* Host ISA bitmap */
static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly; static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
/* Per-cpu ISA extensions. */
struct riscv_isainfo hart_isa[NR_CPUS];
/* Performance information */ /* Performance information */
DEFINE_PER_CPU(long, misaligned_access_speed); DEFINE_PER_CPU(long, misaligned_access_speed);
...@@ -126,8 +129,8 @@ void __init riscv_fill_hwcap(void) ...@@ -126,8 +129,8 @@ void __init riscv_fill_hwcap(void)
} }
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
struct riscv_isainfo *isainfo = &hart_isa[cpu];
unsigned long this_hwcap = 0; unsigned long this_hwcap = 0;
DECLARE_BITMAP(this_isa, RISCV_ISA_EXT_MAX);
const char *temp; const char *temp;
if (acpi_disabled) { if (acpi_disabled) {
...@@ -159,7 +162,6 @@ void __init riscv_fill_hwcap(void) ...@@ -159,7 +162,6 @@ void __init riscv_fill_hwcap(void)
/* The riscv,isa DT property must start with rv64 or rv32 */ /* The riscv,isa DT property must start with rv64 or rv32 */
if (temp == isa) if (temp == isa)
continue; continue;
bitmap_zero(this_isa, RISCV_ISA_EXT_MAX);
for (; *isa; ++isa) { for (; *isa; ++isa) {
const char *ext = isa++; const char *ext = isa++;
const char *ext_end = isa; const char *ext_end = isa;
...@@ -239,7 +241,7 @@ void __init riscv_fill_hwcap(void) ...@@ -239,7 +241,7 @@ void __init riscv_fill_hwcap(void)
if ((ext_end - ext == sizeof(name) - 1) && \ if ((ext_end - ext == sizeof(name) - 1) && \
!strncasecmp(ext, name, sizeof(name) - 1) && \ !strncasecmp(ext, name, sizeof(name) - 1) && \
riscv_isa_extension_check(bit)) \ riscv_isa_extension_check(bit)) \
set_bit(bit, this_isa); \ set_bit(bit, isainfo->isa); \
} while (false) \ } while (false) \
if (unlikely(ext_err)) if (unlikely(ext_err))
...@@ -249,7 +251,7 @@ void __init riscv_fill_hwcap(void) ...@@ -249,7 +251,7 @@ void __init riscv_fill_hwcap(void)
if (riscv_isa_extension_check(nr)) { if (riscv_isa_extension_check(nr)) {
this_hwcap |= isa2hwcap[nr]; this_hwcap |= isa2hwcap[nr];
set_bit(nr, this_isa); set_bit(nr, isainfo->isa);
} }
} else { } else {
/* sorted alphabetically */ /* sorted alphabetically */
...@@ -260,7 +262,9 @@ void __init riscv_fill_hwcap(void) ...@@ -260,7 +262,9 @@ void __init riscv_fill_hwcap(void)
SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL); SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL);
SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT); SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT);
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT); SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
SET_ISA_EXT_MAP("zba", RISCV_ISA_EXT_ZBA);
SET_ISA_EXT_MAP("zbb", RISCV_ISA_EXT_ZBB); SET_ISA_EXT_MAP("zbb", RISCV_ISA_EXT_ZBB);
SET_ISA_EXT_MAP("zbs", RISCV_ISA_EXT_ZBS);
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM); SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ); SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ);
SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE); SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE);
...@@ -279,9 +283,9 @@ void __init riscv_fill_hwcap(void) ...@@ -279,9 +283,9 @@ void __init riscv_fill_hwcap(void)
elf_hwcap = this_hwcap; elf_hwcap = this_hwcap;
if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX)) if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX))
bitmap_copy(riscv_isa, this_isa, RISCV_ISA_EXT_MAX); bitmap_copy(riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
else else
bitmap_and(riscv_isa, riscv_isa, this_isa, RISCV_ISA_EXT_MAX); bitmap_and(riscv_isa, riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
} }
if (!acpi_disabled && rhct) if (!acpi_disabled && rhct)
......
...@@ -122,6 +122,49 @@ static void hwprobe_arch_id(struct riscv_hwprobe *pair, ...@@ -122,6 +122,49 @@ static void hwprobe_arch_id(struct riscv_hwprobe *pair,
pair->value = id; pair->value = id;
} }
static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
const struct cpumask *cpus)
{
int cpu;
u64 missing = 0;
pair->value = 0;
if (has_fpu())
pair->value |= RISCV_HWPROBE_IMA_FD;
if (riscv_isa_extension_available(NULL, c))
pair->value |= RISCV_HWPROBE_IMA_C;
if (has_vector())
pair->value |= RISCV_HWPROBE_IMA_V;
/*
* Loop through and record extensions that 1) anyone has, and 2) anyone
* doesn't have.
*/
for_each_cpu(cpu, cpus) {
struct riscv_isainfo *isainfo = &hart_isa[cpu];
if (riscv_isa_extension_available(isainfo->isa, ZBA))
pair->value |= RISCV_HWPROBE_EXT_ZBA;
else
missing |= RISCV_HWPROBE_EXT_ZBA;
if (riscv_isa_extension_available(isainfo->isa, ZBB))
pair->value |= RISCV_HWPROBE_EXT_ZBB;
else
missing |= RISCV_HWPROBE_EXT_ZBB;
if (riscv_isa_extension_available(isainfo->isa, ZBS))
pair->value |= RISCV_HWPROBE_EXT_ZBS;
else
missing |= RISCV_HWPROBE_EXT_ZBS;
}
/* Now turn off reporting features if any CPU is missing it. */
pair->value &= ~missing;
}
static u64 hwprobe_misaligned(const struct cpumask *cpus) static u64 hwprobe_misaligned(const struct cpumask *cpus)
{ {
int cpu; int cpu;
...@@ -165,16 +208,7 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair, ...@@ -165,16 +208,7 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
break; break;
case RISCV_HWPROBE_KEY_IMA_EXT_0: case RISCV_HWPROBE_KEY_IMA_EXT_0:
pair->value = 0; hwprobe_isa_ext0(pair, cpus);
if (has_fpu())
pair->value |= RISCV_HWPROBE_IMA_FD;
if (riscv_isa_extension_available(NULL, c))
pair->value |= RISCV_HWPROBE_IMA_C;
if (has_vector())
pair->value |= RISCV_HWPROBE_IMA_V;
break; break;
case RISCV_HWPROBE_KEY_CPUPERF_0: case RISCV_HWPROBE_KEY_CPUPERF_0:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment