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

kselftest/arm64: Add a stress test program for ZT0

Following the pattern for the other register sets add a stress test program
for ZT0 which continually loads and verifies patterns in the register in
an effort to discover context switching problems.

Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20221208-arm64-sme2-v4-14-f2fa0aef982f@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Brown and committed by
Catalin Marinas
1c07425e 7d5d8601

+341
+1
tools/testing/selftests/arm64/fp/.gitignore
··· 12 12 za-fork 13 13 za-ptrace 14 14 za-test 15 + zt-test
+3
tools/testing/selftests/arm64/fp/Makefile
··· 14 14 sve-test \ 15 15 ssve-test \ 16 16 za-test \ 17 + zt-test \ 17 18 vlset 18 19 TEST_PROGS_EXTENDED := fpsimd-stress sve-stress ssve-stress za-stress 19 20 ··· 41 40 -static -ffreestanding -Wall $^ -o $@ 42 41 $(OUTPUT)/za-ptrace: za-ptrace.c 43 42 $(OUTPUT)/za-test: za-test.S $(OUTPUT)/asm-utils.o 43 + $(CC) -nostdlib $^ -o $@ 44 + $(OUTPUT)/zt-test: zt-test.S $(OUTPUT)/asm-utils.o 44 45 $(CC) -nostdlib $^ -o $@ 45 46 46 47 include ../../lib.mk
+20
tools/testing/selftests/arm64/fp/sme-inst.h
··· 48 48 | ((\offset) & 7) 49 49 .endm 50 50 51 + /* 52 + * LDR (ZT0) 53 + * 54 + * LDR ZT0, nx 55 + */ 56 + .macro _ldr_zt nx 57 + .inst 0xe11f8000 \ 58 + | (((\nx) & 0x1f) << 5) 59 + .endm 60 + 61 + /* 62 + * STR (ZT0) 63 + * 64 + * STR ZT0, nx 65 + */ 66 + .macro _str_zt nx 67 + .inst 0xe13f8000 \ 68 + | (((\nx) & 0x1f) << 5) 69 + .endm 70 + 51 71 #endif
+317
tools/testing/selftests/arm64/fp/zt-test.S
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (C) 2021-2 ARM Limited. 3 + // Original author: Mark Brown <broonie@kernel.org> 4 + // 5 + // Scalable Matrix Extension ZT context switch test 6 + // Repeatedly writes unique test patterns into ZT0 7 + // and reads them back to verify integrity. 8 + 9 + #include <asm/unistd.h> 10 + #include "assembler.h" 11 + #include "asm-offsets.h" 12 + #include "sme-inst.h" 13 + 14 + .arch_extension sve 15 + 16 + #define ZT_SZ 512 17 + #define ZT_B (ZT_SZ / 8) 18 + 19 + // Declare some storage space to shadow ZT register contents and a 20 + // scratch buffer. 21 + .pushsection .text 22 + .data 23 + .align 4 24 + ztref: 25 + .space ZT_B 26 + scratch: 27 + .space ZT_B 28 + .popsection 29 + 30 + 31 + // Generate a test pattern for storage in ZT 32 + // x0: pid 33 + // x1: generation 34 + 35 + // These values are used to construct a 32-bit pattern that is repeated in the 36 + // scratch buffer as many times as will fit: 37 + // bits 31:24 generation number (increments once per test_loop) 38 + // bits 23: 8 pid 39 + // bits 7: 0 32-bit lane index 40 + 41 + function pattern 42 + mov w3, wzr 43 + bfi w3, w0, #8, #16 // PID 44 + bfi w3, w1, #24, #8 // Generation 45 + 46 + ldr x0, =scratch 47 + mov w1, #ZT_B / 4 48 + 49 + 0: str w3, [x0], #4 50 + add w3, w3, #1 // Lane 51 + subs w1, w1, #1 52 + b.ne 0b 53 + 54 + ret 55 + endfunction 56 + 57 + // Set up test pattern in a ZT horizontal vector 58 + // x0: pid 59 + // x1: generation 60 + function setup_zt 61 + mov x4, x30 62 + 63 + bl pattern // Get pattern in scratch buffer 64 + ldr x0, =ztref 65 + ldr x1, =scratch 66 + mov x2, #ZT_B 67 + bl memcpy 68 + 69 + ldr x0, =ztref 70 + _ldr_zt 0 // load zt0 from pointer x0 71 + 72 + ret x4 73 + endfunction 74 + 75 + // Trivial memory compare: compare x2 bytes starting at address x0 with 76 + // bytes starting at address x1. 77 + // Returns only if all bytes match; otherwise, the program is aborted. 78 + // Clobbers x0-x5. 79 + function memcmp 80 + cbz x2, 2f 81 + 82 + stp x0, x1, [sp, #-0x20]! 83 + str x2, [sp, #0x10] 84 + 85 + mov x5, #0 86 + 0: ldrb w3, [x0, x5] 87 + ldrb w4, [x1, x5] 88 + add x5, x5, #1 89 + cmp w3, w4 90 + b.ne 1f 91 + subs x2, x2, #1 92 + b.ne 0b 93 + 94 + 1: ldr x2, [sp, #0x10] 95 + ldp x0, x1, [sp], #0x20 96 + b.ne barf 97 + 98 + 2: ret 99 + endfunction 100 + 101 + // Verify that a ZT vector matches its shadow in memory, else abort 102 + // Clobbers x0-x3 103 + function check_zt 104 + mov x3, x30 105 + 106 + ldr x0, =scratch // Poison scratch 107 + mov x1, #ZT_B 108 + bl memfill_ae 109 + 110 + ldr x0, =scratch 111 + _str_zt 0 112 + 113 + ldr x0, =ztref 114 + ldr x1, =scratch 115 + mov x2, #ZT_B 116 + mov x30, x3 117 + b memcmp 118 + endfunction 119 + 120 + // Any SME register modified here can cause corruption in the main 121 + // thread -- but *only* the locations modified here. 122 + function irritator_handler 123 + // Increment the irritation signal count (x23): 124 + ldr x0, [x2, #ucontext_regs + 8 * 23] 125 + add x0, x0, #1 126 + str x0, [x2, #ucontext_regs + 8 * 23] 127 + 128 + // Corrupt some random ZT data 129 + #if 0 130 + adr x0, .text + (irritator_handler - .text) / 16 * 16 131 + movi v0.8b, #1 132 + movi v9.16b, #2 133 + movi v31.8b, #3 134 + #endif 135 + 136 + ret 137 + endfunction 138 + 139 + function tickle_handler 140 + // Increment the signal count (x23): 141 + ldr x0, [x2, #ucontext_regs + 8 * 23] 142 + add x0, x0, #1 143 + str x0, [x2, #ucontext_regs + 8 * 23] 144 + 145 + ret 146 + endfunction 147 + 148 + function terminate_handler 149 + mov w21, w0 150 + mov x20, x2 151 + 152 + puts "Terminated by signal " 153 + mov w0, w21 154 + bl putdec 155 + puts ", no error, iterations=" 156 + ldr x0, [x20, #ucontext_regs + 8 * 22] 157 + bl putdec 158 + puts ", signals=" 159 + ldr x0, [x20, #ucontext_regs + 8 * 23] 160 + bl putdecn 161 + 162 + mov x0, #0 163 + mov x8, #__NR_exit 164 + svc #0 165 + endfunction 166 + 167 + // w0: signal number 168 + // x1: sa_action 169 + // w2: sa_flags 170 + // Clobbers x0-x6,x8 171 + function setsignal 172 + str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]! 173 + 174 + mov w4, w0 175 + mov x5, x1 176 + mov w6, w2 177 + 178 + add x0, sp, #16 179 + mov x1, #sa_sz 180 + bl memclr 181 + 182 + mov w0, w4 183 + add x1, sp, #16 184 + str w6, [x1, #sa_flags] 185 + str x5, [x1, #sa_handler] 186 + mov x2, #0 187 + mov x3, #sa_mask_sz 188 + mov x8, #__NR_rt_sigaction 189 + svc #0 190 + 191 + cbz w0, 1f 192 + 193 + puts "sigaction failure\n" 194 + b .Labort 195 + 196 + 1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16) 197 + ret 198 + endfunction 199 + 200 + // Main program entry point 201 + .globl _start 202 + function _start 203 + _start: 204 + mov x23, #0 // signal count 205 + 206 + mov w0, #SIGINT 207 + adr x1, terminate_handler 208 + mov w2, #SA_SIGINFO 209 + bl setsignal 210 + 211 + mov w0, #SIGTERM 212 + adr x1, terminate_handler 213 + mov w2, #SA_SIGINFO 214 + bl setsignal 215 + 216 + mov w0, #SIGUSR1 217 + adr x1, irritator_handler 218 + mov w2, #SA_SIGINFO 219 + orr w2, w2, #SA_NODEFER 220 + bl setsignal 221 + 222 + mov w0, #SIGUSR2 223 + adr x1, tickle_handler 224 + mov w2, #SA_SIGINFO 225 + orr w2, w2, #SA_NODEFER 226 + bl setsignal 227 + 228 + smstart_za 229 + 230 + // Obtain our PID, to ensure test pattern uniqueness between processes 231 + mov x8, #__NR_getpid 232 + svc #0 233 + mov x20, x0 234 + 235 + puts "PID:\t" 236 + mov x0, x20 237 + bl putdecn 238 + 239 + mov x22, #0 // generation number, increments per iteration 240 + .Ltest_loop: 241 + mov x0, x20 242 + mov x1, x22 243 + bl setup_zt 244 + 245 + mov x8, #__NR_sched_yield // Encourage preemption 246 + svc #0 247 + 248 + mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=1,SM=0 249 + and x1, x0, #3 250 + cmp x1, #2 251 + b.ne svcr_barf 252 + 253 + bl check_zt 254 + 255 + add x22, x22, #1 // Everything still working 256 + b .Ltest_loop 257 + 258 + .Labort: 259 + mov x0, #0 260 + mov x1, #SIGABRT 261 + mov x8, #__NR_kill 262 + svc #0 263 + endfunction 264 + 265 + function barf 266 + // fpsimd.c acitivty log dump hack 267 + // ldr w0, =0xdeadc0de 268 + // mov w8, #__NR_exit 269 + // svc #0 270 + // end hack 271 + smstop 272 + mov x10, x0 // expected data 273 + mov x11, x1 // actual data 274 + mov x12, x2 // data size 275 + 276 + puts "Mismatch: PID=" 277 + mov x0, x20 278 + bl putdec 279 + puts ", iteration=" 280 + mov x0, x22 281 + bl putdec 282 + puts "\tExpected [" 283 + mov x0, x10 284 + mov x1, x12 285 + bl dumphex 286 + puts "]\n\tGot [" 287 + mov x0, x11 288 + mov x1, x12 289 + bl dumphex 290 + puts "]\n" 291 + 292 + mov x8, #__NR_getpid 293 + svc #0 294 + // fpsimd.c acitivty log dump hack 295 + // ldr w0, =0xdeadc0de 296 + // mov w8, #__NR_exit 297 + // svc #0 298 + // ^ end of hack 299 + mov x1, #SIGABRT 300 + mov x8, #__NR_kill 301 + svc #0 302 + // mov x8, #__NR_exit 303 + // mov x1, #1 304 + // svc #0 305 + endfunction 306 + 307 + function svcr_barf 308 + mov x10, x0 309 + 310 + puts "Bad SVCR: " 311 + mov x0, x10 312 + bl putdecn 313 + 314 + mov x8, #__NR_exit 315 + mov x1, #1 316 + svc #0 317 + endfunction