ALSA: hda/realtek: modify EAPD in the ALC886
[linux-2.6-microblaze.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 // Print a single character x0 to stdout
37 // Clobbers x0-x2,x8
38 function putc
39         str     x0, [sp, #-16]!
40
41         mov     x0, #1                  // STDOUT_FILENO
42         mov     x1, sp
43         mov     x2, #1
44         mov     x8, #__NR_write
45         svc     #0
46
47         add     sp, sp, #16
48         ret
49 endfunction
50
51 // Print a NUL-terminated string starting at address x0 to stdout
52 // Clobbers x0-x3,x8
53 function puts
54         mov     x1, x0
55
56         mov     x2, #0
57 0:      ldrb    w3, [x0], #1
58         cbz     w3, 1f
59         add     x2, x2, #1
60         b       0b
61
62 1:      mov     w0, #1                  // STDOUT_FILENO
63         mov     x8, #__NR_write
64         svc     #0
65
66         ret
67 endfunction
68
69 // Utility macro to print a literal string
70 // Clobbers x0-x4,x8
71 .macro puts string
72         .pushsection .rodata.str1.1, "aMS", 1
73 .L__puts_literal\@: .string "\string"
74         .popsection
75
76         ldr     x0, =.L__puts_literal\@
77         bl      puts
78 .endm
79
80 // Print an unsigned decimal number x0 to stdout
81 // Clobbers x0-x4,x8
82 function putdec
83         mov     x1, sp
84         str     x30, [sp, #-32]!        // Result can't be > 20 digits
85
86         mov     x2, #0
87         strb    w2, [x1, #-1]!          // Write the NUL terminator
88
89         mov     x2, #10
90 0:      udiv    x3, x0, x2              // div-mod loop to generate the digits
91         msub    x0, x3, x2, x0
92         add     w0, w0, #'0'
93         strb    w0, [x1, #-1]!
94         mov     x0, x3
95         cbnz    x3, 0b
96
97         ldrb    w0, [x1]
98         cbnz    w0, 1f
99         mov     w0, #'0'                // Print "0" for 0, not ""
100         strb    w0, [x1, #-1]!
101
102 1:      mov     x0, x1
103         bl      puts
104
105         ldr     x30, [sp], #32
106         ret
107 endfunction
108
109 // Print an unsigned decimal number x0 to stdout, followed by a newline
110 // Clobbers x0-x5,x8
111 function putdecn
112         mov     x5, x30
113
114         bl      putdec
115         mov     x0, #'\n'
116         bl      putc
117
118         ret     x5
119 endfunction
120
121
122 // Clobbers x0-x3,x8
123 function puthexb
124         str     x30, [sp, #-0x10]!
125
126         mov     w3, w0
127         lsr     w0, w0, #4
128         bl      puthexnibble
129         mov     w0, w3
130
131         ldr     x30, [sp], #0x10
132         // fall through to puthexnibble
133 endfunction
134 // Clobbers x0-x2,x8
135 function puthexnibble
136         and     w0, w0, #0xf
137         cmp     w0, #10
138         blo     1f
139         add     w0, w0, #'a' - ('9' + 1)
140 1:      add     w0, w0, #'0'
141         b       putc
142 endfunction
143
144 // x0=data in, x1=size in, clobbers x0-x5,x8
145 function dumphex
146         str     x30, [sp, #-0x10]!
147
148         mov     x4, x0
149         mov     x5, x1
150
151 0:      subs    x5, x5, #1
152         b.lo    1f
153         ldrb    w0, [x4], #1
154         bl      puthexb
155         b       0b
156
157 1:      ldr     x30, [sp], #0x10
158         ret
159 endfunction
160
161 // Declare some storate space to shadow the SVE register contents:
162 .pushsection .text
163 .data
164 .align 4
165 vref:
166         .space  MAXVL_B * NVR
167 scratch:
168         .space  MAXVL_B
169 .popsection
170
171 // Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
172 // Clobbers x0-x3
173 function memcpy
174         cmp     x2, #0
175         b.eq    1f
176 0:      ldrb    w3, [x1], #1
177         strb    w3, [x0], #1
178         subs    x2, x2, #1
179         b.ne    0b
180 1:      ret
181 endfunction
182
183 // Generate a test pattern for storage in SVE registers
184 // x0: pid      (16 bits)
185 // x1: register number (6 bits)
186 // x2: generation (4 bits)
187 function pattern
188         orr     w1, w0, w1, lsl #16
189         orr     w2, w1, w2, lsl #28
190
191         ldr     x0, =scratch
192         mov     w1, #MAXVL_B / 4
193
194 0:      str     w2, [x0], #4
195         add     w2, w2, #(1 << 22)
196         subs    w1, w1, #1
197         bne     0b
198
199         ret
200 endfunction
201
202 // Get the address of shadow data for FPSIMD V-register V<xn>
203 .macro _adrv xd, xn, nrtmp
204         ldr     \xd, =vref
205         mov     x\nrtmp, #16
206         madd    \xd, x\nrtmp, \xn, \xd
207 .endm
208
209 // Set up test pattern in a FPSIMD V-register
210 // x0: pid
211 // x1: register number
212 // x2: generation
213 function setup_vreg
214         mov     x4, x30
215
216         mov     x6, x1
217         bl      pattern
218         _adrv   x0, x6, 2
219         mov     x5, x0
220         ldr     x1, =scratch
221         bl      memcpy
222
223         mov     x0, x6
224         mov     x1, x5
225         bl      setv
226
227         ret     x4
228 endfunction
229
230 // Fill x1 bytes starting at x0 with 0xae (for canary purposes)
231 // Clobbers x1, x2.
232 function memfill_ae
233         mov     w2, #0xae
234         b       memfill
235 endfunction
236
237 // Fill x1 bytes starting at x0 with 0.
238 // Clobbers x1, x2.
239 function memclr
240         mov     w2, #0
241 endfunction
242         // fall through to memfill
243
244 // Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
245 // Clobbers x1
246 function memfill
247         cmp     x1, #0
248         b.eq    1f
249
250 0:      strb    w2, [x0], #1
251         subs    x1, x1, #1
252         b.ne    0b
253
254 1:      ret
255 endfunction
256
257 // Trivial memory compare: compare x2 bytes starting at address x0 with
258 // bytes starting at address x1.
259 // Returns only if all bytes match; otherwise, the program is aborted.
260 // Clobbers x0-x5.
261 function memcmp
262         cbz     x2, 1f
263
264         mov     x5, #0
265 0:      ldrb    w3, [x0, x5]
266         ldrb    w4, [x1, x5]
267         add     x5, x5, #1
268         cmp     w3, w4
269         b.ne    barf
270         subs    x2, x2, #1
271         b.ne    0b
272
273 1:      ret
274 endfunction
275
276 // Verify that a FPSIMD V-register matches its shadow in memory, else abort
277 // x0: reg number
278 // Clobbers x0-x5.
279 function check_vreg
280         mov     x3, x30
281
282         _adrv   x5, x0, 6
283         mov     x4, x0
284         ldr     x7, =scratch
285
286         mov     x0, x7
287         mov     x1, x6
288         bl      memfill_ae
289
290         mov     x0, x4
291         mov     x1, x7
292         bl      getv
293
294         mov     x0, x5
295         mov     x1, x7
296         mov     x2, x6
297         mov     x30, x3
298         b       memcmp
299 endfunction
300
301 // Any SVE register modified here can cause corruption in the main
302 // thread -- but *only* the registers modified here.
303 function irritator_handler
304         // Increment the irritation signal count (x23):
305         ldr     x0, [x2, #ucontext_regs + 8 * 23]
306         add     x0, x0, #1
307         str     x0, [x2, #ucontext_regs + 8 * 23]
308
309         // Corrupt some random V-regs
310         adr     x0, .text + (irritator_handler - .text) / 16 * 16
311         movi    v0.8b, #7
312         movi    v9.16b, #9
313         movi    v31.8b, #31
314
315         ret
316 endfunction
317
318 function terminate_handler
319         mov     w21, w0
320         mov     x20, x2
321
322         puts    "Terminated by signal "
323         mov     w0, w21
324         bl      putdec
325         puts    ", no error, iterations="
326         ldr     x0, [x20, #ucontext_regs + 8 * 22]
327         bl      putdec
328         puts    ", signals="
329         ldr     x0, [x20, #ucontext_regs + 8 * 23]
330         bl      putdecn
331
332         mov     x0, #0
333         mov     x8, #__NR_exit
334         svc     #0
335 endfunction
336
337 // w0: signal number
338 // x1: sa_action
339 // w2: sa_flags
340 // Clobbers x0-x6,x8
341 function setsignal
342         str     x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
343
344         mov     w4, w0
345         mov     x5, x1
346         mov     w6, w2
347
348         add     x0, sp, #16
349         mov     x1, #sa_sz
350         bl      memclr
351
352         mov     w0, w4
353         add     x1, sp, #16
354         str     w6, [x1, #sa_flags]
355         str     x5, [x1, #sa_handler]
356         mov     x2, #0
357         mov     x3, #sa_mask_sz
358         mov     x8, #__NR_rt_sigaction
359         svc     #0
360
361         cbz     w0, 1f
362
363         puts    "sigaction failure\n"
364         b       .Labort
365
366 1:      ldr     x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
367         ret
368 endfunction
369
370 // Main program entry point
371 .globl _start
372 function _start
373 _start:
374         // Sanity-check and report the vector length
375
376         mov     x19, #128
377         cmp     x19, #128
378         b.lo    1f
379         cmp     x19, #2048
380         b.hi    1f
381         tst     x19, #(8 - 1)
382         b.eq    2f
383
384 1:      puts    "Bad vector length: "
385         mov     x0, x19
386         bl      putdecn
387         b       .Labort
388
389 2:      puts    "Vector length:\t"
390         mov     x0, x19
391         bl      putdec
392         puts    " bits\n"
393
394         // Obtain our PID, to ensure test pattern uniqueness between processes
395
396         mov     x8, #__NR_getpid
397         svc     #0
398         mov     x20, x0
399
400         puts    "PID:\t"
401         mov     x0, x20
402         bl      putdecn
403
404         mov     x23, #0         // Irritation signal count
405
406         mov     w0, #SIGINT
407         adr     x1, terminate_handler
408         mov     w2, #SA_SIGINFO
409         bl      setsignal
410
411         mov     w0, #SIGTERM
412         adr     x1, terminate_handler
413         mov     w2, #SA_SIGINFO
414         bl      setsignal
415
416         mov     w0, #SIGUSR1
417         adr     x1, irritator_handler
418         mov     w2, #SA_SIGINFO
419         orr     w2, w2, #SA_NODEFER
420         bl      setsignal
421
422         mov     x22, #0         // generation number, increments per iteration
423 .Ltest_loop:
424
425         mov     x21, #0         // Set up V-regs & shadow with test pattern
426 0:      mov     x0, x20
427         mov     x1, x21
428         and     x2, x22, #0xf
429         bl      setup_vreg
430         add     x21, x21, #1
431         cmp     x21, #NVR
432         b.lo    0b
433
434 // Can't do this when SVE state is volatile across SVC:
435         mov     x8, #__NR_sched_yield   // Encourage preemption
436         svc     #0
437
438         mov     x21, #0
439 0:      mov     x0, x21
440         bl      check_vreg
441         add     x21, x21, #1
442         cmp     x21, #NVR
443         b.lo    0b
444
445         add     x22, x22, #1
446         b       .Ltest_loop
447
448 .Labort:
449         mov     x0, #0
450         mov     x1, #SIGABRT
451         mov     x8, #__NR_kill
452         svc     #0
453 endfunction
454
455 function barf
456         mov     x10, x0 // expected data
457         mov     x11, x1 // actual data
458         mov     x12, x2 // data size
459
460         puts    "Mistatch: PID="
461         mov     x0, x20
462         bl      putdec
463         puts    ", iteration="
464         mov     x0, x22
465         bl      putdec
466         puts    ", reg="
467         mov     x0, x21
468         bl      putdecn
469         puts    "\tExpected ["
470         mov     x0, x10
471         mov     x1, x12
472         bl      dumphex
473         puts    "]\n\tGot      ["
474         mov     x0, x11
475         mov     x1, x12
476         bl      dumphex
477         puts    "]\n"
478
479         mov     x8, #__NR_exit
480         mov     x1, #1
481         svc     #0
482 endfunction