Skip to content

Commit 16252e0

Browse files
Merge patch series "RISC-V: Export Zba, Zbb to usermode via hwprobe"
Evan Green <[email protected]> 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/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents f202338 + c0baf32 commit 16252e0

File tree

7 files changed

+81
-16
lines changed

7 files changed

+81
-16
lines changed

Documentation/riscv/hwprobe.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ The following keys are defined:
6767
* :c:macro:`RISCV_HWPROBE_IMA_V`: The V extension is supported, as defined by
6868
version 1.0 of the RISC-V Vector extension manual.
6969

70+
* :c:macro:`RISCV_HWPROBE_EXT_ZBA`: The Zba address generation extension is
71+
supported, as defined in version 1.0 of the Bit-Manipulation ISA
72+
extensions.
73+
74+
* :c:macro:`RISCV_HWPROBE_EXT_ZBB`: The Zbb extension is supported, as defined
75+
in version 1.0 of the Bit-Manipulation ISA extensions.
76+
77+
* :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined
78+
in version 1.0 of the Bit-Manipulation ISA extensions.
79+
7080
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance
7181
information about the selected set of processors.
7282

arch/riscv/include/asm/cpufeature.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#ifndef _ASM_CPUFEATURE_H
77
#define _ASM_CPUFEATURE_H
88

9+
#include <linux/bitmap.h>
10+
#include <asm/hwcap.h>
11+
912
/*
1013
* These are probed via a device_initcall(), via either the SBI or directly
1114
* from the corresponding CSRs.
@@ -16,8 +19,15 @@ struct riscv_cpuinfo {
1619
unsigned long mimpid;
1720
};
1821

22+
struct riscv_isainfo {
23+
DECLARE_BITMAP(isa, RISCV_ISA_EXT_MAX);
24+
};
25+
1926
DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
2027

2128
DECLARE_PER_CPU(long, misaligned_access_speed);
2229

30+
/* Per-cpu ISA extensions. */
31+
extern struct riscv_isainfo hart_isa[NR_CPUS];
32+
2333
#endif

arch/riscv/include/asm/hwcap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
#define RISCV_ISA_EXT_ZICBOZ 34
4848
#define RISCV_ISA_EXT_SMAIA 35
4949
#define RISCV_ISA_EXT_SSAIA 36
50+
#define RISCV_ISA_EXT_ZBA 37
51+
#define RISCV_ISA_EXT_ZBS 38
5052

5153
#define RISCV_ISA_EXT_MAX 64
5254
#define RISCV_ISA_EXT_NAME_LEN_MAX 32

arch/riscv/include/uapi/asm/hwprobe.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ struct riscv_hwprobe {
2626
#define RISCV_HWPROBE_IMA_FD (1 << 0)
2727
#define RISCV_HWPROBE_IMA_C (1 << 1)
2828
#define RISCV_HWPROBE_IMA_V (1 << 2)
29+
#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
30+
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
31+
#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
2932
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
3033
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
3134
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)

arch/riscv/kernel/cpu.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ static struct riscv_isa_ext_data isa_ext_arr[] = {
187187
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
188188
__RISCV_ISA_EXT_DATA(zicboz, RISCV_ISA_EXT_ZICBOZ),
189189
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
190+
__RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA),
190191
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
192+
__RISCV_ISA_EXT_DATA(zbs, RISCV_ISA_EXT_ZBS),
191193
__RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA),
192194
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
193195
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),

arch/riscv/kernel/cpufeature.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ unsigned long elf_hwcap __read_mostly;
3030
/* Host ISA bitmap */
3131
static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
3232

33+
/* Per-cpu ISA extensions. */
34+
struct riscv_isainfo hart_isa[NR_CPUS];
35+
3336
/* Performance information */
3437
DEFINE_PER_CPU(long, misaligned_access_speed);
3538

@@ -126,8 +129,8 @@ void __init riscv_fill_hwcap(void)
126129
}
127130

