Skip to content

Commit 462a94f

Browse files
author
Paul Walmsley
committed
riscv: hwprobe: add support for RISCV_HWPROBE_KEY_IMA_EXT_1
We've run out of bits to describe RISC-V ISA extensions in our initial hwprobe key, RISCV_HWPROBE_KEY_IMA_EXT_0. So, let's add RISCV_HWPROBE_KEY_IMA_EXT_1, along with the framework to set the appropriate hwprobe tuple, and add testing for it. Based on a suggestion from Andrew Jones <andrew.jones@oss.qualcomm.com>, also fix the documentation for RISCV_HWPROBE_KEY_IMA_EXT_0. Reviewed-by: Andrew Jones <andrew.jones@oss.qualcomm.com> Signed-off-by: Paul Walmsley <pjw@kernel.org>
1 parent 2af7c9c commit 462a94f

5 files changed

Lines changed: 121 additions & 76 deletions

File tree

Documentation/arch/riscv/hwprobe.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ The following keys are defined:
6767
programs (it may still be executed in userspace via a
6868
kernel-controlled mechanism such as the vDSO).
6969

70-
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`: A bitmask containing the extensions
70+
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`: A bitmask containing extensions
7171
that are compatible with the :c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`:
7272
base system behavior.
7373

@@ -387,3 +387,7 @@ The following keys are defined:
387387

388388
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE`: An unsigned int which
389389
represents the size of the Zicbop block in bytes.
390+
391+
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_1`: A bitmask containing additional
392+
extensions that are compatible with the
393+
:c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`: base system behavior.

arch/riscv/include/asm/hwprobe.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#include <uapi/asm/hwprobe.h>
1010

11-
#define RISCV_HWPROBE_MAX_KEY 15
11+
#define RISCV_HWPROBE_MAX_KEY 16
1212

