1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (C) 2015-2019 ARM Limited.
3 // Original author: Dave Martin <Dave.Martin@arm.com>
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.
9 // for x in `seq 1 NR_CPUS`; do sve-test & pids=$pids\ $! ; done
10 // (leave it running for as long as you want...)
13 #include <asm/unistd.h>
14 #include "assembler.h"
15 #include "asm-offsets.h"
20 #define MAXVL_B (2048 / 8)
24 .macro _sve_ldr_v zt, xn
28 .macro _sve_str_v zt, xn
32 .macro _sve_ldr_p pt, xn
36 .macro _sve_str_p pt, xn
40 // Generate accessor functions to read/write programmatically selected
42 // x0 is the register index to access
43 // x1 is the memory address to read from (getz,setp) or store to (setz,setp)
45 define_accessor setz, NZR, _sve_ldr_v
46 define_accessor getz, NZR, _sve_str_v
47 define_accessor setp, NPR, _sve_ldr_p
48 define_accessor getp, NPR, _sve_str_p
50 // Declare some storate space to shadow the SVE register contents:
57 .space MAXVL_B / 8 * NPR
64 // Generate a test pattern for storage in SVE registers
66 // x1: register number (6 bits)
67 // x2: generation (4 bits)
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
77 orr w1, w0, w1, lsl #16
78 orr w2, w1, w2, lsl #28
84 add w2, w2, #(1 << 22)
91 // Get the address of shadow data for SVE Z-register Z<xn>
92 .macro _adrz xd, xn, nrtmp
95 madd \xd, x\nrtmp, \xn, \xd
98 // Get the address of shadow data for SVE P-register P<xn - NZR>
99 .macro _adrp xd, xn, nrtmp
102 lsr x\nrtmp, x\nrtmp, #3
104 madd \xd, x\nrtmp, \xn, \xd
107 // Set up test pattern in a SVE Z-register
109 // x1: register number
128 // Set up test pattern in a SVE P-register
130 // x1: register number
149 // Set up test pattern in the FFR
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.
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.
195 stp x0, x1, [sp, #-0x20]!
207 1: ldr x2, [sp, #0x10]
208 ldp x0, x1, [sp], #0x20
214 // Verify that a SVE Z-register matches its shadow in memory, else abort
239 // Verify that a SVE P-register matches its shadow in memory, else abort
264 // Verify that the FFR matches its shadow in memory, else abort
265 // Beware -- corrupts P0.
294 // Modify live register state, the signal return will undo our changes
295 function irritator_handler
296 // Increment the irritation signal count (x23):
297 ldr x0, [x2, #ucontext_regs + 8 * 23]
299 str x0, [x2, #ucontext_regs + 8 * 23]
301 // Corrupt some random Z-regs
315 function tickle_handler
316 // Increment the signal count (x23):
317 ldr x0, [x2, #ucontext_regs + 8 * 23]
319 str x0, [x2, #ucontext_regs + 8 * 23]
324 function terminate_handler
328 puts "Terminated by signal "
331 puts ", no error, iterations="
332 ldr x0, [x20, #ucontext_regs + 8 * 22]
335 ldr x0, [x20, #ucontext_regs + 8 * 23]
348 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
360 str w6, [x1, #sa_flags]
361 str x5, [x1, #sa_handler]
364 mov x8, #__NR_rt_sigaction
369 puts "sigaction failure\n"
372 1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
376 // Main program entry point
381 mov x23, #0 // Irritation signal count
384 adr x1, terminate_handler
389 adr x1, terminate_handler
394 adr x1, irritator_handler
396 orr w2, w2, #SA_NODEFER
400 adr x1, tickle_handler
402 orr w2, w2, #SA_NODEFER
406 puts "Streaming mode "
410 // Sanity-check and report the vector length
420 1: puts "Bad vector length: "
425 2: puts "Vector length:\t"
430 // Obtain our PID, to ensure test pattern uniqueness between processes
441 smstart_sm // syscalls will have exited streaming mode
444 mov x22, #0 // generation number, increments per iteration
450 mov x21, #0 // Set up Z-regs & shadow with test pattern
459 mov x0, x20 // Set up FFR & shadow with test pattern
464 0: mov x0, x20 // Set up P-regs & shadow with test pattern
472 // Can't do this when SVE state is volatile across SVC:
473 // mov x8, #__NR_sched_yield // Encourage preemption
477 mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=0,SM=1
509 // fpsimd.c acitivty log dump hack
510 // ldr w0, =0xdeadc0de
511 // mov w8, #__NR_exit
514 mov x10, x0 // expected data
515 mov x11, x1 // actual data
516 mov x12, x2 // data size
519 mrs x13, S3_3_C4_C2_2
522 puts "Mismatch: PID="
549 // fpsimd.c acitivty log dump hack
550 // ldr w0, =0xdeadc0de
551 // mov w8, #__NR_exit
557 // mov x8, #__NR_exit
565 puts "Bad active VL: "