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// Any SVE register modified here can cause corruption in the main
138// thread -- but *only* the registers modified here.
139function 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
152endfunction
153
154function 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
161endfunction
162
163function 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
180endfunction
181
182// w0: signal number
183// x1: sa_action
184// w2: sa_flags
185// Clobbers x0-x6,x8
186function 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
2111: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
212 ret
213endfunction
214
215// Main program entry point
216.globl _start
217function _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
2531: puts "Bad vector length: "
254 mov x0, x19
255 bl putdecn
256 b .Labort
257
2582: 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
2770: 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
2900: 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
304endfunction
305
306function 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
333endfunction