Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (C) 2015-2019 ARM Limited.
3// Original author: Dave Martin <Dave.Martin@arm.com>
4//
5// Simple Scalable Vector Extension context switch test
6// Repeatedly writes unique test patterns into each SVE register
7// and reads them back to verify integrity.
8//
9// for x in `seq 1 NR_CPUS`; do sve-test & pids=$pids\ $! ; done
10// (leave it running for as long as you want...)
11// kill $pids
12
13#include <asm/unistd.h>
14#include "assembler.h"
15#include "asm-offsets.h"
16#include "sme-inst.h"
17
18#define NZR 32
19#define NPR 16
20#define MAXVL_B (2048 / 8)
21
22.arch_extension sve
23
24.macro _sve_ldr_v zt, xn
25 ldr z\zt, [x\xn]
26.endm
27
28.macro _sve_str_v zt, xn
29 str z\zt, [x\xn]
30.endm
31
32.macro _sve_ldr_p pt, xn
33 ldr p\pt, [x\xn]
34.endm
35
36.macro _sve_str_p pt, xn
37 str p\pt, [x\xn]
38.endm
39
40// Generate accessor functions to read/write programmatically selected
41// SVE registers.
42// x0 is the register index to access
43// x1 is the memory address to read from (getz,setp) or store to (setz,setp)
44// All clobber x0-x2
45define_accessor setz, NZR, _sve_ldr_v
46define_accessor getz, NZR, _sve_str_v
47define_accessor setp, NPR, _sve_ldr_p
48define_accessor getp, NPR, _sve_str_p
49
50// Declare some storate space to shadow the SVE register contents:
51.pushsection .text
52.data
53.align 4
54zref:
55 .space MAXVL_B * NZR
56pref:
57 .space MAXVL_B / 8 * NPR
58ffrref:
59 .space MAXVL_B / 8
60scratch:
61 .space MAXVL_B
62.popsection
63
64// Generate a test pattern for storage in SVE registers
65// x0: pid (16 bits)
66// x1: register number (6 bits)
67// x2: generation (4 bits)
68
69// These values are used to constuct a 32-bit pattern that is repeated in the
70// scratch buffer as many times as will fit:
71// bits 31:28 generation number (increments once per test_loop)
72// bits 27:22 32-bit lane index
73// bits 21:16 register number
74// bits 15: 0 pid
75
76function pattern
77 orr w1, w0, w1, lsl #16
78 orr w2, w1, w2, lsl #28
79
80 ldr x0, =scratch
81 mov w1, #MAXVL_B / 4
82
830: str w2, [x0], #4
84 add w2, w2, #(1 << 22)
85 subs w1, w1, #1
86 bne 0b
87
88 ret
89endfunction
90
91// Get the address of shadow data for SVE Z-register Z<xn>
92.macro _adrz xd, xn, nrtmp
93 ldr \xd, =zref
94 rdvl x\nrtmp, #1
95 madd \xd, x\nrtmp, \xn, \xd
96.endm
97
98// Get the address of shadow data for SVE P-register P<xn - NZR>
99.macro _adrp xd, xn, nrtmp
100 ldr \xd, =pref
101 rdvl x\nrtmp, #1
102 lsr x\nrtmp, x\nrtmp, #3
103 sub \xn, \xn, #NZR
104 madd \xd, x\nrtmp, \xn, \xd
105.endm
106
107// Set up test pattern in a SVE Z-register
108// x0: pid
109// x1: register number
110// x2: generation
111function setup_zreg
112 mov x4, x30
113
114 mov x6, x1
115 bl pattern
116 _adrz x0, x6, 2
117 mov x5, x0
118 ldr x1, =scratch
119 bl memcpy
120
121 mov x0, x6
122 mov x1, x5
123 bl setz
124
125 ret x4
126endfunction
127
128// Set up test pattern in a SVE P-register
129// x0: pid
130// x1: register number
131// x2: generation
132function setup_preg
133 mov x4, x30
134
135 mov x6, x1
136 bl pattern
137 _adrp x0, x6, 2
138 mov x5, x0
139 ldr x1, =scratch
140 bl memcpy
141
142 mov x0, x6
143 mov x1, x5
144 bl setp
145
146 ret x4
147endfunction
148
149// Set up test pattern in the FFR
150// x0: pid
151// x2: generation
152//
153// We need to generate a canonical FFR value, which consists of a number of
154// low "1" bits, followed by a number of zeros. This gives us 17 unique values
155// per 16 bits of FFR, so we create a 4 bit signature out of the PID and
156// generation, and use that as the initial number of ones in the pattern.
157// We fill the upper lanes of FFR with zeros.
158// Beware: corrupts P0.
159function setup_ffr
160#ifndef SSVE
161 mov x4, x30
162
163 and w0, w0, #0x3
164 bfi w0, w2, #2, #2
165 mov w1, #1
166 lsl w1, w1, w0
167 sub w1, w1, #1
168
169 ldr x0, =ffrref
170 strh w1, [x0], 2
171 rdvl x1, #1
172 lsr x1, x1, #3
173 sub x1, x1, #2
174 bl memclr
175
176 mov x0, #0
177 ldr x1, =ffrref
178 bl setp
179
180 wrffr p0.b
181
182 ret x4
183#else
184 ret
185#endif
186endfunction
187
188// Trivial memory compare: compare x2 bytes starting at address x0 with
189// bytes starting at address x1.
190// Returns only if all bytes match; otherwise, the program is aborted.
191// Clobbers x0-x5.
192function memcmp
193 cbz x2, 2f
194
195 stp x0, x1, [sp, #-0x20]!
196 str x2, [sp, #0x10]
197
198 mov x5, #0
1990: ldrb w3, [x0, x5]
200 ldrb w4, [x1, x5]
201 add x5, x5, #1
202 cmp w3, w4
203 b.ne 1f
204 subs x2, x2, #1
205 b.ne 0b
206
2071: ldr x2, [sp, #0x10]
208 ldp x0, x1, [sp], #0x20
209 b.ne barf
210
2112: ret
212endfunction
213
214// Verify that a SVE Z-register matches its shadow in memory, else abort
215// x0: reg number
216// Clobbers x0-x7.
217function check_zreg
218 mov x3, x30
219
220 _adrz x5, x0, 6
221 mov x4, x0
222 ldr x7, =scratch
223
224 mov x0, x7
225 mov x1, x6
226 bl memfill_ae
227
228 mov x0, x4
229 mov x1, x7
230 bl getz
231
232 mov x0, x5
233 mov x1, x7
234 mov x2, x6
235 mov x30, x3
236 b memcmp
237endfunction
238
239// Verify that a SVE P-register matches its shadow in memory, else abort
240// x0: reg number
241// Clobbers x0-x7.
242function check_preg
243 mov x3, x30
244
245 _adrp x5, x0, 6
246 mov x4, x0
247 ldr x7, =scratch
248
249 mov x0, x7
250 mov x1, x6
251 bl memfill_ae
252
253 mov x0, x4
254 mov x1, x7
255 bl getp
256
257 mov x0, x5
258 mov x1, x7
259 mov x2, x6
260 mov x30, x3
261 b memcmp
262endfunction
263
264// Verify that the FFR matches its shadow in memory, else abort
265// Beware -- corrupts P0.
266// Clobbers x0-x5.
267function check_ffr
268#ifndef SSVE
269 mov x3, x30
270
271 ldr x4, =scratch
272 rdvl x5, #1
273 lsr x5, x5, #3
274
275 mov x0, x4
276 mov x1, x5
277 bl memfill_ae
278
279 rdffr p0.b
280 mov x0, #0
281 mov x1, x4
282 bl getp
283
284 ldr x0, =ffrref
285 mov x1, x4
286 mov x2, x5
287 mov x30, x3
288 b memcmp
289#else
290 ret
291#endif
292endfunction
293
294// Modify live register state, the signal return will undo our changes
295function irritator_handler
296 // Increment the irritation signal count (x23):
297 ldr x0, [x2, #ucontext_regs + 8 * 23]
298 add x0, x0, #1
299 str x0, [x2, #ucontext_regs + 8 * 23]
300
301 // Corrupt some random Z-regs
302 movi v0.8b, #1
303 movi v9.16b, #2
304 movi v31.8b, #3
305 // And P0
306 ptrue p0.d
307#ifndef SSVE
308 // And FFR
309 wrffr p15.b
310#endif
311
312 ret
313endfunction
314
315function tickle_handler
316 // Increment the signal count (x23):
317 ldr x0, [x2, #ucontext_regs + 8 * 23]
318 add x0, x0, #1
319 str x0, [x2, #ucontext_regs + 8 * 23]
320
321 ret
322endfunction
323
324function terminate_handler
325 mov w21, w0
326 mov x20, x2
327
328 puts "Terminated by signal "
329 mov w0, w21
330 bl putdec
331 puts ", no error, iterations="
332 ldr x0, [x20, #ucontext_regs + 8 * 22]
333 bl putdec
334 puts ", signals="
335 ldr x0, [x20, #ucontext_regs + 8 * 23]
336 bl putdecn
337
338 mov x0, #0
339 mov x8, #__NR_exit
340 svc #0
341endfunction
342
343// w0: signal number
344// x1: sa_action
345// w2: sa_flags
346// Clobbers x0-x6,x8
347function setsignal
348 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
349
350 mov w4, w0
351 mov x5, x1
352 mov w6, w2
353
354 add x0, sp, #16
355 mov x1, #sa_sz
356 bl memclr
357
358 mov w0, w4
359 add x1, sp, #16
360 str w6, [x1, #sa_flags]
361 str x5, [x1, #sa_handler]
362 mov x2, #0
363 mov x3, #sa_mask_sz
364 mov x8, #__NR_rt_sigaction
365 svc #0
366
367 cbz w0, 1f
368
369 puts "sigaction failure\n"
370 b .Labort
371
3721: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
373 ret
374endfunction
375
376// Main program entry point
377.globl _start
378function _start
379 enable_gcs
380
381 mov x23, #0 // Irritation signal count
382
383 mov w0, #SIGINT
384 adr x1, terminate_handler
385 mov w2, #SA_SIGINFO
386 bl setsignal
387
388 mov w0, #SIGTERM
389 adr x1, terminate_handler
390 mov w2, #SA_SIGINFO
391 bl setsignal
392
393 mov w0, #SIGUSR1
394 adr x1, irritator_handler
395 mov w2, #SA_SIGINFO
396 orr w2, w2, #SA_NODEFER
397 bl setsignal
398
399 mov w0, #SIGUSR2
400 adr x1, tickle_handler
401 mov w2, #SA_SIGINFO
402 orr w2, w2, #SA_NODEFER
403 bl setsignal
404
405#ifdef SSVE
406 puts "Streaming mode "
407 smstart_sm
408#endif
409
410 // Sanity-check and report the vector length
411
412 rdvl x19, #8
413 cmp x19, #128
414 b.lo 1f
415 cmp x19, #2048
416 b.hi 1f
417 tst x19, #(8 - 1)
418 b.eq 2f
419
4201: puts "Bad vector length: "
421 mov x0, x19
422 bl putdecn
423 b .Labort
424
4252: puts "Vector length:\t"
426 mov x0, x19
427 bl putdec
428 puts " bits\n"
429
430 // Obtain our PID, to ensure test pattern uniqueness between processes
431
432 mov x8, #__NR_getpid
433 svc #0
434 mov x20, x0
435
436 puts "PID:\t"
437 mov x0, x20
438 bl putdecn
439
440#ifdef SSVE
441 smstart_sm // syscalls will have exited streaming mode
442#endif
443
444 mov x22, #0 // generation number, increments per iteration
445.Ltest_loop:
446 rdvl x0, #8
447 cmp x0, x19
448 b.ne vl_barf
449
450 mov x21, #0 // Set up Z-regs & shadow with test pattern
4510: mov x0, x20
452 mov x1, x21
453 and x2, x22, #0xf
454 bl setup_zreg
455 add x21, x21, #1
456 cmp x21, #NZR
457 b.lo 0b
458
459 mov x0, x20 // Set up FFR & shadow with test pattern
460 mov x1, #NZR + NPR
461 and x2, x22, #0xf
462 bl setup_ffr
463
4640: mov x0, x20 // Set up P-regs & shadow with test pattern
465 mov x1, x21
466 and x2, x22, #0xf
467 bl setup_preg
468 add x21, x21, #1
469 cmp x21, #NZR + NPR
470 b.lo 0b
471
472// Can't do this when SVE state is volatile across SVC:
473// mov x8, #__NR_sched_yield // Encourage preemption
474// svc #0
475
476#ifdef SSVE
477 mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=0,SM=1
478 and x1, x0, #3
479 cmp x1, #1
480 b.ne svcr_barf
481#endif
482
483 mov x21, #0
4840: mov x0, x21
485 bl check_zreg
486 add x21, x21, #1
487 cmp x21, #NZR
488 b.lo 0b
489
4900: mov x0, x21
491 bl check_preg
492 add x21, x21, #1
493 cmp x21, #NZR + NPR
494 b.lo 0b
495
496 bl check_ffr
497
498 add x22, x22, #1
499 b .Ltest_loop
500
501.Labort:
502 mov x0, #0
503 mov x1, #SIGABRT
504 mov x8, #__NR_kill
505 svc #0
506endfunction
507
508function barf
509// fpsimd.c acitivty log dump hack
510// ldr w0, =0xdeadc0de
511// mov w8, #__NR_exit
512// svc #0
513// end hack
514 mov x10, x0 // expected data
515 mov x11, x1 // actual data
516 mov x12, x2 // data size
517
518#ifdef SSVE
519 mrs x13, S3_3_C4_C2_2
520#endif
521
522 puts "Mismatch: PID="
523 mov x0, x20
524 bl putdec
525 puts ", iteration="
526 mov x0, x22
527 bl putdec
528 puts ", reg="
529 mov x0, x21
530 bl putdecn
531 puts "\tExpected ["
532 mov x0, x10
533 mov x1, x12
534 bl dumphex
535 puts "]\n\tGot ["
536 mov x0, x11
537 mov x1, x12
538 bl dumphex
539 puts "]\n"
540
541#ifdef SSVE
542 puts "\tSVCR: "
543 mov x0, x13
544 bl putdecn
545#endif
546
547 mov x8, #__NR_getpid
548 svc #0
549// fpsimd.c acitivty log dump hack
550// ldr w0, =0xdeadc0de
551// mov w8, #__NR_exit
552// svc #0
553// ^ end of hack
554 mov x1, #SIGABRT
555 mov x8, #__NR_kill
556 svc #0
557// mov x8, #__NR_exit
558// mov x1, #1
559// svc #0
560endfunction
561
562function vl_barf
563 mov x10, x0
564
565 puts "Bad active VL: "
566 mov x0, x10
567 bl putdecn
568
569 mov x8, #__NR_exit
570 mov x1, #1
571 svc #0
572endfunction
573
574function svcr_barf
575 mov x10, x0
576
577 puts "Bad SVCR: "
578 mov x0, x10
579 bl putdecn
580
581 mov x8, #__NR_exit
582 mov x1, #1
583 svc #0
584endfunction