kselftest/arm64: Install signal handlers before output in FP stress tests
[platform/kernel/linux-starfive.git] / tools / testing / selftests / arm64 / fp / fpsimd-test.S
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 FPSIMD context switch test
6 // Repeatedly writes unique test patterns into each FPSIMD register
7 // and reads them back to verify integrity.
8 //
9 // for x in `seq 1 NR_CPUS`; do fpsimd-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
17 #define NVR     32
18 #define MAXVL_B (128 / 8)
19
20 .macro _vldr Vn:req, Xt:req
21         ld1     {v\Vn\().2d}, [x\Xt]
22 .endm
23
24 .macro _vstr Vn:req, Xt:req
25         st1     {v\Vn\().2d}, [x\Xt]
26 .endm
27
28 // Generate accessor functions to read/write programmatically selected
29 // FPSIMD registers.
30 // x0 is the register index to access
31 // x1 is the memory address to read from (getv,setp) or store to (setv,setp)
32 // All clobber x0-x2
33 define_accessor setv, NVR, _vldr
34 define_accessor getv, NVR, _vstr
35
36 // Declare some storate space to shadow the SVE register contents:
37 .pushsection .text
38 .data
39 .align 4
40 vref:
41         .space  MAXVL_B * NVR
42 scratch:
43         .space  MAXVL_B
44 .popsection
45
46 // Generate a test pattern for storage in SVE registers
47 // x0: pid      (16 bits)
48 // x1: register number (6 bits)
49 // x2: generation (4 bits)
50 function pattern
51         orr     w1, w0, w1, lsl #16
52         orr     w2, w1, w2, lsl #28
53
54         ldr     x0, =scratch
55         mov     w1, #MAXVL_B / 4
56
57 0:      str     w2, [x0], #4
58         add     w2, w2, #(1 << 22)
59         subs    w1, w1, #1
60         bne     0b
61
62         ret
63 endfunction
64
65 // Get the address of shadow data for FPSIMD V-register V<xn>
66 .macro _adrv xd, xn, nrtmp
67         ldr     \xd, =vref
68         mov     x\nrtmp, #16
69         madd    \xd, x\nrtmp, \xn, \xd
70 .endm
71
72 // Set up test pattern in a FPSIMD V-register
73 // x0: pid
74 // x1: register number
75 // x2: generation
76 function setup_vreg
77         mov     x4, x30
78
79         mov     x6, x1
80         bl      pattern
81         _adrv   x0, x6, 2
82         mov     x5, x0
83         ldr     x1, =scratch
84         bl      memcpy
85
86         mov     x0, x6
87         mov     x1, x5
88         bl      setv
89
90         ret     x4
91 endfunction
92
93 // Trivial memory compare: compare x2 bytes starting at address x0 with
94 // bytes starting at address x1.
95 // Returns only if all bytes match; otherwise, the program is aborted.
96 // Clobbers x0-x5.
97 function memcmp
98         cbz     x2, 1f
99
100         mov     x5, #0
101 0:      ldrb    w3, [x0, x5]
102         ldrb    w4, [x1, x5]
103         add     x5, x5, #1
104         cmp     w3, w4
105         b.ne    barf
106         subs    x2, x2, #1
107         b.ne    0b
108
109 1:      ret
110 endfunction
111
112 // Verify that a FPSIMD V-register matches its shadow in memory, else abort
113 // x0: reg number
114 // Clobbers x0-x5.
115 function check_vreg
116         mov     x3, x30
117
118         _adrv   x5, x0, 6
119         mov     x4, x0
120         ldr     x7, =scratch
121
122         mov     x0, x7
123         mov     x1, x6
124         bl      memfill_ae
125
126         mov     x0, x4
127         mov     x1, x7
128         bl      getv
129
130         mov     x0, x5
131         mov     x1, x7
132         mov     x2, x6
133         mov     x30, x3
134         b       memcmp
135 endfunction
136
137 // Any SVE register modified here can cause corruption in the main
138 // thread -- but *only* the registers modified here.
139 function irritator_handler
140         // Increment the irritation 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         // Corrupt some random V-regs
146         adr     x0, .text + (irritator_handler - .text) / 16 * 16
147         movi    v0.8b, #7
148         movi    v9.16b, #9
149         movi    v31.8b, #31
150
151         ret
152 endfunction
153
154 function tickle_handler
155         // Increment the signal count (x23):
156         ldr     x0, [x2, #ucontext_regs + 8 * 23]
157         add     x0, x0, #1
158         str     x0, [x2, #ucontext_regs + 8 * 23]
159
160         ret
161 endfunction
162
163 function terminate_handler
164         mov     w21, w0
165         mov     x20, x2
166
167         puts    "Terminated by signal "
168         mov     w0, w21
169         bl      putdec
170         puts    ", no error, iterations="
171         ldr     x0, [x20, #ucontext_regs + 8 * 22]
172         bl      putdec
173         puts    ", signals="
174         ldr     x0, [x20, #ucontext_regs + 8 * 23]
175         bl      putdecn
176
177         mov     x0, #0
178         mov     x8, #__NR_exit
179         svc     #0
180 endfunction
181
182 // w0: signal number
183 // x1: sa_action
184 // w2: sa_flags
185 // Clobbers x0-x6,x8
186 function setsignal
187         str     x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
188
189         mov     w4, w0
190         mov     x5, x1
191         mov     w6, w2
192
193         add     x0, sp, #16
194         mov     x1, #sa_sz
195         bl      memclr
196
197         mov     w0, w4
198         add     x1, sp, #16
199         str     w6, [x1, #sa_flags]
200         str     x5, [x1, #sa_handler]
201         mov     x2, #0
202         mov     x3, #sa_mask_sz
203         mov     x8, #__NR_rt_sigaction
204         svc     #0
205
206         cbz     w0, 1f
207
208         puts    "sigaction failure\n"
209         b       .Labort
210
211 1:      ldr     x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
212         ret
213 endfunction
214
215 // Main program entry point
216 .globl _start
217 function _start
218 _start:
219         mov     x23, #0         // signal count
220
221         mov     w0, #SIGINT
222         adr     x1, terminate_handler
223         mov     w2, #SA_SIGINFO
224         bl      setsignal
225
226         mov     w0, #SIGTERM
227         adr     x1, terminate_handler
228         mov     w2, #SA_SIGINFO
229         bl      setsignal
230
231         mov     w0, #SIGUSR1
232         adr     x1, irritator_handler
233         mov     w2, #SA_SIGINFO
234         orr     w2, w2, #SA_NODEFER
235         bl      setsignal
236
237         mov     w0, #SIGUSR2
238         adr     x1, tickle_handler
239         mov     w2, #SA_SIGINFO
240         orr     w2, w2, #SA_NODEFER
241         bl      setsignal
242
243         // Sanity-check and report the vector length
244
245         mov     x19, #128
246         cmp     x19, #128
247         b.lo    1f
248         cmp     x19, #2048
249         b.hi    1f
250         tst     x19, #(8 - 1)
251         b.eq    2f
252
253 1:      puts    "Bad vector length: "
254         mov     x0, x19
255         bl      putdecn
256         b       .Labort
257
258 2:      puts    "Vector length:\t"
259         mov     x0, x19
260         bl      putdec
261         puts    " bits\n"
262
263         // Obtain our PID, to ensure test pattern uniqueness between processes
264
265         mov     x8, #__NR_getpid
266         svc     #0
267         mov     x20, x0
268
269         puts    "PID:\t"
270         mov     x0, x20
271         bl      putdecn
272
273         mov     x22, #0         // generation number, increments per iteration
274 .Ltest_loop:
275
276         mov     x21, #0         // Set up V-regs & shadow with test pattern
277 0:      mov     x0, x20
278         mov     x1, x21
279         and     x2, x22, #0xf
280         bl      setup_vreg
281         add     x21, x21, #1
282         cmp     x21, #NVR
283         b.lo    0b
284
285 // Can't do this when SVE state is volatile across SVC:
286         mov     x8, #__NR_sched_yield   // Encourage preemption
287         svc     #0
288
289         mov     x21, #0
290 0:      mov     x0, x21
291         bl      check_vreg
292         add     x21, x21, #1
293         cmp     x21, #NVR
294         b.lo    0b
295
296         add     x22, x22, #1
297         b       .Ltest_loop
298
299 .Labort:
300         mov     x0, #0
301         mov     x1, #SIGABRT
302         mov     x8, #__NR_kill
303         svc     #0
304 endfunction
305
306 function barf
307         mov     x10, x0 // expected data
308         mov     x11, x1 // actual data
309         mov     x12, x2 // data size
310
311         puts    "Mismatch: PID="
312         mov     x0, x20
313         bl      putdec
314         puts    ", iteration="
315         mov     x0, x22
316         bl      putdec
317         puts    ", reg="
318         mov     x0, x21
319         bl      putdecn
320         puts    "\tExpected ["
321         mov     x0, x10
322         mov     x1, x12
323         bl      dumphex
324         puts    "]\n\tGot      ["
325         mov     x0, x11
326         mov     x1, x12
327         bl      dumphex
328         puts    "]\n"
329
330         mov     x8, #__NR_exit
331         mov     x1, #1
332         svc     #0
333 endfunction