128131
for_each_possible_cpu(cpu) {
132+
struct riscv_isainfo *isainfo = &hart_isa[cpu];
129133
unsigned long this_hwcap = 0;
130-
DECLARE_BITMAP(this_isa, RISCV_ISA_EXT_MAX);
131134
const char *temp;
132135

133136
if (acpi_disabled) {
@@ -159,7 +162,6 @@ void __init riscv_fill_hwcap(void)
159162
/* The riscv,isa DT property must start with rv64 or rv32 */
160163
if (temp == isa)
161164
continue;
162-
bitmap_zero(this_isa, RISCV_ISA_EXT_MAX);
163165
for (; *isa; ++isa) {
164166
const char *ext = isa++;
165167
const char *ext_end = isa;
@@ -239,7 +241,7 @@ void __init riscv_fill_hwcap(void)
239241
if ((ext_end - ext == sizeof(name) - 1) && \
240242
!strncasecmp(ext, name, sizeof(name) - 1) && \
241243
riscv_isa_extension_check(bit)) \
242-
set_bit(bit, this_isa); \
244+
set_bit(bit, isainfo->isa); \
243245
} while (false) \
244246

245247
if (unlikely(ext_err))
@@ -249,7 +251,7 @@ void __init riscv_fill_hwcap(void)
249251

250252
if (riscv_isa_extension_check(nr)) {
251253
this_hwcap |= isa2hwcap[nr];
252-
set_bit(nr, this_isa);
254+
set_bit(nr, isainfo->isa);
253255
}
254256
} else {
255257
/* sorted alphabetically */
@@ -260,7 +262,9 @@ void __init riscv_fill_hwcap(void)
260262
SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL);
261263
SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT);
262264
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
265+
SET_ISA_EXT_MAP("zba", RISCV_ISA_EXT_ZBA);
263266
SET_ISA_EXT_MAP("zbb", RISCV_ISA_EXT_ZBB);
267+
SET_ISA_EXT_MAP("zbs", RISCV_ISA_EXT_ZBS);
264268
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
265269
SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ);
266270
SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE);
@@ -279,9 +283,9 @@ void __init riscv_fill_hwcap(void)
279283
elf_hwcap = this_hwcap;
280284

281285
if (bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX))
282-
bitmap_copy(riscv_isa, this_isa, RISCV_ISA_EXT_MAX);
286+
bitmap_copy(riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
283287
else
284-
bitmap_and(riscv_isa, riscv_isa, this_isa, RISCV_ISA_EXT_MAX);
288+
bitmap_and(riscv_isa, riscv_isa, isainfo->isa, RISCV_ISA_EXT_MAX);
285289
}
286290

287291
if (!acpi_disabled && rhct)

arch/riscv/kernel/sys_riscv.c

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,49 @@ static void hwprobe_arch_id(struct riscv_hwprobe *pair,
122122
pair->value = id;
123123
}
124124

125+
static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
126+
const struct cpumask *cpus)
127+
{
128+
int cpu;
129+
u64 missing = 0;
130+
131+
pair->value = 0;
132+
if (has_fpu())
133+
pair->value |= RISCV_HWPROBE_IMA_FD;
134+
135+
if (riscv_isa_extension_available(NULL, c))
136+
pair->value |= RISCV_HWPROBE_IMA_C;
137+
138+
if (has_vector())
139+
pair->value |= RISCV_HWPROBE_IMA_V;
140+
141+
/*
142+
* Loop through and record extensions that 1) anyone has, and 2) anyone
143+
* doesn't have.
144+
*/
145+
for_each_cpu(cpu, cpus) {
146+
struct riscv_isainfo *isainfo = &hart_isa[cpu];
147+
148+
if (riscv_isa_extension_available(isainfo->isa, ZBA))
149+
pair->value |= RISCV_HWPROBE_EXT_ZBA;
150+
else
151+
missing |= RISCV_HWPROBE_EXT_ZBA;
152+
153+
if (riscv_isa_extension_available(isainfo->isa, ZBB))
154+
pair->value |= RISCV_HWPROBE_EXT_ZBB;
155+
else
156+
missing |= RISCV_HWPROBE_EXT_ZBB;
157+
158+
if (riscv_isa_extension_available(isainfo->isa, ZBS))
159+
pair->value |= RISCV_HWPROBE_EXT_ZBS;
160+
else
161+
missing |= RISCV_HWPROBE_EXT_ZBS;
162+
}
163+
164+
/* Now turn off reporting features if any CPU is missing it. */
165+
pair->value &= ~missing;
166+
}
167+
125168
static u64 hwprobe_misaligned(const struct cpumask *cpus)
126169
{
127170
int cpu;
@@ -165,16 +208,7 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
165208
break;
166209

167210
case RISCV_HWPROBE_KEY_IMA_EXT_0:
168-
pair->value = 0;
169-
if (has_fpu())
170-
pair->value |= RISCV_HWPROBE_IMA_FD;
171-
172-
if (riscv_isa_extension_available(NULL, c))
173-
pair->value |= RISCV_HWPROBE_IMA_C;
174-
175-
if (has_vector())
176-
pair->value |= RISCV_HWPROBE_IMA_V;
177-
211+
hwprobe_isa_ext0(pair, cpus);
178212
break;
179213

180214
case RISCV_HWPROBE_KEY_CPUPERF_0:

0 commit comments

Comments
 (0)