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 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
33define_accessor setv, NVR, _vldr
34define_accessor getv, NVR, _vstr
35
36// Declare some storate space to shadow the SVE register contents:
37.pushsection .text
38.data
39.align 4
40vref:
41 .space MAXVL_B * NVR
42scratch:
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)
50function 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
570: str w2, [x0], #4
58 add w2, w2, #(1 << 22)
59 subs w1, w1, #1
60 bne 0b
61
62 ret
63endfunction
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
76function 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
91endfunction
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.
97function memcmp
98 cbz x2, 1f
99
100 mov x5, #0
1010: 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
1091: ret
110endfunction
111
112// Verify that a FPSIMD V-register matches its shadow in memory, else abort
113// x0: reg number
114// Clobbers x0-x5.
115function 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
135endfunction
136
137// Modify live register state, the signal return will undo our changes
138function irritator_handler
139 // Increment the irritation signal count (x23):
140 ldr x0, [x2, #ucontext_regs + 8 * 23]
141 add x0, x0, #1
142 str x0, [x2, #ucontext_regs + 8 * 23]
143
144 // Corrupt some random V-regs
145 movi v0.8b, #7
146 movi v9.16b, #9
147 movi v31.8b, #31
148
149 ret
150endfunction
151
152function tickle_handler
153 // Increment the signal count (x23):
154 ldr x0, [x2, #ucontext_regs + 8 * 23]
155 add x0, x0, #1
156 str x0, [x2, #ucontext_regs + 8 * 23]
157
158 ret
159endfunction
160
161function terminate_handler
162 mov w21, w0
163 mov x20, x2
164
165 puts "Terminated by signal "
166 mov w0, w21
167 bl putdec
168 puts ", no error, iterations="
169 ldr x0, [x20, #ucontext_regs + 8 * 22]
170 bl putdec
171 puts ", signals="
172 ldr x0, [x20, #ucontext_regs + 8 * 23]
173 bl putdecn
174
175 mov x0, #0
176 mov x8, #__NR_exit
177 svc #0
178endfunction
179
180// w0: signal number
181// x1: sa_action
182// w2: sa_flags
183// Clobbers x0-x6,x8
184function setsignal
185 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
186
187 mov w4, w0
188 mov x5, x1
189 mov w6, w2
190
191 add x0, sp, #16
192 mov x1, #sa_sz
193 bl memclr
194
195 mov w0, w4
196 add x1, sp, #16
197 str w6, [x1, #sa_flags]
198 str x5, [x1, #sa_handler]
199 mov x2, #0
200 mov x3, #sa_mask_sz
201 mov x8, #__NR_rt_sigaction
202 svc #0
203
204 cbz w0, 1f
205
206 puts "sigaction failure\n"
207 b .Labort
208
2091: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
210 ret
211endfunction
212
213// Main program entry point
214.globl _start
215function _start
216 enable_gcs
217
218 mov x23, #0 // signal count
219
220 mov w0, #SIGINT
221 adr x1, terminate_handler
222 mov w2, #SA_SIGINFO
223 bl setsignal
224
225 mov w0, #SIGTERM
226 adr x1, terminate_handler
227 mov w2, #SA_SIGINFO
228 bl setsignal
229
230 mov w0, #SIGUSR1
231 adr x1, irritator_handler
232 mov w2, #SA_SIGINFO
233 orr w2, w2, #SA_NODEFER
234 bl setsignal
235
236 mov w0, #SIGUSR2
237 adr x1, tickle_handler
238 mov w2, #SA_SIGINFO
239 orr w2, w2, #SA_NODEFER
240 bl setsignal
241
242 // Sanity-check and report the vector length
243
244 mov x19, #128
245 cmp x19, #128
246 b.lo 1f
247 cmp x19, #2048
248 b.hi 1f
249 tst x19, #(8 - 1)
250 b.eq 2f
251
2521: puts "Bad vector length: "
253 mov x0, x19
254 bl putdecn
255 b .Labort
256
2572: puts "Vector length:\t"
258 mov x0, x19
259 bl putdec
260 puts " bits\n"
261
262 // Obtain our PID, to ensure test pattern uniqueness between processes
263
264 mov x8, #__NR_getpid
265 svc #0
266 mov x20, x0
267
268 puts "PID:\t"
269 mov x0, x20
270 bl putdecn
271
272 mov x22, #0 // generation number, increments per iteration
273.Ltest_loop:
274
275 mov x21, #0 // Set up V-regs & shadow with test pattern
2760: mov x0, x20
277 mov x1, x21
278 and x2, x22, #0xf
279 bl setup_vreg
280 add x21, x21, #1
281 cmp x21, #NVR
282 b.lo 0b
283
284// Can't do this when SVE state is volatile across SVC:
285 mov x8, #__NR_sched_yield // Encourage preemption
286 svc #0
287
288 mov x21, #0
2890: mov x0, x21
290 bl check_vreg
291 add x21, x21, #1
292 cmp x21, #NVR
293 b.lo 0b
294
295 add x22, x22, #1
296 b .Ltest_loop
297
298.Labort:
299 mov x0, #0
300 mov x1, #SIGABRT
301 mov x8, #__NR_kill
302 svc #0
303endfunction
304
305function barf
306 mov x10, x0 // expected data
307 mov x11, x1 // actual data
308 mov x12, x2 // data size
309
310 puts "Mismatch: PID="
311 mov x0, x20
312 bl putdec
313 puts ", iteration="
314 mov x0, x22
315 bl putdec
316 puts ", reg="
317 mov x0, x21
318 bl putdecn
319 puts "\tExpected ["
320 mov x0, x10
321 mov x1, x12
322 bl dumphex
323 puts "]\n\tGot ["
324 mov x0, x11
325 mov x1, x12
326 bl dumphex
327 puts "]\n"
328
329 mov x8, #__NR_exit
330 mov x1, #1
331 svc #0
332endfunction