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

Merge tag 'riscv-for-linus-6.19-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V updates from Paul Walmsley:

- Enable parallel hotplug for RISC-V

- Optimize vector regset allocation for ptrace()

- Add a kernel selftest for the vector ptrace interface

- Enable the userspace RAID6 test to build and run using RISC-V vectors

- Add initial support for the Zalasr RISC-V ratified ISA extension

- For the Zicbop RISC-V ratified ISA extension to userspace, expose
hardware and kernel support to userspace and add a kselftest for
Zicbop

- Convert open-coded instances of 'asm goto's that are controlled by
runtime ALTERNATIVEs to use riscv_has_extension_{un,}likely(),
following arm64's alternative_has_cap_{un,}likely()

- Remove an unnecessary mask in the GFP flags used in some calls to
pagetable_alloc()

* tag 'riscv-for-linus-6.19-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
selftests/riscv: Add Zicbop prefetch test
riscv: hwprobe: Expose Zicbop extension and its block size
riscv: Introduce Zalasr instructions
riscv: hwprobe: Export Zalasr extension
dt-bindings: riscv: Add Zalasr ISA extension description
riscv: Add ISA extension parsing for Zalasr
selftests: riscv: Add test for the Vector ptrace interface
riscv: ptrace: Optimize the allocation of vector regset
raid6: test: Add support for RISC-V
raid6: riscv: Allow code to be compiled in userspace
raid6: riscv: Prevent compiler from breaking inline vector assembly code
riscv: cmpxchg: Use riscv_has_extension_likely
riscv: bitops: Use riscv_has_extension_likely
riscv: hweight: Use riscv_has_extension_likely
riscv: checksum: Use riscv_has_extension_likely
riscv: pgtable: Use riscv_has_extension_unlikely
riscv: Remove __GFP_HIGHMEM masking
RISC-V: Enable HOTPLUG_PARALLEL for secondary CPUs

