#include <vdso/vsyscall.h>
+#define EXT_KEY(isa_arg, ext, pv, missing) \
+ do { \
+ if (__riscv_isa_extension_available(isa_arg, RISCV_ISA_EXT_##ext)) \
+ pv |= RISCV_HWPROBE_EXT_##ext; \
+ else \
+ missing |= RISCV_HWPROBE_EXT_##ext; \
+ } while (false)
+
static void hwprobe_arch_id(struct riscv_hwprobe *pair,
const struct cpumask *cpus)
{
for_each_cpu(cpu, cpus) {
struct riscv_isainfo *isainfo = &hart_isa[cpu];
-#define EXT_KEY(ext) \
- do { \
- if (__riscv_isa_extension_available(isainfo->isa, RISCV_ISA_EXT_##ext)) \
- pair->value |= RISCV_HWPROBE_EXT_##ext; \
- else \
- missing |= RISCV_HWPROBE_EXT_##ext; \
- } while (false)
-
/*
* Only use EXT_KEY() for extensions which can be exposed to userspace,
* regardless of the kernel's configuration, as no other checks, besides
* presence in the hart_isa bitmap, are made.
*/
- EXT_KEY(ZAAMO);
- EXT_KEY(ZABHA);
- EXT_KEY(ZACAS);
- EXT_KEY(ZALASR);
- EXT_KEY(ZALRSC);
- EXT_KEY(ZAWRS);
- EXT_KEY(ZBA);
- EXT_KEY(ZBB);
- EXT_KEY(ZBC);
- EXT_KEY(ZBKB);
- EXT_KEY(ZBKC);
- EXT_KEY(ZBKX);
- EXT_KEY(ZBS);
- EXT_KEY(ZCA);
- EXT_KEY(ZCB);
- EXT_KEY(ZCLSD);
- EXT_KEY(ZCMOP);
- EXT_KEY(ZICBOM);
- EXT_KEY(ZICBOP);
- EXT_KEY(ZICBOZ);
- EXT_KEY(ZICNTR);
- EXT_KEY(ZICOND);
- EXT_KEY(ZIHINTNTL);
- EXT_KEY(ZIHINTPAUSE);
- EXT_KEY(ZIHPM);
- EXT_KEY(ZILSD);
- EXT_KEY(ZIMOP);
- EXT_KEY(ZKND);
- EXT_KEY(ZKNE);
- EXT_KEY(ZKNH);
- EXT_KEY(ZKSED);
- EXT_KEY(ZKSH);
- EXT_KEY(ZKT);
- EXT_KEY(ZTSO);
+ EXT_KEY(isainfo->isa, ZAAMO, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZABHA, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZACAS, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZALASR, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZALRSC, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZAWRS, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZBA, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZBB, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZBC, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZBKB, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZBKC, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZBKX, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZBS, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZCA, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZCB, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZCLSD, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZCMOP, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZICBOM, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZICBOP, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZICBOZ, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZICNTR, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZICOND, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZIHINTNTL, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZIHINTPAUSE, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZIHPM, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZILSD, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZIMOP, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZKND, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZKNE, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZKNH, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZKSED, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZKSH, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZKT, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZTSO, pair->value, missing);
/*
* All the following extensions must depend on the kernel
* support of V.
*/
if (has_vector()) {
- EXT_KEY(ZVBB);
- EXT_KEY(ZVBC);
- EXT_KEY(ZVE32F);
- EXT_KEY(ZVE32X);
- EXT_KEY(ZVE64D);
- EXT_KEY(ZVE64F);
- EXT_KEY(ZVE64X);
- EXT_KEY(ZVFBFMIN);
- EXT_KEY(ZVFBFWMA);
- EXT_KEY(ZVFH);
- EXT_KEY(ZVFHMIN);
- EXT_KEY(ZVKB);
- EXT_KEY(ZVKG);
- EXT_KEY(ZVKNED);
- EXT_KEY(ZVKNHA);
- EXT_KEY(ZVKNHB);
- EXT_KEY(ZVKSED);
- EXT_KEY(ZVKSH);
- EXT_KEY(ZVKT);
+ EXT_KEY(isainfo->isa, ZVBB, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVBC, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVE32F, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVE32X, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVE64D, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVE64F, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVE64X, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVFBFMIN, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVFBFWMA, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVFH, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVFHMIN, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKB, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKG, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKNED, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKNHA, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKNHB, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKSED, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKSH, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZVKT, pair->value, missing);
}
- EXT_KEY(ZCD);
- EXT_KEY(ZCF);
- EXT_KEY(ZFA);
- EXT_KEY(ZFBFMIN);
- EXT_KEY(ZFH);
- EXT_KEY(ZFHMIN);
+ EXT_KEY(isainfo->isa, ZCD, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZCF, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZFA, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZFBFMIN, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZFH, pair->value, missing);
+ EXT_KEY(isainfo->isa, ZFHMIN, pair->value, missing);
if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM))
- EXT_KEY(SUPM);
-#undef EXT_KEY
+ EXT_KEY(isainfo->isa, SUPM, pair->value, missing);
+ }
+
+ /* Now turn off reporting features if any CPU is missing it. */
+ pair->value &= ~missing;
+}
+
+static void hwprobe_isa_ext1(struct riscv_hwprobe *pair,
+ const struct cpumask *cpus)
+{
+ int cpu;
+ u64 missing = 0;
+
+ pair->value = 0;
+
+ /*
+ * 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]; */
+
+ /*
+ * Only use EXT_KEY() for extensions which can be
+ * exposed to userspace, regardless of the kernel's
+ * configuration, as no other checks, besides presence
+ * in the hart_isa bitmap, are made.
+ */
+ /* Nothing here yet */
}
/* Now turn off reporting features if any CPU is missing it. */
hwprobe_isa_ext0(pair, cpus);
break;
+ case RISCV_HWPROBE_KEY_IMA_EXT_1:
+ hwprobe_isa_ext1(pair, cpus);
+ break;
+
case RISCV_HWPROBE_KEY_CPUPERF_0:
case RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF:
pair->value = hwprobe_misaligned(cpus);
int main(int argc, char **argv)
{
- struct riscv_hwprobe pairs[2];
+ struct riscv_hwprobe pairs[3];
cpu_set_t cpus_aff, cpus;
- __u64 ext0_all;
+ __u64 ext0_all, ext1_all;
long rc;
rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus_aff);
assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_IMA_EXT_0);
ext0_all = pairs[0].value;
+ pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, };
+ rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
+ assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_IMA_EXT_1);
+ ext1_all = pairs[0].value;
+
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
CPU_ZERO(&cpus);
rc = riscv_hwprobe(pairs, 1, 0, (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
+ pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ext1_all, };
CPU_ZERO(&cpus);
- rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
+ rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == sysconf(_SC_NPROCESSORS_ONLN), "set all cpus\n");
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
+ pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ext1_all, };
memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
- rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
+ rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
ksft_test_result(rc == 0 && CPU_EQUAL(&cpus, &cpus_aff), "set all affinity cpus\n");
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ~ext0_all, };
+ pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ~ext1_all, };
memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
- rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
+ rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == 0, "clear all cpus\n");
ksft_finished();