1313
static inline bool riscv_hwprobe_key_is_valid(__s64 key)
1414
{
@@ -20,6 +20,7 @@ static inline bool hwprobe_key_is_bitmask(__s64 key)
2020
switch (key) {
2121
case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
2222
case RISCV_HWPROBE_KEY_IMA_EXT_0:
23+
case RISCV_HWPROBE_KEY_IMA_EXT_1:
2324
case RISCV_HWPROBE_KEY_CPUPERF_0:
2425
case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0:
2526
case RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ struct riscv_hwprobe {
113113
#define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0 13
114114
#define RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0 14
115115
#define RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE 15
116+
#define RISCV_HWPROBE_KEY_IMA_EXT_1 16
116117
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
117118

118119
/* Flags */

arch/riscv/kernel/sys_hwprobe.c

Lines changed: 100 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
#include <vdso/vsyscall.h>
2525

2626

27+
#define EXT_KEY(isa_arg, ext, pv, missing) \
28+
do { \
29+
if (__riscv_isa_extension_available(isa_arg, RISCV_ISA_EXT_##ext)) \
30+
pv |= RISCV_HWPROBE_EXT_##ext; \
31+
else \
32+
missing |= RISCV_HWPROBE_EXT_##ext; \
33+
} while (false)
34+
2735
static void hwprobe_arch_id(struct riscv_hwprobe *pair,
2836
const struct cpumask *cpus)
2937
{
@@ -93,90 +101,109 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
93101
for_each_cpu(cpu, cpus) {
94102
struct riscv_isainfo *isainfo = &hart_isa[cpu];
95103

96-
#define EXT_KEY(ext) \
97-
do { \
98-
if (__riscv_isa_extension_available(isainfo->isa, RISCV_ISA_EXT_##ext)) \
99-
pair->value |= RISCV_HWPROBE_EXT_##ext; \
100-
else \
101-
missing |= RISCV_HWPROBE_EXT_##ext; \
102-
} while (false)
103-
104104
/*
105105
* Only use EXT_KEY() for extensions which can be exposed to userspace,
106106
* regardless of the kernel's configuration, as no other checks, besides
107107
* presence in the hart_isa bitmap, are made.
108108
*/
109-
EXT_KEY(ZAAMO);
110-
EXT_KEY(ZABHA);
111-
EXT_KEY(ZACAS);
112-
EXT_KEY(ZALASR);
113-
EXT_KEY(ZALRSC);
114-
EXT_KEY(ZAWRS);
115-
EXT_KEY(ZBA);
116-
EXT_KEY(ZBB);
117-
EXT_KEY(ZBC);
118-
EXT_KEY(ZBKB);
119-
EXT_KEY(ZBKC);
120-
EXT_KEY(ZBKX);
121-
EXT_KEY(ZBS);
122-
EXT_KEY(ZCA);
123-
EXT_KEY(ZCB);
124-
EXT_KEY(ZCLSD);
125-
EXT_KEY(ZCMOP);
126-
EXT_KEY(ZICBOM);
127-
EXT_KEY(ZICBOP);
128-
EXT_KEY(ZICBOZ);
129-
EXT_KEY(ZICNTR);
130-
EXT_KEY(ZICOND);
131-
EXT_KEY(ZIHINTNTL);
132-
EXT_KEY(ZIHINTPAUSE);
133-
EXT_KEY(ZIHPM);
134-
EXT_KEY(ZILSD);
135-
EXT_KEY(ZIMOP);
136-
EXT_KEY(ZKND);
137-
EXT_KEY(ZKNE);
138-
EXT_KEY(ZKNH);
139-
EXT_KEY(ZKSED);
140-
EXT_KEY(ZKSH);
141-
EXT_KEY(ZKT);
142-
EXT_KEY(ZTSO);
109+
EXT_KEY(isainfo->isa, ZAAMO, pair->value, missing);
110+
EXT_KEY(isainfo->isa, ZABHA, pair->value, missing);
111+
EXT_KEY(isainfo->isa, ZACAS, pair->value, missing);
112+
EXT_KEY(isainfo->isa, ZALASR, pair->value, missing);
113+
EXT_KEY(isainfo->isa, ZALRSC, pair->value, missing);
114+
EXT_KEY(isainfo->isa, ZAWRS, pair->value, missing);
115+
EXT_KEY(isainfo->isa, ZBA, pair->value, missing);
116+
EXT_KEY(isainfo->isa, ZBB, pair->value, missing);
117+
EXT_KEY(isainfo->isa, ZBC, pair->value, missing);
118+
EXT_KEY(isainfo->isa, ZBKB, pair->value, missing);
119+
EXT_KEY(isainfo->isa, ZBKC, pair->value, missing);
120+
EXT_KEY(isainfo->isa, ZBKX, pair->value, missing);
121+
EXT_KEY(isainfo->isa, ZBS, pair->value, missing);
122+
EXT_KEY(isainfo->isa, ZCA, pair->value, missing);
123+
EXT_KEY(isainfo->isa, ZCB, pair->value, missing);
124+
EXT_KEY(isainfo->isa, ZCLSD, pair->value, missing);
125+
EXT_KEY(isainfo->isa, ZCMOP, pair->value, missing);
126+
EXT_KEY(isainfo->isa, ZICBOM, pair->value, missing);
127+
EXT_KEY(isainfo->isa, ZICBOP, pair->value, missing);
128+
EXT_KEY(isainfo->isa, ZICBOZ, pair->value, missing);
129+
EXT_KEY(isainfo->isa, ZICNTR, pair->value, missing);
130+
EXT_KEY(isainfo->isa, ZICOND, pair->value, missing);
131+
EXT_KEY(isainfo->isa, ZIHINTNTL, pair->value, missing);
132+
EXT_KEY(isainfo->isa, ZIHINTPAUSE, pair->value, missing);
133+
EXT_KEY(isainfo->isa, ZIHPM, pair->value, missing);
134+
EXT_KEY(isainfo->isa, ZILSD, pair->value, missing);
135+
EXT_KEY(isainfo->isa, ZIMOP, pair->value, missing);
136+
EXT_KEY(isainfo->isa, ZKND, pair->value, missing);
137+
EXT_KEY(isainfo->isa, ZKNE, pair->value, missing);
138+
EXT_KEY(isainfo->isa, ZKNH, pair->value, missing);
139+
EXT_KEY(isainfo->isa, ZKSED, pair->value, missing);
140+
EXT_KEY(isainfo->isa, ZKSH, pair->value, missing);
141+
EXT_KEY(isainfo->isa, ZKT, pair->value, missing);
142+
EXT_KEY(isainfo->isa, ZTSO, pair->value, missing);
143143

144144
/*
145145
* All the following extensions must depend on the kernel
146146
* support of V.
147147
*/
148148
if (has_vector()) {
149-
EXT_KEY(ZVBB);
150-
EXT_KEY(ZVBC);
151-
EXT_KEY(ZVE32F);
152-
EXT_KEY(ZVE32X);
153-
EXT_KEY(ZVE64D);
154-
EXT_KEY(ZVE64F);
155-
EXT_KEY(ZVE64X);
156-
EXT_KEY(ZVFBFMIN);
157-
EXT_KEY(ZVFBFWMA);
158-
EXT_KEY(ZVFH);
159-
EXT_KEY(ZVFHMIN);
160-
EXT_KEY(ZVKB);
161-
EXT_KEY(ZVKG);
162-
EXT_KEY(ZVKNED);
163-
EXT_KEY(ZVKNHA);
164-
EXT_KEY(ZVKNHB);
165-
EXT_KEY(ZVKSED);
166-
EXT_KEY(ZVKSH);
167-
EXT_KEY(ZVKT);
149+
EXT_KEY(isainfo->isa, ZVBB, pair->value, missing);
150+
EXT_KEY(isainfo->isa, ZVBC, pair->value, missing);
151+
EXT_KEY(isainfo->isa, ZVE32F, pair->value, missing);
152+
EXT_KEY(isainfo->isa, ZVE32X, pair->value, missing);
153+
EXT_KEY(isainfo->isa, ZVE64D, pair->value, missing);
154+
EXT_KEY(isainfo->isa, ZVE64F, pair->value, missing);
155+
EXT_KEY(isainfo->isa, ZVE64X, pair->value, missing);
156+
EXT_KEY(isainfo->isa, ZVFBFMIN, pair->value, missing);
157+
EXT_KEY(isainfo->isa, ZVFBFWMA, pair->value, missing);
158+
EXT_KEY(isainfo->isa, ZVFH, pair->value, missing);
159+
EXT_KEY(isainfo->isa, ZVFHMIN, pair->value, missing);
160+
EXT_KEY(isainfo->isa, ZVKB, pair->value, missing);
161+
EXT_KEY(isainfo->isa, ZVKG, pair->value, missing);
162+
EXT_KEY(isainfo->isa, ZVKNED, pair->value, missing);
163+
EXT_KEY(isainfo->isa, ZVKNHA, pair->value, missing);
164+
EXT_KEY(isainfo->isa, ZVKNHB, pair->value, missing);
165+
EXT_KEY(isainfo->isa, ZVKSED, pair->value, missing);
166+
EXT_KEY(isainfo->isa, ZVKSH, pair->value, missing);
167+
EXT_KEY(isainfo->isa, ZVKT, pair->value, missing);
168168
}
169169

170-
EXT_KEY(ZCD);
171-
EXT_KEY(ZCF);
172-
EXT_KEY(ZFA);
173-
EXT_KEY(ZFBFMIN);
174-
EXT_KEY(ZFH);
175-
EXT_KEY(ZFHMIN);
170+
EXT_KEY(isainfo->isa, ZCD, pair->value, missing);
171+
EXT_KEY(isainfo->isa, ZCF, pair->value, missing);
172+
EXT_KEY(isainfo->isa, ZFA, pair->value, missing);
173+
EXT_KEY(isainfo->isa, ZFBFMIN, pair->value, missing);
174+
EXT_KEY(isainfo->isa, ZFH, pair->value, missing);
175+
EXT_KEY(isainfo->isa, ZFHMIN, pair->value, missing);
176176

177177
if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM))
178-
EXT_KEY(SUPM);
179-
#undef EXT_KEY
178+
EXT_KEY(isainfo->isa, SUPM, pair->value, missing);
179+
}
180+
181+
/* Now turn off reporting features if any CPU is missing it. */
182+
pair->value &= ~missing;
183+
}
184+
185+
static void hwprobe_isa_ext1(struct riscv_hwprobe *pair,
186+
const struct cpumask *cpus)
187+
{
188+
int cpu;
189+
u64 missing = 0;
190+
191+
pair->value = 0;
192+
193+
/*
194+
* Loop through and record extensions that 1) anyone has, and 2) anyone
195+
* doesn't have.
196+
*/
197+
for_each_cpu(cpu, cpus) {
198+
/* struct riscv_isainfo *isainfo = &hart_isa[cpu]; */
199+
200+
/*
201+
* Only use EXT_KEY() for extensions which can be
202+
* exposed to userspace, regardless of the kernel's
203+
* configuration, as no other checks, besides presence
204+
* in the hart_isa bitmap, are made.
205+
*/
206+
/* Nothing here yet */
180207
}
181208

182209
/* Now turn off reporting features if any CPU is missing it. */
@@ -287,6 +314,10 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
287314
hwprobe_isa_ext0(pair, cpus);
288315
break;
289316

317+
case RISCV_HWPROBE_KEY_IMA_EXT_1:
318+
hwprobe_isa_ext1(pair, cpus);
319+
break;
320+
290321
case RISCV_HWPROBE_KEY_CPUPERF_0:
291322
case RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF:
292323
pair->value = hwprobe_misaligned(cpus);

tools/testing/selftests/riscv/hwprobe/which-cpus.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ static void do_which_cpus(int argc, char **argv, cpu_set_t *cpus)
8383

8484
int main(int argc, char **argv)
8585
{
86-
struct riscv_hwprobe pairs[2];
86+
struct riscv_hwprobe pairs[3];
8787
cpu_set_t cpus_aff, cpus;
88-
__u64 ext0_all;
88+
__u64 ext0_all, ext1_all;
8989
long rc;
9090

9191
rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus_aff);
@@ -112,6 +112,11 @@ int main(int argc, char **argv)
112112
assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_IMA_EXT_0);
113113
ext0_all = pairs[0].value;
114114

115+
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, };
116+
rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
117+
assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_IMA_EXT_1);
118+
ext1_all = pairs[0].value;
119+
115120
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
116121
CPU_ZERO(&cpus);
117122
rc = riscv_hwprobe(pairs, 1, 0, (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
@@ -134,20 +139,23 @@ int main(int argc, char **argv)
134139

135140
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
136141
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
142+
pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ext1_all, };
137143
CPU_ZERO(&cpus);
138-
rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
144+
rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
139145
ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == sysconf(_SC_NPROCESSORS_ONLN), "set all cpus\n");
140146

141147
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
142148
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
149+
pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ext1_all, };
143150
memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
144-
rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
151+
rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
145152
ksft_test_result(rc == 0 && CPU_EQUAL(&cpus, &cpus_aff), "set all affinity cpus\n");
146153

147154
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
148155
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ~ext0_all, };
156+
pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ~ext1_all, };
149157
memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
150-
rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
158+
rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
151159
ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == 0, "clear all cpus\n");
152160

153161
ksft_finished();

0 commit comments

Comments
 (0)