+655 -304
+9
Documentation/arch/riscv/hwprobe.rst
··· 249 249 defined in the in the RISC-V ISA manual starting from commit e87412e621f1 250 250 ("integrate Zaamo and Zalrsc text (#1304)"). 251 251 252 + * :c:macro:`RISCV_HWPROBE_EXT_ZALASR`: The Zalasr extension is supported as 253 + frozen at commit 194f0094 ("Version 0.9 for freeze") of riscv-zalasr. 254 + 252 255 * :c:macro:`RISCV_HWPROBE_EXT_ZALRSC`: The Zalrsc extension is supported as 253 256 defined in the in the RISC-V ISA manual starting from commit e87412e621f1 254 257 ("integrate Zaamo and Zalrsc text (#1304)"). ··· 277 274 * :c:macro:`RISCV_HWPROBE_EXT_ZABHA`: The Zabha extension is supported as 278 275 ratified in commit 49f49c842ff9 ("Update to Rafified state") of 279 276 riscv-zabha. 277 + 278 + * :c:macro:`RISCV_HWPROBE_EXT_ZICBOP`: The Zicbop extension is supported, as 279 + ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs. 280 280 281 281 * :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: Deprecated. Returns similar values to 282 282 :c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was ··· 376 370 * :c:macro:`RISCV_HWPROBE_VENDOR_EXT_XSFVFWMACCQQQ`: The Xsfvfwmaccqqq 377 371 vendor extension is supported in version 1.0 of Matrix Multiply Accumulate 378 372 Instruction Extensions Specification. 373 + 374 + * :c:macro:`RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE`: An unsigned int which 375 + represents the size of the Zicbop block in bytes.
+5
Documentation/devicetree/bindings/riscv/extensions.yaml
··· 248 248 is supported as ratified at commit 5059e0ca641c ("update to 249 249 ratified") of the riscv-zacas. 250 250 251 + - const: zalasr 252 + description: | 253 + The standard Zalasr extension for load-acquire/store-release as frozen 254 + at commit 194f0094 ("Version 0.9 for freeze") of riscv-zalasr. 255 + 251 256 - const: zalrsc 252 257 description: | 253 258 The standard Zalrsc extension for load-reserved/store-conditional as
+1 -1
arch/riscv/Kconfig
··· 200 200 select HAVE_SAMPLE_FTRACE_DIRECT_MULTI 201 201 select HAVE_STACKPROTECTOR 202 202 select HAVE_SYSCALL_TRACEPOINTS 203 - select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU 203 + select HOTPLUG_PARALLEL if HOTPLUG_CPU 204 204 select IRQ_DOMAIN 205 205 select IRQ_FORCED_THREADING 206 206 select KASAN_VMALLOC if KASAN
+8 -16
arch/riscv/include/asm/arch_hweight.h
··· 19 19 20 20 static __always_inline unsigned int __arch_hweight32(unsigned int w) 21 21 { 22 - #if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) 23 - asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 24 - RISCV_ISA_EXT_ZBB, 1) 25 - : : : : legacy); 22 + if (!(IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && 23 + IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) && 24 + riscv_has_extension_likely(RISCV_ISA_EXT_ZBB))) 25 + return __sw_hweight32(w); 26 26 27 27 asm (".option push\n" 28 28 ".option arch,+zbb\n" ··· 31 31 : "=r" (w) : "r" (w) :); 32 32 33 33 return w; 34 - 35 - legacy: 36 - #endif 37 - return __sw_hweight32(w); 38 34 } 39 35 40 36 static inline unsigned int __arch_hweight16(unsigned int w) ··· 46 50 #if BITS_PER_LONG == 64 47 51 static __always_inline unsigned long __arch_hweight64(__u64 w) 48 52 { 49 - #if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB) 50 - asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 51 - RISCV_ISA_EXT_ZBB, 1) 52 - : : : : legacy); 53 + if (!(IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && 54 + IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) && 55 + riscv_has_extension_likely(RISCV_ISA_EXT_ZBB))) 56 + return __sw_hweight64(w); 53 57 54 58 asm (".option push\n" 55 59 ".option arch,+zbb\n" ··· 58 62 : "=r" (w) : "r" (w) :); 59 63 60 64 return w; 61 - 62 - legacy: 63 - #endif 64 - return __sw_hweight64(w); 65 65 } 66 66 #else /* BITS_PER_LONG == 64 */ 67 67 static inline unsigned long __arch_hweight64(__u64 w)
+8 -24
arch/riscv/include/asm/bitops.h
··· 47 47 48 48 static __always_inline __attribute_const__ unsigned long variable__ffs(unsigned long word) 49 49 { 50 - asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 51 - RISCV_ISA_EXT_ZBB, 1) 52 - : : : : legacy); 50 + if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) 51 + return generic___ffs(word); 53 52 54 53 asm volatile (".option push\n" 55 54 ".option arch,+zbb\n" ··· 57 58 : "=r" (word) : "r" (word) :); 58 59 59 60 return word; 60 - 61 - legacy: 62 - return generic___ffs(word); 63 61 } 64 62 65 63 /** ··· 72 76 73 77 static __always_inline __attribute_const__ unsigned long variable__fls(unsigned long word) 74 78 { 75 - asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 76 - RISCV_ISA_EXT_ZBB, 1) 77 - : : : : legacy); 79 + if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) 80 + return generic___fls(word); 78 81 79 82 asm volatile (".option push\n" 80 83 ".option arch,+zbb\n" ··· 82 87 : "=r" (word) : "r" (word) :); 83 88 84 89 return BITS_PER_LONG - 1 - word; 85 - 86 - legacy: 87 - return generic___fls(word); 88 90 } 89 91 90 92 /** ··· 97 105 98 106 static __always_inline __attribute_const__ int variable_ffs(int x) 99 107 { 100 - asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 101 - RISCV_ISA_EXT_ZBB, 1) 102 - : : : : legacy); 108 + if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) 109 + return generic_ffs(x); 103 110 104 111 if (!x) 105 112 return 0; ··· 110 119 : "=r" (x) : "r" (x) :); 111 120 112 121 return x + 1; 113 - 114 - legacy: 115 - return generic_ffs(x); 116 122 } 117 123 118 124 /** ··· 125 137 126 138 static __always_inline int variable_fls(unsigned int x) 127 139 { 128 - asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 129 - RISCV_ISA_EXT_ZBB, 1) 130 - : : : : legacy); 140 + if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) 141 + return generic_fls(x); 131 142 132 143 if (!x) 133 144 return 0; ··· 138 151 : "=r" (x) : "r" (x) :); 139 152 140 153 return 32 - x; 141 - 142 - legacy: 143 - return generic_fls(x); 144 154 } 145 155 146 156 /**
+4 -9
arch/riscv/include/asm/checksum.h
··· 49 49 * ZBB only saves three instructions on 32-bit and five on 64-bit so not 50 50 * worth checking if supported without Alternatives. 51 51 */ 52 - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { 52 + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && 53 + IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) && 54 + riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) { 53 55 unsigned long fold_temp; 54 - 55 - asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, 56 - RISCV_ISA_EXT_ZBB, 1) 57 - : 58 - : 59 - : 60 - : no_zbb); 61 56 62 57 if (IS_ENABLED(CONFIG_32BIT)) { 63 58 asm(".option push \n\ ··· 76 81 } 77 82 return (__force __sum16)(csum >> 16); 78 83 } 79 - no_zbb: 84 + 80 85 #ifndef CONFIG_32BIT 81 86 csum += ror64(csum, 32); 82 87 csum >>= 32;
+4 -8
arch/riscv/include/asm/cmpxchg.h
··· 373 373 u32 *__ptr32b; 374 374 ulong __s, __val, __mask; 375 375 376 - asm goto(ALTERNATIVE("j %l[no_zawrs]", "nop", 377 - 0, RISCV_ISA_EXT_ZAWRS, 1) 378 - : : : : no_zawrs); 376 + if (!riscv_has_extension_likely(RISCV_ISA_EXT_ZAWRS)) { 377 + ALT_RISCV_PAUSE(); 378 + return; 379 + } 379 380 380 381 switch (size) { 381 382 case 1: ··· 438 437 default: 439 438 BUILD_BUG(); 440 439 } 441 - 442 - return; 443 - 444 - no_zawrs: 445 - ALT_RISCV_PAUSE(); 446 440 } 447 441 448 442 #define __cmpwait_relaxed(ptr, val) \
+1
arch/riscv/include/asm/hwcap.h
··· 107 107 #define RISCV_ISA_EXT_ZALRSC 98 108 108 #define RISCV_ISA_EXT_ZICBOP 99 109 109 #define RISCV_ISA_EXT_SVRSW60T59B 100 110 + #define RISCV_ISA_EXT_ZALASR 101 110 111 111 112 #define RISCV_ISA_EXT_XLINUXENVCFG 127 112 113
+1 -1
arch/riscv/include/asm/hwprobe.h
··· 8 8 9 9 #include <uapi/asm/hwprobe.h> 10 10 11 - #define RISCV_HWPROBE_MAX_KEY 14 11 + #define RISCV_HWPROBE_MAX_KEY 15 12 12 13 13 static inline bool riscv_hwprobe_key_is_valid(__s64 key) 14 14 {
+79
arch/riscv/include/asm/insn-def.h
··· 179 179 #define RV___RS1(v) __RV_REG(v) 180 180 #define RV___RS2(v) __RV_REG(v) 181 181 182 + #define RV_OPCODE_AMO RV_OPCODE(47) 182 183 #define RV_OPCODE_MISC_MEM RV_OPCODE(15) 183 184 #define RV_OPCODE_OP_IMM RV_OPCODE(19) 184 185 #define RV_OPCODE_SYSTEM RV_OPCODE(115) ··· 207 206 #else 208 207 #define HLV_D(dest, addr) \ 209 208 __ASM_STR(.error "hlv.d requires 64-bit support") 209 + #endif 210 + 211 + #define LB_AQ(dest, addr) \ 212 + INSN_R(OPCODE_AMO, FUNC3(0), FUNC7(26), \ 213 + RD(dest), RS1(addr), __RS2(0)) 214 + 215 + #define LB_AQRL(dest, addr) \ 216 + INSN_R(OPCODE_AMO, FUNC3(0), FUNC7(27), \ 217 + RD(dest), RS1(addr), __RS2(0)) 218 + 219 + #define LH_AQ(dest, addr) \ 220 + INSN_R(OPCODE_AMO, FUNC3(1), FUNC7(26), \ 221 + RD(dest), RS1(addr), __RS2(0)) 222 + 223 + #define LH_AQRL(dest, addr) \ 224 + INSN_R(OPCODE_AMO, FUNC3(1), FUNC7(27), \ 225 + RD(dest), RS1(addr), __RS2(0)) 226 + 227 + #define LW_AQ(dest, addr) \ 228 + INSN_R(OPCODE_AMO, FUNC3(2), FUNC7(26), \ 229 + RD(dest), RS1(addr), __RS2(0)) 230 + 231 + #define LW_AQRL(dest, addr) \ 232 + INSN_R(OPCODE_AMO, FUNC3(2), FUNC7(27), \ 233 + RD(dest), RS1(addr), __RS2(0)) 234 + 235 + #define SB_RL(src, addr) \ 236 + INSN_R(OPCODE_AMO, FUNC3(0), FUNC7(29), \ 237 + __RD(0), RS1(addr), RS2(src)) 238 + 239 + #define SB_AQRL(src, addr) \ 240 + INSN_R(OPCODE_AMO, FUNC3(0), FUNC7(31), \ 241 + __RD(0), RS1(addr), RS2(src)) 242 + 243 + #define SH_RL(src, addr) \ 244 + INSN_R(OPCODE_AMO, FUNC3(1), FUNC7(29), \ 245 + __RD(0), RS1(addr), RS2(src)) 246 + 247 + #define SH_AQRL(src, addr) \ 248 + INSN_R(OPCODE_AMO, FUNC3(1), FUNC7(31), \ 249 + __RD(0), RS1(addr), RS2(src)) 250 + 251 + #define SW_RL(src, addr) \ 252 + INSN_R(OPCODE_AMO, FUNC3(2), FUNC7(29), \ 253 + __RD(0), RS1(addr), RS2(src)) 254 + 255 + #define SW_AQRL(src, addr) \ 256 + INSN_R(OPCODE_AMO, FUNC3(2), FUNC7(31), \ 257 + __RD(0), RS1(addr), RS2(src)) 258 + 259 + #ifdef CONFIG_64BIT 260 + #define LD_AQ(dest, addr) \ 261 + INSN_R(OPCODE_AMO, FUNC3(3), FUNC7(26), \ 262 + RD(dest), RS1(addr), __RS2(0)) 263 + 264 + #define LD_AQRL(dest, addr) \ 265 + INSN_R(OPCODE_AMO, FUNC3(3), FUNC7(27), \ 266 + RD(dest), RS1(addr), __RS2(0)) 267 + 268 + #define SD_RL(src, addr) \ 269 + INSN_R(OPCODE_AMO, FUNC3(3), FUNC7(29), \ 270 + __RD(0), RS1(addr), RS2(src)) 271 + 272 + #define SD_AQRL(src, addr) \ 273 + INSN_R(OPCODE_AMO, FUNC3(3), FUNC7(31), \ 274 + __RD(0), RS1(addr), RS2(src)) 275 + #else 276 + #define LD_AQ(dest, addr) \ 277 + __ASM_STR(.error "ld.aq requires 64-bit support") 278 + 279 + #define LD_AQRL(dest, addr) \ 280 + __ASM_STR(.error "ld.aqrl requires 64-bit support") 281 + 282 + #define SD_RL(dest, addr) \ 283 + __ASM_STR(.error "sd.rl requires 64-bit support") 284 + 285 + #define SD_AQRL(dest, addr) \ 286 + __ASM_STR(.error "sd.aqrl requires 64-bit support") 210 287 #endif 211 288 212 289 #define SINVAL_VMA(vaddr, asid) \
+7 -8
arch/riscv/include/asm/pgtable.h
··· 567 567 struct vm_area_struct *vma, unsigned long address, 568 568 pte_t *ptep, unsigned int nr) 569 569 { 570 - asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1) 571 - : : : : svvptc); 570 + /* 571 + * Svvptc guarantees that the new valid pte will be visible within 572 + * a bounded timeframe, so when the uarch does not cache invalid 573 + * entries, we don't have to do anything. 574 + */ 575 + if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC)) 576 + return; 572 577 573 578 /* 574 579 * The kernel assumes that TLBs don't cache invalid entries, but ··· 585 580 while (nr--) 586 581 local_flush_tlb_page(address + nr * PAGE_SIZE); 587 582 588 - svvptc:; 589 - /* 590 - * Svvptc guarantees that the new valid pte will be visible within 591 - * a bounded timeframe, so when the uarch does not cache invalid 592 - * entries, we don't have to do anything. 593 - */ 594 583 } 595 584 #define update_mmu_cache(vma, addr, ptep) \ 596 585 update_mmu_cache_range(NULL, vma, addr, ptep, 1)
+1
arch/riscv/include/asm/vector.h
··· 51 51 void riscv_v_thread_free(struct task_struct *tsk); 52 52 void __init riscv_v_setup_ctx_cache(void); 53 53 void riscv_v_thread_alloc(struct task_struct *tsk); 54 + void __init update_regset_vector_info(unsigned long size); 54 55 55 56 static inline u32 riscv_v_flags(void) 56 57 {
+3
arch/riscv/include/uapi/asm/hwprobe.h
··· 82 82 #define RISCV_HWPROBE_EXT_ZAAMO (1ULL << 56) 83 83 #define RISCV_HWPROBE_EXT_ZALRSC (1ULL << 57) 84 84 #define RISCV_HWPROBE_EXT_ZABHA (1ULL << 58) 85 + #define RISCV_HWPROBE_EXT_ZALASR (1ULL << 59) 86 + #define RISCV_HWPROBE_EXT_ZICBOP (1ULL << 60) 85 87 #define RISCV_HWPROBE_KEY_CPUPERF_0 5 86 88 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) 87 89 #define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) ··· 109 107 #define RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE 12 110 108 #define RISCV_HWPROBE_KEY_VENDOR_EXT_SIFIVE_0 13 111 109 #define RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0 14 110 + #define RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE 15 112 111 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ 113 112 114 113 /* Flags */
+1
arch/riscv/kernel/cpufeature.c
··· 472 472 __RISCV_ISA_EXT_DATA(zaamo, RISCV_ISA_EXT_ZAAMO), 473 473 __RISCV_ISA_EXT_DATA(zabha, RISCV_ISA_EXT_ZABHA), 474 474 __RISCV_ISA_EXT_DATA(zacas, RISCV_ISA_EXT_ZACAS), 475 + __RISCV_ISA_EXT_DATA(zalasr, RISCV_ISA_EXT_ZALASR), 475 476 __RISCV_ISA_EXT_DATA(zalrsc, RISCV_ISA_EXT_ZALRSC), 476 477 __RISCV_ISA_EXT_DATA(zawrs, RISCV_ISA_EXT_ZAWRS), 477 478 __RISCV_ISA_EXT_DATA_VALIDATE(zfa, RISCV_ISA_EXT_ZFA, riscv_ext_f_depends),
+21 -3
arch/riscv/kernel/ptrace.c
··· 153 153 0, riscv_v_vsize); 154 154 return ret; 155 155 } 156 + 157 + static int riscv_vr_active(struct task_struct *target, const struct user_regset *regset) 158 + { 159 + if (!(has_vector() || has_xtheadvector())) 160 + return -ENODEV; 161 + 162 + if (!riscv_v_vstate_query(task_pt_regs(target))) 163 + return 0; 164 + 165 + return regset->n; 166 + } 156 167 #endif 157 168 158 169 #ifdef CONFIG_RISCV_ISA_SUPM ··· 195 184 } 196 185 #endif 197 186 198 - static const struct user_regset riscv_user_regset[] = { 187 + static struct user_regset riscv_user_regset[] __ro_after_init = { 199 188 [REGSET_X] = { 200 189 USER_REGSET_NOTE_TYPE(PRSTATUS), 201 190 .n = ELF_NGREG, ··· 218 207 [REGSET_V] = { 219 208 USER_REGSET_NOTE_TYPE(RISCV_VECTOR), 220 209 .align = 16, 221 - .n = ((32 * RISCV_MAX_VLENB) + 222 - sizeof(struct __riscv_v_regset_state)) / sizeof(__u32), 223 210 .size = sizeof(__u32), 224 211 .regset_get = riscv_vr_get, 225 212 .set = riscv_vr_set, 213 + .active = riscv_vr_active, 226 214 }, 227 215 #endif 228 216 #ifdef CONFIG_RISCV_ISA_SUPM ··· 242 232 .regsets = riscv_user_regset, 243 233 .n = ARRAY_SIZE(riscv_user_regset), 244 234 }; 235 + 236 + #ifdef CONFIG_RISCV_ISA_V 237 + void __init update_regset_vector_info(unsigned long size) 238 + { 239 + riscv_user_regset[REGSET_V].n = (size + sizeof(struct __riscv_v_regset_state)) / 240 + sizeof(__u32); 241 + } 242 + #endif 245 243 246 244 struct pt_regs_offset { 247 245 const char *name;
+15
arch/riscv/kernel/smpboot.c
··· 39 39 40 40 #include "head.h" 41 41 42 + #ifndef CONFIG_HOTPLUG_PARALLEL 42 43 static DECLARE_COMPLETION(cpu_running); 44 + #endif 43 45 44 46 void __init smp_prepare_cpus(unsigned int max_cpus) 45 47 { ··· 181 179 return -EOPNOTSUPP; 182 180 } 183 181 182 + #ifdef CONFIG_HOTPLUG_PARALLEL 183 + int arch_cpuhp_kick_ap_alive(unsigned int cpu, struct task_struct *tidle) 184 + { 185 + return start_secondary_cpu(cpu, tidle); 186 + } 187 + #else 184 188 int __cpu_up(unsigned int cpu, struct task_struct *tidle) 185 189 { 186 190 int ret = 0; ··· 207 199 208 200 return ret; 209 201 } 202 + #endif 210 203 211 204 void __init smp_cpus_done(unsigned int max_cpus) 212 205 { ··· 234 225 mmgrab(mm); 235 226 current->active_mm = mm; 236 227 228 + #ifdef CONFIG_HOTPLUG_PARALLEL 229 + cpuhp_ap_sync_alive(); 230 + #endif 231 + 237 232 store_cpu_topology(curr_cpuid); 238 233 notify_cpu_starting(curr_cpuid); 239 234 ··· 256 243 */ 257 244 local_flush_icache_all(); 258 245 local_flush_tlb_all(); 246 + #ifndef CONFIG_HOTPLUG_PARALLEL 259 247 complete(&cpu_running); 248 + #endif 260 249 /* 261 250 * Disable preemption before enabling interrupts, so we don't try to 262 251 * schedule a CPU that hasn't actually started yet.
+7
arch/riscv/kernel/sys_hwprobe.c
··· 109 109 EXT_KEY(ZAAMO); 110 110 EXT_KEY(ZABHA); 111 111 EXT_KEY(ZACAS); 112 + EXT_KEY(ZALASR); 112 113 EXT_KEY(ZALRSC); 113 114 EXT_KEY(ZAWRS); 114 115 EXT_KEY(ZBA); ··· 123 122 EXT_KEY(ZCB); 124 123 EXT_KEY(ZCMOP); 125 124 EXT_KEY(ZICBOM); 125 + EXT_KEY(ZICBOP); 126 126 EXT_KEY(ZICBOZ); 127 127 EXT_KEY(ZICNTR); 128 128 EXT_KEY(ZICOND); ··· 303 301 pair->value = 0; 304 302 if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOM)) 305 303 pair->value = riscv_cbom_block_size; 304 + break; 305 + case RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE: 306 + pair->value = 0; 307 + if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOP)) 308 + pair->value = riscv_cbop_block_size; 306 309 break; 307 310 case RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS: 308 311 pair->value = user_max_virt_addr();
+2
arch/riscv/kernel/vector.c
··· 66 66 if (!(has_vector() || has_xtheadvector())) 67 67 return; 68 68 69 + update_regset_vector_info(riscv_v_vsize); 70 + 69 71 riscv_v_user_cachep = kmem_cache_create_usercopy("riscv_vector_ctx", 70 72 riscv_v_vsize, 16, SLAB_PANIC, 71 73 0, riscv_v_vsize, NULL);
+12 -41
arch/riscv/lib/csum.c
··· 40 40 uproto = (__force unsigned int)htonl(proto); 41 41 sum += uproto; 42 42 43 - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { 43 + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && 44 + IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) && 45 + riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) { 44 46 unsigned long fold_temp; 45 47 46 - /* 47 - * Zbb is likely available when the kernel is compiled with Zbb 48 - * support, so nop when Zbb is available and jump when Zbb is 49 - * not available. 50 - */ 51 - asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, 52 - RISCV_ISA_EXT_ZBB, 1) 53 - : 54 - : 55 - : 56 - : no_zbb); 57 48 asm(".option push \n\ 58 49 .option arch,+zbb \n\ 59 50 rori %[fold_temp], %[sum], 32 \n\ ··· 57 66 : [sum] "+r" (sum), [fold_temp] "=&r" (fold_temp)); 58 67 return (__force __sum16)(sum >> 16); 59 68 } 60 - no_zbb: 69 + 61 70 sum += ror64(sum, 32); 62 71 sum >>= 32; 63 72 return csum_fold((__force __wsum)sum); ··· 143 152 csum = do_csum_common(ptr, end, data); 144 153 145 154 #ifdef CC_HAS_ASM_GOTO_TIED_OUTPUT 146 - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { 155 + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && 156 + IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) && 157 + riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) { 147 158 unsigned long fold_temp; 148 - 149 - /* 150 - * Zbb is likely available when the kernel is compiled with Zbb 151 - * support, so nop when Zbb is available and jump when Zbb is 152 - * not available. 153 - */ 154 - asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, 155 - RISCV_ISA_EXT_ZBB, 1) 156 - : 157 - : 158 - : 159 - : no_zbb); 160 159 161 160 #ifdef CONFIG_32BIT 162 161 asm_goto_output(".option push \n\ ··· 185 204 end: 186 205 return csum >> 16; 187 206 } 188 - no_zbb: 207 + 189 208 #endif /* CC_HAS_ASM_GOTO_TIED_OUTPUT */ 190 209 #ifndef CONFIG_32BIT 191 210 csum += ror64(csum, 32); ··· 215 234 end = (const unsigned long *)(buff + len); 216 235 csum = do_csum_common(ptr, end, data); 217 236 218 - if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB)) { 237 + if (IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && 238 + IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB) && 239 + riscv_has_extension_likely(RISCV_ISA_EXT_ZBB)) { 219 240 unsigned long fold_temp; 220 - 221 - /* 222 - * Zbb is likely available when the kernel is compiled with Zbb 223 - * support, so nop when Zbb is available and jump when Zbb is 224 - * not available. 225 - */ 226 - asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, 227 - RISCV_ISA_EXT_ZBB, 1) 228 - : 229 - : 230 - : 231 - : no_zbb); 232 241 233 242 #ifdef CONFIG_32BIT 234 243 asm (".option push \n\ ··· 245 274 #endif /* !CONFIG_32BIT */ 246 275 return csum >> 16; 247 276 } 248 - no_zbb: 277 + 249 278 #ifndef CONFIG_32BIT 250 279 csum += ror64(csum, 32); 251 280 csum >>= 32;
+2 -2
arch/riscv/mm/init.c
··· 441 441 442 442 static phys_addr_t __meminit alloc_pte_late(uintptr_t va) 443 443 { 444 - struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0); 444 + struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0); 445 445 446 446 /* 447 447 * We do not know which mm the PTE page is associated to at this point. ··· 526 526 527 527 static phys_addr_t __meminit alloc_pmd_late(uintptr_t va) 528 528 { 529 - struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0); 529 + struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0); 530 530 531 531 /* See comment in alloc_pte_late() regarding NULL passed the ctor */ 532 532 BUG_ON(!ptdesc || !pagetable_pmd_ctor(NULL, ptdesc));
+10 -12
arch/riscv/mm/pgtable.c
··· 9 9 unsigned long address, pte_t *ptep, 10 10 pte_t entry, int dirty) 11 11 { 12 - asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1) 13 - : : : : svvptc); 12 + if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC)) { 13 + if (!pte_same(ptep_get(ptep), entry)) { 14 + __set_pte_at(vma->vm_mm, ptep, entry); 15 + /* Here only not svadu is impacted */ 16 + flush_tlb_page(vma, address); 17 + return true; 18 + } 19 + 20 + return false; 21 + } 14 22 15 23 if (!pte_same(ptep_get(ptep), entry)) 16 24 __set_pte_at(vma->vm_mm, ptep, entry); ··· 27 19 * the case that the PTE changed and the spurious fault case. 28 20 */ 29 21 return true; 30 - 31 - svvptc: 32 - if (!pte_same(ptep_get(ptep), entry)) { 33 - __set_pte_at(vma->vm_mm, ptep, entry); 34 - /* Here only not svadu is impacted */ 35 - flush_tlb_page(vma, address); 36 - return true; 37 - } 38 - 39 - return false; 40 22 } 41 23 42 24 int ptep_test_and_clear_young(struct vm_area_struct *vma,
+1 -6
lib/raid6/recov_rvv.c
··· 4 4 * Author: Chunyan Zhang <zhangchunyan@iscas.ac.cn> 5 5 */ 6 6 7 - #include <asm/vector.h> 8 7 #include <linux/raid/pq.h> 9 - 10 - static int rvv_has_vector(void) 11 - { 12 - return has_vector(); 13 - } 8 + #include "rvv.h" 14 9 15 10 static void __raid6_2data_recov_rvv(int bytes, u8 *p, u8 *q, u8 *dp, 16 11 u8 *dq, const u8 *pbmul,
+155 -144
lib/raid6/rvv.c
··· 9 9 * Copyright 2002-2004 H. Peter Anvin 10 10 */ 11 11 12 - #include <asm/vector.h> 13 - #include <linux/raid/pq.h> 14 12 #include "rvv.h" 15 13 16 - #define NSIZE (riscv_v_vsize / 32) /* NSIZE = vlenb */ 17 - 18 - static int rvv_has_vector(void) 19 - { 20 - return has_vector(); 21 - } 14 + #ifdef __riscv_vector 15 + #error "This code must be built without compiler support for vector" 16 + #endif 22 17 23 18 static void raid6_rvv1_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs) 24 19 { 25 20 u8 **dptr = (u8 **)ptrs; 26 21 u8 *p, *q; 27 - unsigned long vl, d; 22 + unsigned long vl, d, nsize; 28 23 int z, z0; 29 24 30 25 z0 = disks - 3; /* Highest data disk */ ··· 33 38 : "=&r" (vl) 34 39 ); 35 40 41 + nsize = vl; 42 + 36 43 /* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */ 37 - for (d = 0; d < bytes; d += NSIZE * 1) { 44 + for (d = 0; d < bytes; d += nsize * 1) { 38 45 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 39 46 asm volatile (".option push\n" 40 47 ".option arch,+v\n" ··· 44 47 "vmv.v.v v1, v0\n" 45 48 ".option pop\n" 46 49 : : 47 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]) 50 + [wp0]"r"(&dptr[z0][d + 0 * nsize]) 48 51 ); 49 52 50 53 for (z = z0 - 1 ; z >= 0 ; z--) { ··· 68 71 "vxor.vv v0, v0, v2\n" 69 72 ".option pop\n" 70 73 : : 71 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 74 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 72 75 [x1d]"r"(0x1d) 73 76 ); 74 77 } ··· 83 86 "vse8.v v1, (%[wq0])\n" 84 87 ".option pop\n" 85 88 : : 86 - [wp0]"r"(&p[d + NSIZE * 0]), 87 - [wq0]"r"(&q[d + NSIZE * 0]) 89 + [wp0]"r"(&p[d + nsize * 0]), 90 + [wq0]"r"(&q[d + nsize * 0]) 88 91 ); 89 92 } 90 93 } ··· 94 97 { 95 98 u8 **dptr = (u8 **)ptrs; 96 99 u8 *p, *q; 97 - unsigned long vl, d; 100 + unsigned long vl, d, nsize; 98 101 int z, z0; 99 102 100 103 z0 = stop; /* P/Q right side optimization */ ··· 108 111 : "=&r" (vl) 109 112 ); 110 113 114 + nsize = vl; 115 + 111 116 /* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */ 112 - for (d = 0 ; d < bytes ; d += NSIZE * 1) { 117 + for (d = 0 ; d < bytes ; d += nsize * 1) { 113 118 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 114 119 asm volatile (".option push\n" 115 120 ".option arch,+v\n" ··· 119 120 "vmv.v.v v1, v0\n" 120 121 ".option pop\n" 121 122 : : 122 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]) 123 + [wp0]"r"(&dptr[z0][d + 0 * nsize]) 123 124 ); 124 125 125 126 /* P/Q data pages */ ··· 144 145 "vxor.vv v0, v0, v2\n" 145 146 ".option pop\n" 146 147 : : 147 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 148 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 148 149 [x1d]"r"(0x1d) 149 150 ); 150 151 } ··· 184 185 "vse8.v v3, (%[wq0])\n" 185 186 ".option pop\n" 186 187 : : 187 - [wp0]"r"(&p[d + NSIZE * 0]), 188 - [wq0]"r"(&q[d + NSIZE * 0]) 188 + [wp0]"r"(&p[d + nsize * 0]), 189 + [wq0]"r"(&q[d + nsize * 0]) 189 190 ); 190 191 } 191 192 } ··· 194 195 { 195 196 u8 **dptr = (u8 **)ptrs; 196 197 u8 *p, *q; 197 - unsigned long vl, d; 198 + unsigned long vl, d, nsize; 198 199 int z, z0; 199 200 200 201 z0 = disks - 3; /* Highest data disk */ ··· 208 209 : "=&r" (vl) 209 210 ); 210 211 212 + nsize = vl; 213 + 211 214 /* 212 215 * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 213 216 * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11 214 217 */ 215 - for (d = 0; d < bytes; d += NSIZE * 2) { 218 + for (d = 0; d < bytes; d += nsize * 2) { 216 219 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 217 220 asm volatile (".option push\n" 218 221 ".option arch,+v\n" ··· 224 223 "vmv.v.v v5, v4\n" 225 224 ".option pop\n" 226 225 : : 227 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]), 228 - [wp1]"r"(&dptr[z0][d + 1 * NSIZE]) 226 + [wp0]"r"(&dptr[z0][d + 0 * nsize]), 227 + [wp1]"r"(&dptr[z0][d + 1 * nsize]) 229 228 ); 230 229 231 230 for (z = z0 - 1; z >= 0; z--) { ··· 257 256 "vxor.vv v4, v4, v6\n" 258 257 ".option pop\n" 259 258 : : 260 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 261 - [wd1]"r"(&dptr[z][d + 1 * NSIZE]), 259 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 260 + [wd1]"r"(&dptr[z][d + 1 * nsize]), 262 261 [x1d]"r"(0x1d) 263 262 ); 264 263 } ··· 275 274 "vse8.v v5, (%[wq1])\n" 276 275 ".option pop\n" 277 276 : : 278 - [wp0]"r"(&p[d + NSIZE * 0]), 279 - [wq0]"r"(&q[d + NSIZE * 0]), 280 - [wp1]"r"(&p[d + NSIZE * 1]), 281 - [wq1]"r"(&q[d + NSIZE * 1]) 277 + [wp0]"r"(&p[d + nsize * 0]), 278 + [wq0]"r"(&q[d + nsize * 0]), 279 + [wp1]"r"(&p[d + nsize * 1]), 280 + [wq1]"r"(&q[d + nsize * 1]) 282 281 ); 283 282 } 284 283 } ··· 288 287 { 289 288 u8 **dptr = (u8 **)ptrs; 290 289 u8 *p, *q; 291 - unsigned long vl, d; 290 + unsigned long vl, d, nsize; 292 291 int z, z0; 293 292 294 293 z0 = stop; /* P/Q right side optimization */ ··· 302 301 : "=&r" (vl) 303 302 ); 304 303 304 + nsize = vl; 305 + 305 306 /* 306 307 * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 307 308 * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11 308 309 */ 309 - for (d = 0; d < bytes; d += NSIZE * 2) { 310 + for (d = 0; d < bytes; d += nsize * 2) { 310 311 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 311 312 asm volatile (".option push\n" 312 313 ".option arch,+v\n" ··· 318 315 "vmv.v.v v5, v4\n" 319 316 ".option pop\n" 320 317 : : 321 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]), 322 - [wp1]"r"(&dptr[z0][d + 1 * NSIZE]) 318 + [wp0]"r"(&dptr[z0][d + 0 * nsize]), 319 + [wp1]"r"(&dptr[z0][d + 1 * nsize]) 323 320 ); 324 321 325 322 /* P/Q data pages */ ··· 352 349 "vxor.vv v4, v4, v6\n" 353 350 ".option pop\n" 354 351 : : 355 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 356 - [wd1]"r"(&dptr[z][d + 1 * NSIZE]), 352 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 353 + [wd1]"r"(&dptr[z][d + 1 * nsize]), 357 354 [x1d]"r"(0x1d) 358 355 ); 359 356 } ··· 406 403 "vse8.v v7, (%[wq1])\n" 407 404 ".option pop\n" 408 405 : : 409 - [wp0]"r"(&p[d + NSIZE * 0]), 410 - [wq0]"r"(&q[d + NSIZE * 0]), 411 - [wp1]"r"(&p[d + NSIZE * 1]), 412 - [wq1]"r"(&q[d + NSIZE * 1]) 406 + [wp0]"r"(&p[d + nsize * 0]), 407 + [wq0]"r"(&q[d + nsize * 0]), 408 + [wp1]"r"(&p[d + nsize * 1]), 409 + [wq1]"r"(&q[d + nsize * 1]) 413 410 ); 414 411 } 415 412 } ··· 418 415 { 419 416 u8 **dptr = (u8 **)ptrs; 420 417 u8 *p, *q; 421 - unsigned long vl, d; 418 + unsigned long vl, d, nsize; 422 419 int z, z0; 423 420 424 421 z0 = disks - 3; /* Highest data disk */ ··· 432 429 : "=&r" (vl) 433 430 ); 434 431 432 + nsize = vl; 433 + 435 434 /* 436 435 * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 437 436 * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11 438 437 * v8:wp2, v9:wq2, v10:wd2/w22, v11:w12 439 438 * v12:wp3, v13:wq3, v14:wd3/w23, v15:w13 440 439 */ 441 - for (d = 0; d < bytes; d += NSIZE * 4) { 440 + for (d = 0; d < bytes; d += nsize * 4) { 442 441 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 443 442 asm volatile (".option push\n" 444 443 ".option arch,+v\n" ··· 454 449 "vmv.v.v v13, v12\n" 455 450 ".option pop\n" 456 451 : : 457 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]), 458 - [wp1]"r"(&dptr[z0][d + 1 * NSIZE]), 459 - [wp2]"r"(&dptr[z0][d + 2 * NSIZE]), 460 - [wp3]"r"(&dptr[z0][d + 3 * NSIZE]) 452 + [wp0]"r"(&dptr[z0][d + 0 * nsize]), 453 + [wp1]"r"(&dptr[z0][d + 1 * nsize]), 454 + [wp2]"r"(&dptr[z0][d + 2 * nsize]), 455 + [wp3]"r"(&dptr[z0][d + 3 * nsize]) 461 456 ); 462 457 463 458 for (z = z0 - 1; z >= 0; z--) { ··· 505 500 "vxor.vv v12, v12, v14\n" 506 501 ".option pop\n" 507 502 : : 508 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 509 - [wd1]"r"(&dptr[z][d + 1 * NSIZE]), 510 - [wd2]"r"(&dptr[z][d + 2 * NSIZE]), 511 - [wd3]"r"(&dptr[z][d + 3 * NSIZE]), 503 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 504 + [wd1]"r"(&dptr[z][d + 1 * nsize]), 505 + [wd2]"r"(&dptr[z][d + 2 * nsize]), 506 + [wd3]"r"(&dptr[z][d + 3 * nsize]), 512 507 [x1d]"r"(0x1d) 513 508 ); 514 509 } ··· 529 524 "vse8.v v13, (%[wq3])\n" 530 525 ".option pop\n" 531 526 : : 532 - [wp0]"r"(&p[d + NSIZE * 0]), 533 - [wq0]"r"(&q[d + NSIZE * 0]), 534 - [wp1]"r"(&p[d + NSIZE * 1]), 535 - [wq1]"r"(&q[d + NSIZE * 1]), 536 - [wp2]"r"(&p[d + NSIZE * 2]), 537 - [wq2]"r"(&q[d + NSIZE * 2]), 538 - [wp3]"r"(&p[d + NSIZE * 3]), 539 - [wq3]"r"(&q[d + NSIZE * 3]) 527 + [wp0]"r"(&p[d + nsize * 0]), 528 + [wq0]"r"(&q[d + nsize * 0]), 529 + [wp1]"r"(&p[d + nsize * 1]), 530 + [wq1]"r"(&q[d + nsize * 1]), 531 + [wp2]"r"(&p[d + nsize * 2]), 532 + [wq2]"r"(&q[d + nsize * 2]), 533 + [wp3]"r"(&p[d + nsize * 3]), 534 + [wq3]"r"(&q[d + nsize * 3]) 540 535 ); 541 536 } 542 537 } ··· 546 541 { 547 542 u8 **dptr = (u8 **)ptrs; 548 543 u8 *p, *q; 549 - unsigned long vl, d; 544 + unsigned long vl, d, nsize; 550 545 int z, z0; 551 546 552 547 z0 = stop; /* P/Q right side optimization */ ··· 560 555 : "=&r" (vl) 561 556 ); 562 557 558 + nsize = vl; 559 + 563 560 /* 564 561 * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 565 562 * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11 566 563 * v8:wp2, v9:wq2, v10:wd2/w22, v11:w12 567 564 * v12:wp3, v13:wq3, v14:wd3/w23, v15:w13 568 565 */ 569 - for (d = 0; d < bytes; d += NSIZE * 4) { 566 + for (d = 0; d < bytes; d += nsize * 4) { 570 567 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 571 568 asm volatile (".option push\n" 572 569 ".option arch,+v\n" ··· 582 575 "vmv.v.v v13, v12\n" 583 576 ".option pop\n" 584 577 : : 585 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]), 586 - [wp1]"r"(&dptr[z0][d + 1 * NSIZE]), 587 - [wp2]"r"(&dptr[z0][d + 2 * NSIZE]), 588 - [wp3]"r"(&dptr[z0][d + 3 * NSIZE]) 578 + [wp0]"r"(&dptr[z0][d + 0 * nsize]), 579 + [wp1]"r"(&dptr[z0][d + 1 * nsize]), 580 + [wp2]"r"(&dptr[z0][d + 2 * nsize]), 581 + [wp3]"r"(&dptr[z0][d + 3 * nsize]) 589 582 ); 590 583 591 584 /* P/Q data pages */ ··· 634 627 "vxor.vv v12, v12, v14\n" 635 628 ".option pop\n" 636 629 : : 637 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 638 - [wd1]"r"(&dptr[z][d + 1 * NSIZE]), 639 - [wd2]"r"(&dptr[z][d + 2 * NSIZE]), 640 - [wd3]"r"(&dptr[z][d + 3 * NSIZE]), 630 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 631 + [wd1]"r"(&dptr[z][d + 1 * nsize]), 632 + [wd2]"r"(&dptr[z][d + 2 * nsize]), 633 + [wd3]"r"(&dptr[z][d + 3 * nsize]), 641 634 [x1d]"r"(0x1d) 642 635 ); 643 636 } ··· 716 709 "vse8.v v15, (%[wq3])\n" 717 710 ".option pop\n" 718 711 : : 719 - [wp0]"r"(&p[d + NSIZE * 0]), 720 - [wq0]"r"(&q[d + NSIZE * 0]), 721 - [wp1]"r"(&p[d + NSIZE * 1]), 722 - [wq1]"r"(&q[d + NSIZE * 1]), 723 - [wp2]"r"(&p[d + NSIZE * 2]), 724 - [wq2]"r"(&q[d + NSIZE * 2]), 725 - [wp3]"r"(&p[d + NSIZE * 3]), 726 - [wq3]"r"(&q[d + NSIZE * 3]) 712 + [wp0]"r"(&p[d + nsize * 0]), 713 + [wq0]"r"(&q[d + nsize * 0]), 714 + [wp1]"r"(&p[d + nsize * 1]), 715 + [wq1]"r"(&q[d + nsize * 1]), 716 + [wp2]"r"(&p[d + nsize * 2]), 717 + [wq2]"r"(&q[d + nsize * 2]), 718 + [wp3]"r"(&p[d + nsize * 3]), 719 + [wq3]"r"(&q[d + nsize * 3]) 727 720 ); 728 721 } 729 722 } ··· 732 725 { 733 726 u8 **dptr = (u8 **)ptrs; 734 727 u8 *p, *q; 735 - unsigned long vl, d; 728 + unsigned long vl, d, nsize; 736 729 int z, z0; 737 730 738 731 z0 = disks - 3; /* Highest data disk */ ··· 746 739 : "=&r" (vl) 747 740 ); 748 741 742 + nsize = vl; 743 + 749 744 /* 750 745 * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 751 746 * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11 ··· 758 749 * v24:wp6, v25:wq6, v26:wd6/w26, v27:w16 759 750 * v28:wp7, v29:wq7, v30:wd7/w27, v31:w17 760 751 */ 761 - for (d = 0; d < bytes; d += NSIZE * 8) { 752 + for (d = 0; d < bytes; d += nsize * 8) { 762 753 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 763 754 asm volatile (".option push\n" 764 755 ".option arch,+v\n" ··· 780 771 "vmv.v.v v29, v28\n" 781 772 ".option pop\n" 782 773 : : 783 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]), 784 - [wp1]"r"(&dptr[z0][d + 1 * NSIZE]), 785 - [wp2]"r"(&dptr[z0][d + 2 * NSIZE]), 786 - [wp3]"r"(&dptr[z0][d + 3 * NSIZE]), 787 - [wp4]"r"(&dptr[z0][d + 4 * NSIZE]), 788 - [wp5]"r"(&dptr[z0][d + 5 * NSIZE]), 789 - [wp6]"r"(&dptr[z0][d + 6 * NSIZE]), 790 - [wp7]"r"(&dptr[z0][d + 7 * NSIZE]) 774 + [wp0]"r"(&dptr[z0][d + 0 * nsize]), 775 + [wp1]"r"(&dptr[z0][d + 1 * nsize]), 776 + [wp2]"r"(&dptr[z0][d + 2 * nsize]), 777 + [wp3]"r"(&dptr[z0][d + 3 * nsize]), 778 + [wp4]"r"(&dptr[z0][d + 4 * nsize]), 779 + [wp5]"r"(&dptr[z0][d + 5 * nsize]), 780 + [wp6]"r"(&dptr[z0][d + 6 * nsize]), 781 + [wp7]"r"(&dptr[z0][d + 7 * nsize]) 791 782 ); 792 783 793 784 for (z = z0 - 1; z >= 0; z--) { ··· 867 858 "vxor.vv v28, v28, v30\n" 868 859 ".option pop\n" 869 860 : : 870 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 871 - [wd1]"r"(&dptr[z][d + 1 * NSIZE]), 872 - [wd2]"r"(&dptr[z][d + 2 * NSIZE]), 873 - [wd3]"r"(&dptr[z][d + 3 * NSIZE]), 874 - [wd4]"r"(&dptr[z][d + 4 * NSIZE]), 875 - [wd5]"r"(&dptr[z][d + 5 * NSIZE]), 876 - [wd6]"r"(&dptr[z][d + 6 * NSIZE]), 877 - [wd7]"r"(&dptr[z][d + 7 * NSIZE]), 861 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 862 + [wd1]"r"(&dptr[z][d + 1 * nsize]), 863 + [wd2]"r"(&dptr[z][d + 2 * nsize]), 864 + [wd3]"r"(&dptr[z][d + 3 * nsize]), 865 + [wd4]"r"(&dptr[z][d + 4 * nsize]), 866 + [wd5]"r"(&dptr[z][d + 5 * nsize]), 867 + [wd6]"r"(&dptr[z][d + 6 * nsize]), 868 + [wd7]"r"(&dptr[z][d + 7 * nsize]), 878 869 [x1d]"r"(0x1d) 879 870 ); 880 871 } ··· 903 894 "vse8.v v29, (%[wq7])\n" 904 895 ".option pop\n" 905 896 : : 906 - [wp0]"r"(&p[d + NSIZE * 0]), 907 - [wq0]"r"(&q[d + NSIZE * 0]), 908 - [wp1]"r"(&p[d + NSIZE * 1]), 909 - [wq1]"r"(&q[d + NSIZE * 1]), 910 - [wp2]"r"(&p[d + NSIZE * 2]), 911 - [wq2]"r"(&q[d + NSIZE * 2]), 912 - [wp3]"r"(&p[d + NSIZE * 3]), 913 - [wq3]"r"(&q[d + NSIZE * 3]), 914 - [wp4]"r"(&p[d + NSIZE * 4]), 915 - [wq4]"r"(&q[d + NSIZE * 4]), 916 - [wp5]"r"(&p[d + NSIZE * 5]), 917 - [wq5]"r"(&q[d + NSIZE * 5]), 918 - [wp6]"r"(&p[d + NSIZE * 6]), 919 - [wq6]"r"(&q[d + NSIZE * 6]), 920 - [wp7]"r"(&p[d + NSIZE * 7]), 921 - [wq7]"r"(&q[d + NSIZE * 7]) 897 + [wp0]"r"(&p[d + nsize * 0]), 898 + [wq0]"r"(&q[d + nsize * 0]), 899 + [wp1]"r"(&p[d + nsize * 1]), 900 + [wq1]"r"(&q[d + nsize * 1]), 901 + [wp2]"r"(&p[d + nsize * 2]), 902 + [wq2]"r"(&q[d + nsize * 2]), 903 + [wp3]"r"(&p[d + nsize * 3]), 904 + [wq3]"r"(&q[d + nsize * 3]), 905 + [wp4]"r"(&p[d + nsize * 4]), 906 + [wq4]"r"(&q[d + nsize * 4]), 907 + [wp5]"r"(&p[d + nsize * 5]), 908 + [wq5]"r"(&q[d + nsize * 5]), 909 + [wp6]"r"(&p[d + nsize * 6]), 910 + [wq6]"r"(&q[d + nsize * 6]), 911 + [wp7]"r"(&p[d + nsize * 7]), 912 + [wq7]"r"(&q[d + nsize * 7]) 922 913 ); 923 914 } 924 915 } ··· 928 919 { 929 920 u8 **dptr = (u8 **)ptrs; 930 921 u8 *p, *q; 931 - unsigned long vl, d; 922 + unsigned long vl, d, nsize; 932 923 int z, z0; 933 924 934 925 z0 = stop; /* P/Q right side optimization */ ··· 942 933 : "=&r" (vl) 943 934 ); 944 935 936 + nsize = vl; 937 + 945 938 /* 946 939 * v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 947 940 * v4:wp1, v5:wq1, v6:wd1/w21, v7:w11 ··· 954 943 * v24:wp6, v25:wq6, v26:wd6/w26, v27:w16 955 944 * v28:wp7, v29:wq7, v30:wd7/w27, v31:w17 956 945 */ 957 - for (d = 0; d < bytes; d += NSIZE * 8) { 946 + for (d = 0; d < bytes; d += nsize * 8) { 958 947 /* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */ 959 948 asm volatile (".option push\n" 960 949 ".option arch,+v\n" ··· 976 965 "vmv.v.v v29, v28\n" 977 966 ".option pop\n" 978 967 : : 979 - [wp0]"r"(&dptr[z0][d + 0 * NSIZE]), 980 - [wp1]"r"(&dptr[z0][d + 1 * NSIZE]), 981 - [wp2]"r"(&dptr[z0][d + 2 * NSIZE]), 982 - [wp3]"r"(&dptr[z0][d + 3 * NSIZE]), 983 - [wp4]"r"(&dptr[z0][d + 4 * NSIZE]), 984 - [wp5]"r"(&dptr[z0][d + 5 * NSIZE]), 985 - [wp6]"r"(&dptr[z0][d + 6 * NSIZE]), 986 - [wp7]"r"(&dptr[z0][d + 7 * NSIZE]) 968 + [wp0]"r"(&dptr[z0][d + 0 * nsize]), 969 + [wp1]"r"(&dptr[z0][d + 1 * nsize]), 970 + [wp2]"r"(&dptr[z0][d + 2 * nsize]), 971 + [wp3]"r"(&dptr[z0][d + 3 * nsize]), 972 + [wp4]"r"(&dptr[z0][d + 4 * nsize]), 973 + [wp5]"r"(&dptr[z0][d + 5 * nsize]), 974 + [wp6]"r"(&dptr[z0][d + 6 * nsize]), 975 + [wp7]"r"(&dptr[z0][d + 7 * nsize]) 987 976 ); 988 977 989 978 /* P/Q data pages */ ··· 1064 1053 "vxor.vv v28, v28, v30\n" 1065 1054 ".option pop\n" 1066 1055 : : 1067 - [wd0]"r"(&dptr[z][d + 0 * NSIZE]), 1068 - [wd1]"r"(&dptr[z][d + 1 * NSIZE]), 1069 - [wd2]"r"(&dptr[z][d + 2 * NSIZE]), 1070 - [wd3]"r"(&dptr[z][d + 3 * NSIZE]), 1071 - [wd4]"r"(&dptr[z][d + 4 * NSIZE]), 1072 - [wd5]"r"(&dptr[z][d + 5 * NSIZE]), 1073 - [wd6]"r"(&dptr[z][d + 6 * NSIZE]), 1074 - [wd7]"r"(&dptr[z][d + 7 * NSIZE]), 1056 + [wd0]"r"(&dptr[z][d + 0 * nsize]), 1057 + [wd1]"r"(&dptr[z][d + 1 * nsize]), 1058 + [wd2]"r"(&dptr[z][d + 2 * nsize]), 1059 + [wd3]"r"(&dptr[z][d + 3 * nsize]), 1060 + [wd4]"r"(&dptr[z][d + 4 * nsize]), 1061 + [wd5]"r"(&dptr[z][d + 5 * nsize]), 1062 + [wd6]"r"(&dptr[z][d + 6 * nsize]), 1063 + [wd7]"r"(&dptr[z][d + 7 * nsize]), 1075 1064 [x1d]"r"(0x1d) 1076 1065 ); 1077 1066 } ··· 1202 1191 "vse8.v v31, (%[wq7])\n" 1203 1192 ".option pop\n" 1204 1193 : : 1205 - [wp0]"r"(&p[d + NSIZE * 0]), 1206 - [wq0]"r"(&q[d + NSIZE * 0]), 1207 - [wp1]"r"(&p[d + NSIZE * 1]), 1208 - [wq1]"r"(&q[d + NSIZE * 1]), 1209 - [wp2]"r"(&p[d + NSIZE * 2]), 1210 - [wq2]"r"(&q[d + NSIZE * 2]), 1211 - [wp3]"r"(&p[d + NSIZE * 3]), 1212 - [wq3]"r"(&q[d + NSIZE * 3]), 1213 - [wp4]"r"(&p[d + NSIZE * 4]), 1214 - [wq4]"r"(&q[d + NSIZE * 4]), 1215 - [wp5]"r"(&p[d + NSIZE * 5]), 1216 - [wq5]"r"(&q[d + NSIZE * 5]), 1217 - [wp6]"r"(&p[d + NSIZE * 6]), 1218 - [wq6]"r"(&q[d + NSIZE * 6]), 1219 - [wp7]"r"(&p[d + NSIZE * 7]), 1220 - [wq7]"r"(&q[d + NSIZE * 7]) 1194 + [wp0]"r"(&p[d + nsize * 0]), 1195 + [wq0]"r"(&q[d + nsize * 0]), 1196 + [wp1]"r"(&p[d + nsize * 1]), 1197 + [wq1]"r"(&q[d + nsize * 1]), 1198 + [wp2]"r"(&p[d + nsize * 2]), 1199 + [wq2]"r"(&q[d + nsize * 2]), 1200 + [wp3]"r"(&p[d + nsize * 3]), 1201 + [wq3]"r"(&q[d + nsize * 3]), 1202 + [wp4]"r"(&p[d + nsize * 4]), 1203 + [wq4]"r"(&q[d + nsize * 4]), 1204 + [wp5]"r"(&p[d + nsize * 5]), 1205 + [wq5]"r"(&q[d + nsize * 5]), 1206 + [wp6]"r"(&p[d + nsize * 6]), 1207 + [wq6]"r"(&q[d + nsize * 6]), 1208 + [wp7]"r"(&p[d + nsize * 7]), 1209 + [wq7]"r"(&q[d + nsize * 7]) 1221 1210 ); 1222 1211 } 1223 1212 }
+17
lib/raid6/rvv.h
··· 7 7 * Definitions for RISC-V RAID-6 code 8 8 */ 9 9 10 + #ifdef __KERNEL__ 11 + #include <asm/vector.h> 12 + #else 13 + #define kernel_vector_begin() 14 + #define kernel_vector_end() 15 + #include <sys/auxv.h> 16 + #include <asm/hwcap.h> 17 + #define has_vector() (getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_V) 18 + #endif 19 + 20 + #include <linux/raid/pq.h> 21 + 22 + static int rvv_has_vector(void) 23 + { 24 + return has_vector(); 25 + } 26 + 10 27 #define RAID6_RVV_WRAPPER(_n) \ 11 28 static void raid6_rvv ## _n ## _gen_syndrome(int disks, \ 12 29 size_t bytes, void **ptrs) \
+8
lib/raid6/test/Makefile
··· 35 35 HAS_NEON = yes 36 36 endif 37 37 38 + ifeq ($(findstring riscv,$(ARCH)),riscv) 39 + CFLAGS += -I../../../arch/riscv/include -DCONFIG_RISCV=1 40 + HAS_RVV = yes 41 + endif 42 + 38 43 ifeq ($(findstring ppc,$(ARCH)),ppc) 39 44 CFLAGS += -I../../../arch/powerpc/include 40 45 HAS_ALTIVEC := $(shell printf '$(pound)include <altivec.h>\nvector int a;\n' |\ ··· 68 63 vpermxor1.o vpermxor2.o vpermxor4.o vpermxor8.o 69 64 else ifeq ($(ARCH),loongarch64) 70 65 OBJS += loongarch_simd.o recov_loongarch_simd.o 66 + else ifeq ($(HAS_RVV),yes) 67 + OBJS += rvv.o recov_rvv.o 68 + CFLAGS += -DCONFIG_RISCV_ISA_V=1 71 69 endif 72 70 73 71 .c.o:
+135 -28
tools/testing/selftests/riscv/hwprobe/cbo.c
··· 15 15 #include <linux/compiler.h> 16 16 #include <linux/kernel.h> 17 17 #include <asm/ucontext.h> 18 + #include <getopt.h> 18 19 19 20 #include "hwprobe.h" 20 21 #include "../../kselftest.h" 21 22 22 23 #define MK_CBO(fn) le32_bswap((uint32_t)(fn) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15) 24 + #define MK_PREFETCH(fn) \ 25 + le32_bswap(0 << 25 | (uint32_t)(fn) << 20 | 10 << 15 | 6 << 12 | 0 << 7 | 19) 23 26 24 27 static char mem[4096] __aligned(4096) = { [0 ... 4095] = 0xa5 }; 25 28 26 - static bool illegal_insn; 29 + static bool got_fault; 27 30 28 - static void sigill_handler(int sig, siginfo_t *info, void *context) 31 + static void fault_handler(int sig, siginfo_t *info, void *context) 29 32 { 30 33 unsigned long *regs = (unsigned long *)&((ucontext_t *)context)->uc_mcontext; 31 34 uint32_t insn = *(uint32_t *)regs[0]; 32 35 33 - assert(insn == MK_CBO(regs[11])); 36 + if (sig == SIGILL) 37 + assert(insn == MK_CBO(regs[11])); 34 38 35 - illegal_insn = true; 39 + if (sig == SIGSEGV || sig == SIGBUS) 40 + assert(insn == MK_PREFETCH(regs[11])); 41 + 42 + got_fault = true; 36 43 regs[0] += 4; 37 44 } 38 45 ··· 52 45 : : "r" (base), "i" (fn), "i" (MK_CBO(fn)) : "a0", "a1", "memory"); \ 53 46 }) 54 47 48 + #define prefetch_insn(base, fn) \ 49 + ({ \ 50 + asm volatile( \ 51 + "mv a0, %0\n" \ 52 + "li a1, %1\n" \ 53 + ".4byte %2\n" \ 54 + : : "r" (base), "i" (fn), "i" (MK_PREFETCH(fn)) : "a0", "a1"); \ 55 + }) 56 + 55 57 static void cbo_inval(char *base) { cbo_insn(base, 0); } 56 58 static void cbo_clean(char *base) { cbo_insn(base, 1); } 57 59 static void cbo_flush(char *base) { cbo_insn(base, 2); } 58 60 static void cbo_zero(char *base) { cbo_insn(base, 4); } 61 + static void prefetch_i(char *base) { prefetch_insn(base, 0); } 62 + static void prefetch_r(char *base) { prefetch_insn(base, 1); } 63 + static void prefetch_w(char *base) { prefetch_insn(base, 3); } 59 64 60 65 static void test_no_cbo_inval(void *arg) 61 66 { 62 67 ksft_print_msg("Testing cbo.inval instruction remain privileged\n"); 63 - illegal_insn = false; 68 + got_fault = false; 64 69 cbo_inval(&mem[0]); 65 - ksft_test_result(illegal_insn, "No cbo.inval\n"); 70 + ksft_test_result(got_fault, "No cbo.inval\n"); 66 71 } 67 72 68 73 static void test_no_zicbom(void *arg) 69 74 { 70 75 ksft_print_msg("Testing Zicbom instructions remain privileged\n"); 71 76 72 - illegal_insn = false; 77 + got_fault = false; 73 78 cbo_clean(&mem[0]); 74 - ksft_test_result(illegal_insn, "No cbo.clean\n"); 79 + ksft_test_result(got_fault, "No cbo.clean\n"); 75 80 76 - illegal_insn = false; 81 + got_fault = false; 77 82 cbo_flush(&mem[0]); 78 - ksft_test_result(illegal_insn, "No cbo.flush\n"); 83 + ksft_test_result(got_fault, "No cbo.flush\n"); 79 84 } 80 85 81 86 static void test_no_zicboz(void *arg) 82 87 { 83 88 ksft_print_msg("No Zicboz, testing cbo.zero remains privileged\n"); 84 89 85 - illegal_insn = false; 90 + got_fault = false; 86 91 cbo_zero(&mem[0]); 87 - ksft_test_result(illegal_insn, "No cbo.zero\n"); 92 + ksft_test_result(got_fault, "No cbo.zero\n"); 88 93 } 89 94 90 95 static bool is_power_of_2(__u64 n) 91 96 { 92 97 return n != 0 && (n & (n - 1)) == 0; 98 + } 99 + 100 + static void test_zicbop(void *arg) 101 + { 102 + struct riscv_hwprobe pair = { 103 + .key = RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE, 104 + }; 105 + struct sigaction act = { 106 + .sa_sigaction = &fault_handler, 107 + .sa_flags = SA_SIGINFO 108 + }; 109 + struct sigaction dfl = { 110 + .sa_handler = SIG_DFL 111 + }; 112 + cpu_set_t *cpus = (cpu_set_t *)arg; 113 + __u64 block_size; 114 + long rc; 115 + 116 + rc = sigaction(SIGSEGV, &act, NULL); 117 + assert(rc == 0); 118 + rc = sigaction(SIGBUS, &act, NULL); 119 + assert(rc == 0); 120 + 121 + rc = riscv_hwprobe(&pair, 1, sizeof(cpu_set_t), (unsigned long *)cpus, 0); 122 + block_size = pair.value; 123 + ksft_test_result(rc == 0 && pair.key == RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE && 124 + is_power_of_2(block_size), "Zicbop block size\n"); 125 + ksft_print_msg("Zicbop block size: %llu\n", block_size); 126 + 127 + got_fault = false; 128 + prefetch_i(&mem[0]); 129 + prefetch_r(&mem[0]); 130 + prefetch_w(&mem[0]); 131 + ksft_test_result(!got_fault, "Zicbop prefetch.* on valid address\n"); 132 + 133 + got_fault = false; 134 + prefetch_i(NULL); 135 + prefetch_r(NULL); 136 + prefetch_w(NULL); 137 + ksft_test_result(!got_fault, "Zicbop prefetch.* on NULL\n"); 138 + 139 + rc = sigaction(SIGBUS, &dfl, NULL); 140 + assert(rc == 0); 141 + rc = sigaction(SIGSEGV, &dfl, NULL); 142 + assert(rc == 0); 93 143 } 94 144 95 145 static void test_zicbom(void *arg) ··· 164 100 is_power_of_2(block_size), "Zicbom block size\n"); 165 101 ksft_print_msg("Zicbom block size: %llu\n", block_size); 166 102 167 - illegal_insn = false; 103 + got_fault = false; 168 104 cbo_clean(&mem[block_size]); 169 - ksft_test_result(!illegal_insn, "cbo.clean\n"); 105 + ksft_test_result(!got_fault, "cbo.clean\n"); 170 106 171 - illegal_insn = false; 107 + got_fault = false; 172 108 cbo_flush(&mem[block_size]); 173 - ksft_test_result(!illegal_insn, "cbo.flush\n"); 109 + ksft_test_result(!got_fault, "cbo.flush\n"); 174 110 } 175 111 176 112 static void test_zicboz(void *arg) ··· 189 125 is_power_of_2(block_size), "Zicboz block size\n"); 190 126 ksft_print_msg("Zicboz block size: %llu\n", block_size); 191 127 192 - illegal_insn = false; 128 + got_fault = false; 193 129 cbo_zero(&mem[block_size]); 194 - ksft_test_result(!illegal_insn, "cbo.zero\n"); 130 + ksft_test_result(!got_fault, "cbo.zero\n"); 195 131 196 - if (illegal_insn || !is_power_of_2(block_size)) { 132 + if (got_fault || !is_power_of_2(block_size)) { 197 133 ksft_test_result_skip("cbo.zero check\n"); 198 134 return; 199 135 } ··· 241 177 rc = riscv_hwprobe(&pair, 1, sizeof(cpu_set_t), (unsigned long *)&one_cpu, 0); 242 178 assert(rc == 0 && pair.key == RISCV_HWPROBE_KEY_IMA_EXT_0); 243 179 244 - cbostr = cbo == RISCV_HWPROBE_EXT_ZICBOZ ? "Zicboz" : "Zicbom"; 180 + switch (cbo) { 181 + case RISCV_HWPROBE_EXT_ZICBOZ: 182 + cbostr = "Zicboz"; 183 + break; 184 + case RISCV_HWPROBE_EXT_ZICBOM: 185 + cbostr = "Zicbom"; 186 + break; 187 + case RISCV_HWPROBE_EXT_ZICBOP: 188 + cbostr = "Zicbop"; 189 + break; 190 + default: 191 + ksft_exit_fail_msg("Internal error: invalid cbo %llu\n", cbo); 192 + } 245 193 246 194 if (pair.value & cbo) 247 195 ksft_exit_fail_msg("%s is only present on a subset of harts.\n" ··· 270 194 TEST_ZICBOM, 271 195 TEST_NO_ZICBOM, 272 196 TEST_NO_CBO_INVAL, 197 + TEST_ZICBOP, 273 198 }; 274 199 275 200 static struct test_info { ··· 283 206 [TEST_ZICBOM] = { .nr_tests = 3, test_zicbom }, 284 207 [TEST_NO_ZICBOM] = { .nr_tests = 2, test_no_zicbom }, 285 208 [TEST_NO_CBO_INVAL] = { .nr_tests = 1, test_no_cbo_inval }, 209 + [TEST_ZICBOP] = { .nr_tests = 3, test_zicbop }, 210 + }; 211 + 212 + static const struct option long_opts[] = { 213 + {"zicbom-raises-sigill", no_argument, 0, 'm'}, 214 + {"zicboz-raises-sigill", no_argument, 0, 'z'}, 215 + {0, 0, 0, 0} 286 216 }; 287 217 288 218 int main(int argc, char **argv) 289 219 { 290 220 struct sigaction act = { 291 - .sa_sigaction = &sigill_handler, 221 + .sa_sigaction = &fault_handler, 292 222 .sa_flags = SA_SIGINFO, 293 223 }; 294 224 struct riscv_hwprobe pair; 295 225 unsigned int plan = 0; 296 226 cpu_set_t cpus; 297 227 long rc; 298 - int i; 228 + int i, opt, long_index; 299 229 300 - if (argc > 1 && !strcmp(argv[1], "--sigill")) { 301 - rc = sigaction(SIGILL, &act, NULL); 302 - assert(rc == 0); 303 - tests[TEST_NO_ZICBOZ].enabled = true; 304 - tests[TEST_NO_ZICBOM].enabled = true; 305 - tests[TEST_NO_CBO_INVAL].enabled = true; 230 + long_index = 0; 231 + 232 + while ((opt = getopt_long(argc, argv, "mz", long_opts, &long_index)) != -1) { 233 + switch (opt) { 234 + case 'm': 235 + tests[TEST_NO_ZICBOM].enabled = true; 236 + tests[TEST_NO_CBO_INVAL].enabled = true; 237 + rc = sigaction(SIGILL, &act, NULL); 238 + assert(rc == 0); 239 + break; 240 + case 'z': 241 + tests[TEST_NO_ZICBOZ].enabled = true; 242 + tests[TEST_NO_CBO_INVAL].enabled = true; 243 + rc = sigaction(SIGILL, &act, NULL); 244 + assert(rc == 0); 245 + break; 246 + case '?': 247 + fprintf(stderr, 248 + "Usage: %s [--zicbom-raises-sigill|-m] [--zicboz-raises-sigill|-z]\n", 249 + argv[0]); 250 + exit(1); 251 + default: 252 + break; 253 + } 306 254 } 307 255 308 256 rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus); ··· 354 252 } else { 355 253 check_no_zicbo_cpus(&cpus, RISCV_HWPROBE_EXT_ZICBOM); 356 254 } 255 + 256 + if (pair.value & RISCV_HWPROBE_EXT_ZICBOP) 257 + tests[TEST_ZICBOP].enabled = true; 258 + else 259 + check_no_zicbo_cpus(&cpus, RISCV_HWPROBE_EXT_ZICBOP); 357 260 358 261 for (i = 0; i < ARRAY_SIZE(tests); ++i) 359 262 plan += tests[i].enabled ? tests[i].nr_tests : 0;
+4 -1
tools/testing/selftests/riscv/vector/Makefile
··· 2 2 # Copyright (C) 2021 ARM Limited 3 3 # Originally tools/testing/arm64/abi/Makefile 4 4 5 - TEST_GEN_PROGS := v_initval vstate_prctl 5 + TEST_GEN_PROGS := v_initval vstate_prctl vstate_ptrace 6 6 TEST_GEN_PROGS_EXTENDED := vstate_exec_nolibc v_exec_initval_nolibc 7 7 8 8 include ../../lib.mk ··· 26 26 $(OUTPUT)/v_exec_initval_nolibc: v_exec_initval_nolibc.c 27 27 $(CC) -nostdlib -static -include ../../../../include/nolibc/nolibc.h \ 28 28 -Wall $(CFLAGS) $(LDFLAGS) $^ -o $@ -lgcc 29 + 30 + $(OUTPUT)/vstate_ptrace: vstate_ptrace.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o 31 + $(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
+134
tools/testing/selftests/riscv/vector/vstate_ptrace.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #include <stdio.h> 3 + #include <stdlib.h> 4 + #include <asm/ptrace.h> 5 + #include <linux/elf.h> 6 + #include <sys/ptrace.h> 7 + #include <sys/uio.h> 8 + #include <sys/wait.h> 9 + #include "../../kselftest.h" 10 + #include "v_helpers.h" 11 + 12 + int parent_set_val, child_set_val; 13 + 14 + static long do_ptrace(enum __ptrace_request op, pid_t pid, long type, size_t size, void *data) 15 + { 16 + struct iovec v_iovec = { 17 + .iov_len = size, 18 + .iov_base = data 19 + }; 20 + 21 + return ptrace(op, pid, type, &v_iovec); 22 + } 23 + 24 + static int do_child(void) 25 + { 26 + int out; 27 + 28 + if (ptrace(PTRACE_TRACEME, -1, NULL, NULL)) { 29 + ksft_perror("PTRACE_TRACEME failed\n"); 30 + return EXIT_FAILURE; 31 + } 32 + 33 + asm volatile (".option push\n\t" 34 + ".option arch, +v\n\t" 35 + ".option norvc\n\t" 36 + "vsetivli x0, 1, e32, m1, ta, ma\n\t" 37 + "vmv.s.x v31, %[in]\n\t" 38 + "ebreak\n\t" 39 + "vmv.x.s %[out], v31\n\t" 40 + ".option pop\n\t" 41 + : [out] "=r" (out) 42 + : [in] "r" (child_set_val)); 43 + 44 + if (out != parent_set_val) 45 + return EXIT_FAILURE; 46 + 47 + return EXIT_SUCCESS; 48 + } 49 + 50 + static void do_parent(pid_t child) 51 + { 52 + int status; 53 + void *data = NULL; 54 + 55 + /* Attach to the child */ 56 + while (waitpid(child, &status, 0)) { 57 + if (WIFEXITED(status)) { 58 + ksft_test_result(WEXITSTATUS(status) == 0, "SETREGSET vector\n"); 59 + goto out; 60 + } else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) { 61 + size_t size; 62 + void *data, *v31; 63 + struct __riscv_v_regset_state *v_regset_hdr; 64 + struct user_regs_struct *gpreg; 65 + 66 + size = sizeof(*v_regset_hdr); 67 + data = malloc(size); 68 + if (!data) 69 + goto out; 70 + v_regset_hdr = (struct __riscv_v_regset_state *)data; 71 + 72 + if (do_ptrace(PTRACE_GETREGSET, child, NT_RISCV_VECTOR, size, data)) 73 + goto out; 74 + 75 + ksft_print_msg("vlenb %ld\n", v_regset_hdr->vlenb); 76 + data = realloc(data, size + v_regset_hdr->vlenb * 32); 77 + if (!data) 78 + goto out; 79 + v_regset_hdr = (struct __riscv_v_regset_state *)data; 80 + v31 = (void *)(data + size + v_regset_hdr->vlenb * 31); 81 + size += v_regset_hdr->vlenb * 32; 82 + 83 + if (do_ptrace(PTRACE_GETREGSET, child, NT_RISCV_VECTOR, size, data)) 84 + goto out; 85 + 86 + ksft_test_result(*(int *)v31 == child_set_val, "GETREGSET vector\n"); 87 + 88 + *(int *)v31 = parent_set_val; 89 + if (do_ptrace(PTRACE_SETREGSET, child, NT_RISCV_VECTOR, size, data)) 90 + goto out; 91 + 92 + /* move the pc forward */ 93 + size = sizeof(*gpreg); 94 + data = realloc(data, size); 95 + gpreg = (struct user_regs_struct *)data; 96 + 97 + if (do_ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, size, data)) 98 + goto out; 99 + 100 + gpreg->pc += 4; 101 + if (do_ptrace(PTRACE_SETREGSET, child, NT_PRSTATUS, size, data)) 102 + goto out; 103 + } 104 + 105 + ptrace(PTRACE_CONT, child, NULL, NULL); 106 + } 107 + 108 + out: 109 + free(data); 110 + } 111 + 112 + int main(void) 113 + { 114 + pid_t child; 115 + 116 + ksft_set_plan(2); 117 + if (!is_vector_supported() && !is_xtheadvector_supported()) 118 + ksft_exit_skip("Vector not supported\n"); 119 + 120 + srandom(getpid()); 121 + parent_set_val = rand(); 122 + child_set_val = rand(); 123 + 124 + child = fork(); 125 + if (child < 0) 126 + ksft_exit_fail_msg("Fork failed %d\n", child); 127 + 128 + if (!child) 129 + return do_child(); 130 + 131 + do_parent(child); 132 + 133 + ksft_finished(); 134 + }