Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/arm64/fp/fpsimd-test.S
26289 views
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
// Modify live register state, the signal return will undo our changes
138
function 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
150
endfunction
151
152
function 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
159
endfunction
160
161
function 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
178
endfunction
179
180
// w0: signal number
181
// x1: sa_action
182
// w2: sa_flags
183
// Clobbers x0-x6,x8
184
function 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
209
1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
210
ret
211
endfunction
212
213
// Main program entry point
214
.globl _start
215
function _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
252
1: puts "Bad vector length: "
253
mov x0, x19
254
bl putdecn
255
b .Labort
256
257
2: 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
276
0: 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
289
0: 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
303
endfunction
304
305
function 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
332
endfunction
333
334