drm/atomic-helper: document drm_atomic_helper_check() restrictions
[drm/drm-misc.git] / tools / testing / selftests / arm64 / fp / fpsimd-test.S
blobf89d67894c2e47bce849d06674eba6bdfb002b79
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
13 #include <asm/unistd.h>
14 #include "assembler.h"
15 #include "asm-offsets.h"
17 #define NVR     32
18 #define MAXVL_B (128 / 8)
20 .macro _vldr Vn:req, Xt:req
21         ld1     {v\Vn\().2d}, [x\Xt]
22 .endm
24 .macro _vstr Vn:req, Xt:req
25         st1     {v\Vn\().2d}, [x\Xt]
26 .endm
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
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
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
54         ldr     x0, =scratch
55         mov     w1, #MAXVL_B / 4
57 0:      str     w2, [x0], #4
58         add     w2, w2, #(1 << 22)
59         subs    w1, w1, #1
60         bne     0b
62         ret
63 endfunction
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
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
79         mov     x6, x1
80         bl      pattern
81         _adrv   x0, x6, 2
82         mov     x5, x0
83         ldr     x1, =scratch
84         bl      memcpy
86         mov     x0, x6
87         mov     x1, x5
88         bl      setv
90         ret     x4
91 endfunction
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
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
109 1:      ret
110 endfunction
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
118         _adrv   x5, x0, 6
119         mov     x4, x0
120         ldr     x7, =scratch
122         mov     x0, x7
123         mov     x1, x6
124         bl      memfill_ae
126         mov     x0, x4
127         mov     x1, x7
128         bl      getv
130         mov     x0, x5
131         mov     x1, x7
132         mov     x2, x6
133         mov     x30, x3
134         b       memcmp
135 endfunction
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]
144         // Corrupt some random V-regs
145         movi    v0.8b, #7
146         movi    v9.16b, #9
147         movi    v31.8b, #31
149         ret
150 endfunction
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]
158         ret
159 endfunction
161 function terminate_handler
162         mov     w21, w0
163         mov     x20, x2
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
175         mov     x0, #0
176         mov     x8, #__NR_exit
177         svc     #0
178 endfunction
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)]!
187         mov     w4, w0
188         mov     x5, x1
189         mov     w6, w2
191         add     x0, sp, #16
192         mov     x1, #sa_sz
193         bl      memclr
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
204         cbz     w0, 1f
206         puts    "sigaction failure\n"
207         b       .Labort
209 1:      ldr     x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
210         ret
211 endfunction
213 // Main program entry point
214 .globl _start
215 function _start
216         enable_gcs
218         mov     x23, #0         // signal count
220         mov     w0, #SIGINT
221         adr     x1, terminate_handler
222         mov     w2, #SA_SIGINFO
223         bl      setsignal
225         mov     w0, #SIGTERM
226         adr     x1, terminate_handler
227         mov     w2, #SA_SIGINFO
228         bl      setsignal
230         mov     w0, #SIGUSR1
231         adr     x1, irritator_handler
232         mov     w2, #SA_SIGINFO
233         orr     w2, w2, #SA_NODEFER
234         bl      setsignal
236         mov     w0, #SIGUSR2
237         adr     x1, tickle_handler
238         mov     w2, #SA_SIGINFO
239         orr     w2, w2, #SA_NODEFER
240         bl      setsignal
242         // Sanity-check and report the vector length
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
252 1:      puts    "Bad vector length: "
253         mov     x0, x19
254         bl      putdecn
255         b       .Labort
257 2:      puts    "Vector length:\t"
258         mov     x0, x19
259         bl      putdec
260         puts    " bits\n"
262         // Obtain our PID, to ensure test pattern uniqueness between processes
264         mov     x8, #__NR_getpid
265         svc     #0
266         mov     x20, x0
268         puts    "PID:\t"
269         mov     x0, x20
270         bl      putdecn
272         mov     x22, #0         // generation number, increments per iteration
273 .Ltest_loop:
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
284 // Can't do this when SVE state is volatile across SVC:
285         mov     x8, #__NR_sched_yield   // Encourage preemption
286         svc     #0
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
295         add     x22, x22, #1
296         b       .Ltest_loop
298 .Labort:
299         mov     x0, #0
300         mov     x1, #SIGABRT
301         mov     x8, #__NR_kill
302         svc     #0
303 endfunction
305 function barf
306         mov     x10, x0 // expected data
307         mov     x11, x1 // actual data
308         mov     x12, x2 // data size
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"
329         mov     x8, #__NR_exit
330         mov     x1, #1
331         svc     #0
332 endfunction