Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+121 -76
+5 -1
Documentation/arch/riscv/hwprobe.rst
··· 67 67 programs (it may still be executed in userspace via a 68 68 kernel-controlled mechanism such as the vDSO). 69 69 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 71 71 that are compatible with the :c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`: 72 72 base system behavior. 73 73 ··· 387 387 388 388 * :c:macro:`RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE`: An unsigned int which 389 389 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.
+2 -1
arch/riscv/include/asm/hwprobe.h
··· 8 8 9 9 #include <uapi/asm/hwprobe.h> 10 10 11 - #define RISCV_HWPROBE_MAX_KEY 15 11 + #define RISCV_HWPROBE_MAX_KEY 16 12 12 13 13 static inline bool riscv_hwprobe_key_is_valid(__s64 key) 14 14 { ··· 20 20 switch (key) { 21 21 case RISCV_HWPROBE_KEY_BASE_BEHAVIOR: 22 22 case RISCV_HWPROBE_KEY_IMA_EXT_0: 23 + case RISCV_HWPROBE_KEY_IMA_EXT_1: 23 24 case RISCV_HWPROBE_KEY_CPUPERF_0: 24 25 case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0: 25 26 case RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0:
+1
arch/riscv/include/uapi/asm/hwprobe.h
··· 113 113 #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0 13 114 114 #define RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0 14 115 115 #define RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE 15 116 + #define RISCV_HWPROBE_KEY_IMA_EXT_1 16 116 117 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ 117 118 118 119 /* Flags */
+100 -69
arch/riscv/kernel/sys_hwprobe.c
··· 24 24 #include <vdso/vsyscall.h> 25 25 26 26 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 + 27 35 static void hwprobe_arch_id(struct riscv_hwprobe *pair, 28 36 const struct cpumask *cpus) 29 37 { ··· 101 93 for_each_cpu(cpu, cpus) { 102 94 struct riscv_isainfo *isainfo = &hart_isa[cpu]; 103 95 104 - #define EXT_KEY(ext) \ 105 - do { \ 106 - if (__riscv_isa_extension_available(isainfo->isa, RISCV_ISA_EXT_##ext)) \ 107 - pair->value |= RISCV_HWPROBE_EXT_##ext; \ 108 - else \ 109 - missing |= RISCV_HWPROBE_EXT_##ext; \ 110 - } while (false) 111 - 112 96 /* 113 97 * Only use EXT_KEY() for extensions which can be exposed to userspace, 114 98 * regardless of the kernel's configuration, as no other checks, besides 115 99 * presence in the hart_isa bitmap, are made. 116 100 */ 117 - EXT_KEY(ZAAMO); 118 - EXT_KEY(ZABHA); 119 - EXT_KEY(ZACAS); 120 - EXT_KEY(ZALASR); 121 - EXT_KEY(ZALRSC); 122 - EXT_KEY(ZAWRS); 123 - EXT_KEY(ZBA); 124 - EXT_KEY(ZBB); 125 - EXT_KEY(ZBC); 126 - EXT_KEY(ZBKB); 127 - EXT_KEY(ZBKC); 128 - EXT_KEY(ZBKX); 129 - EXT_KEY(ZBS); 130 - EXT_KEY(ZCA); 131 - EXT_KEY(ZCB); 132 - EXT_KEY(ZCLSD); 133 - EXT_KEY(ZCMOP); 134 - EXT_KEY(ZICBOM); 135 - EXT_KEY(ZICBOP); 136 - EXT_KEY(ZICBOZ); 137 - EXT_KEY(ZICNTR); 138 - EXT_KEY(ZICOND); 139 - EXT_KEY(ZIHINTNTL); 140 - EXT_KEY(ZIHINTPAUSE); 141 - EXT_KEY(ZIHPM); 142 - EXT_KEY(ZILSD); 143 - EXT_KEY(ZIMOP); 144 - EXT_KEY(ZKND); 145 - EXT_KEY(ZKNE); 146 - EXT_KEY(ZKNH); 147 - EXT_KEY(ZKSED); 148 - EXT_KEY(ZKSH); 149 - EXT_KEY(ZKT); 150 - EXT_KEY(ZTSO); 101 + EXT_KEY(isainfo->isa, ZAAMO, pair->value, missing); 102 + EXT_KEY(isainfo->isa, ZABHA, pair->value, missing); 103 + EXT_KEY(isainfo->isa, ZACAS, pair->value, missing); 104 + EXT_KEY(isainfo->isa, ZALASR, pair->value, missing); 105 + EXT_KEY(isainfo->isa, ZALRSC, pair->value, missing); 106 + EXT_KEY(isainfo->isa, ZAWRS, pair->value, missing); 107 + EXT_KEY(isainfo->isa, ZBA, pair->value, missing); 108 + EXT_KEY(isainfo->isa, ZBB, pair->value, missing); 109 + EXT_KEY(isainfo->isa, ZBC, pair->value, missing); 110 + EXT_KEY(isainfo->isa, ZBKB, pair->value, missing); 111 + EXT_KEY(isainfo->isa, ZBKC, pair->value, missing); 112 + EXT_KEY(isainfo->isa, ZBKX, pair->value, missing); 113 + EXT_KEY(isainfo->isa, ZBS, pair->value, missing); 114 + EXT_KEY(isainfo->isa, ZCA, pair->value, missing); 115 + EXT_KEY(isainfo->isa, ZCB, pair->value, missing); 116 + EXT_KEY(isainfo->isa, ZCLSD, pair->value, missing); 117 + EXT_KEY(isainfo->isa, ZCMOP, pair->value, missing); 118 + EXT_KEY(isainfo->isa, ZICBOM, pair->value, missing); 119 + EXT_KEY(isainfo->isa, ZICBOP, pair->value, missing); 120 + EXT_KEY(isainfo->isa, ZICBOZ, pair->value, missing); 121 + EXT_KEY(isainfo->isa, ZICNTR, pair->value, missing); 122 + EXT_KEY(isainfo->isa, ZICOND, pair->value, missing); 123 + EXT_KEY(isainfo->isa, ZIHINTNTL, pair->value, missing); 124 + EXT_KEY(isainfo->isa, ZIHINTPAUSE, pair->value, missing); 125 + EXT_KEY(isainfo->isa, ZIHPM, pair->value, missing); 126 + EXT_KEY(isainfo->isa, ZILSD, pair->value, missing); 127 + EXT_KEY(isainfo->isa, ZIMOP, pair->value, missing); 128 + EXT_KEY(isainfo->isa, ZKND, pair->value, missing); 129 + EXT_KEY(isainfo->isa, ZKNE, pair->value, missing); 130 + EXT_KEY(isainfo->isa, ZKNH, pair->value, missing); 131 + EXT_KEY(isainfo->isa, ZKSED, pair->value, missing); 132 + EXT_KEY(isainfo->isa, ZKSH, pair->value, missing); 133 + EXT_KEY(isainfo->isa, ZKT, pair->value, missing); 134 + EXT_KEY(isainfo->isa, ZTSO, pair->value, missing); 151 135 152 136 /* 153 137 * All the following extensions must depend on the kernel 154 138 * support of V. 155 139 */ 156 140 if (has_vector()) { 157 - EXT_KEY(ZVBB); 158 - EXT_KEY(ZVBC); 159 - EXT_KEY(ZVE32F); 160 - EXT_KEY(ZVE32X); 161 - EXT_KEY(ZVE64D); 162 - EXT_KEY(ZVE64F); 163 - EXT_KEY(ZVE64X); 164 - EXT_KEY(ZVFBFMIN); 165 - EXT_KEY(ZVFBFWMA); 166 - EXT_KEY(ZVFH); 167 - EXT_KEY(ZVFHMIN); 168 - EXT_KEY(ZVKB); 169 - EXT_KEY(ZVKG); 170 - EXT_KEY(ZVKNED); 171 - EXT_KEY(ZVKNHA); 172 - EXT_KEY(ZVKNHB); 173 - EXT_KEY(ZVKSED); 174 - EXT_KEY(ZVKSH); 175 - EXT_KEY(ZVKT); 141 + EXT_KEY(isainfo->isa, ZVBB, pair->value, missing); 142 + EXT_KEY(isainfo->isa, ZVBC, pair->value, missing); 143 + EXT_KEY(isainfo->isa, ZVE32F, pair->value, missing); 144 + EXT_KEY(isainfo->isa, ZVE32X, pair->value, missing); 145 + EXT_KEY(isainfo->isa, ZVE64D, pair->value, missing); 146 + EXT_KEY(isainfo->isa, ZVE64F, pair->value, missing); 147 + EXT_KEY(isainfo->isa, ZVE64X, pair->value, missing); 148 + EXT_KEY(isainfo->isa, ZVFBFMIN, pair->value, missing); 149 + EXT_KEY(isainfo->isa, ZVFBFWMA, pair->value, missing); 150 + EXT_KEY(isainfo->isa, ZVFH, pair->value, missing); 151 + EXT_KEY(isainfo->isa, ZVFHMIN, pair->value, missing); 152 + EXT_KEY(isainfo->isa, ZVKB, pair->value, missing); 153 + EXT_KEY(isainfo->isa, ZVKG, pair->value, missing); 154 + EXT_KEY(isainfo->isa, ZVKNED, pair->value, missing); 155 + EXT_KEY(isainfo->isa, ZVKNHA, pair->value, missing); 156 + EXT_KEY(isainfo->isa, ZVKNHB, pair->value, missing); 157 + EXT_KEY(isainfo->isa, ZVKSED, pair->value, missing); 158 + EXT_KEY(isainfo->isa, ZVKSH, pair->value, missing); 159 + EXT_KEY(isainfo->isa, ZVKT, pair->value, missing); 176 160 } 177 161 178 - EXT_KEY(ZCD); 179 - EXT_KEY(ZCF); 180 - EXT_KEY(ZFA); 181 - EXT_KEY(ZFBFMIN); 182 - EXT_KEY(ZFH); 183 - EXT_KEY(ZFHMIN); 162 + EXT_KEY(isainfo->isa, ZCD, pair->value, missing); 163 + EXT_KEY(isainfo->isa, ZCF, pair->value, missing); 164 + EXT_KEY(isainfo->isa, ZFA, pair->value, missing); 165 + EXT_KEY(isainfo->isa, ZFBFMIN, pair->value, missing); 166 + EXT_KEY(isainfo->isa, ZFH, pair->value, missing); 167 + EXT_KEY(isainfo->isa, ZFHMIN, pair->value, missing); 184 168 185 169 if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM)) 186 - EXT_KEY(SUPM); 187 - #undef EXT_KEY 170 + EXT_KEY(isainfo->isa, SUPM, pair->value, missing); 171 + } 172 + 173 + /* Now turn off reporting features if any CPU is missing it. */ 174 + pair->value &= ~missing; 175 + } 176 + 177 + static void hwprobe_isa_ext1(struct riscv_hwprobe *pair, 178 + const struct cpumask *cpus) 179 + { 180 + int cpu; 181 + u64 missing = 0; 182 + 183 + pair->value = 0; 184 + 185 + /* 186 + * Loop through and record extensions that 1) anyone has, and 2) anyone 187 + * doesn't have. 188 + */ 189 + for_each_cpu(cpu, cpus) { 190 + /* struct riscv_isainfo *isainfo = &hart_isa[cpu]; */ 191 + 192 + /* 193 + * Only use EXT_KEY() for extensions which can be 194 + * exposed to userspace, regardless of the kernel's 195 + * configuration, as no other checks, besides presence 196 + * in the hart_isa bitmap, are made. 197 + */ 198 + /* Nothing here yet */ 188 199 } 189 200 190 201 /* Now turn off reporting features if any CPU is missing it. */ ··· 312 285 313 286 case RISCV_HWPROBE_KEY_IMA_EXT_0: 314 287 hwprobe_isa_ext0(pair, cpus); 288 + break; 289 + 290 + case RISCV_HWPROBE_KEY_IMA_EXT_1: 291 + hwprobe_isa_ext1(pair, cpus); 315 292 break; 316 293 317 294 case RISCV_HWPROBE_KEY_CPUPERF_0:
+13 -5
tools/testing/selftests/riscv/hwprobe/which-cpus.c
··· 83 83 84 84 int main(int argc, char **argv) 85 85 { 86 - struct riscv_hwprobe pairs[2]; 86 + struct riscv_hwprobe pairs[3]; 87 87 cpu_set_t cpus_aff, cpus; 88 - __u64 ext0_all; 88 + __u64 ext0_all, ext1_all; 89 89 long rc; 90 90 91 91 rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus_aff); ··· 112 112 assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_IMA_EXT_0); 113 113 ext0_all = pairs[0].value; 114 114 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 + 115 120 pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, }; 116 121 CPU_ZERO(&cpus); 117 122 rc = riscv_hwprobe(pairs, 1, 0, (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS); ··· 139 134 140 135 pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, }; 141 136 pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, }; 137 + pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ext1_all, }; 142 138 CPU_ZERO(&cpus); 143 - rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS); 139 + rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS); 144 140 ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == sysconf(_SC_NPROCESSORS_ONLN), "set all cpus\n"); 145 141 146 142 pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, }; 147 143 pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, }; 144 + pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ext1_all, }; 148 145 memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t)); 149 - rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS); 146 + rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS); 150 147 ksft_test_result(rc == 0 && CPU_EQUAL(&cpus, &cpus_aff), "set all affinity cpus\n"); 151 148 152 149 pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, }; 153 150 pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ~ext0_all, }; 151 + pairs[2] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_1, .value = ~ext1_all, }; 154 152 memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t)); 155 - rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS); 153 + rc = riscv_hwprobe(pairs, 3, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS); 156 154 ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == 0, "clear all cpus\n"); 157 155 158 156 ksft_finished();