WIP FPC-III support
[linux/fpc-iii.git] / tools / testing / selftests / arm64 / fp / sve-test.S
blobf95074c9b48b730e3055a70f121a8cd3e11783bc
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 Scalable Vector Extension context switch test
6 // Repeatedly writes unique test patterns into each SVE register
7 // and reads them back to verify integrity.
8 //
9 // for x in `seq 1 NR_CPUS`; do sve-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 NZR     32
18 #define NPR     16
19 #define MAXVL_B (2048 / 8)
21 .arch_extension sve
23 .macro _sve_ldr_v zt, xn
24         ldr     z\zt, [x\xn]
25 .endm
27 .macro _sve_str_v zt, xn
28         str     z\zt, [x\xn]
29 .endm
31 .macro _sve_ldr_p pt, xn
32         ldr     p\pt, [x\xn]
33 .endm
35 .macro _sve_str_p pt, xn
36         str     p\pt, [x\xn]
37 .endm
39 // Generate accessor functions to read/write programmatically selected
40 // SVE registers.
41 // x0 is the register index to access
42 // x1 is the memory address to read from (getz,setp) or store to (setz,setp)
43 // All clobber x0-x2
44 define_accessor setz, NZR, _sve_ldr_v
45 define_accessor getz, NZR, _sve_str_v
46 define_accessor setp, NPR, _sve_ldr_p
47 define_accessor getp, NPR, _sve_str_p
49 // Print a single character x0 to stdout
50 // Clobbers x0-x2,x8
51 function putc
52         str     x0, [sp, #-16]!
54         mov     x0, #1                  // STDOUT_FILENO
55         mov     x1, sp
56         mov     x2, #1
57         mov     x8, #__NR_write
58         svc     #0
60         add     sp, sp, #16
61         ret
62 endfunction
64 // Print a NUL-terminated string starting at address x0 to stdout
65 // Clobbers x0-x3,x8
66 function puts
67         mov     x1, x0
69         mov     x2, #0
70 0:      ldrb    w3, [x0], #1
71         cbz     w3, 1f
72         add     x2, x2, #1
73         b       0b
75 1:      mov     w0, #1                  // STDOUT_FILENO
76         mov     x8, #__NR_write
77         svc     #0
79         ret
80 endfunction
82 // Utility macro to print a literal string
83 // Clobbers x0-x4,x8
84 .macro puts string
85         .pushsection .rodata.str1.1, "aMS", 1
86 .L__puts_literal\@: .string "\string"
87         .popsection
89         ldr     x0, =.L__puts_literal\@
90         bl      puts
91 .endm
93 // Print an unsigned decimal number x0 to stdout
94 // Clobbers x0-x4,x8
95 function putdec
96         mov     x1, sp
97         str     x30, [sp, #-32]!        // Result can't be > 20 digits
99         mov     x2, #0
100         strb    w2, [x1, #-1]!          // Write the NUL terminator
102         mov     x2, #10
103 0:      udiv    x3, x0, x2              // div-mod loop to generate the digits
104         msub    x0, x3, x2, x0
105         add     w0, w0, #'0'
106         strb    w0, [x1, #-1]!
107         mov     x0, x3
108         cbnz    x3, 0b
110         ldrb    w0, [x1]
111         cbnz    w0, 1f
112         mov     w0, #'0'                // Print "0" for 0, not ""
113         strb    w0, [x1, #-1]!
115 1:      mov     x0, x1
116         bl      puts
118         ldr     x30, [sp], #32
119         ret
120 endfunction
122 // Print an unsigned decimal number x0 to stdout, followed by a newline
123 // Clobbers x0-x5,x8
124 function putdecn
125         mov     x5, x30
127         bl      putdec
128         mov     x0, #'\n'
129         bl      putc
131         ret     x5
132 endfunction
134 // Clobbers x0-x3,x8
135 function puthexb
136         str     x30, [sp, #-0x10]!
138         mov     w3, w0
139         lsr     w0, w0, #4
140         bl      puthexnibble
141         mov     w0, w3
143         ldr     x30, [sp], #0x10
144         // fall through to puthexnibble
145 endfunction
146 // Clobbers x0-x2,x8
147 function puthexnibble
148         and     w0, w0, #0xf
149         cmp     w0, #10
150         blo     1f
151         add     w0, w0, #'a' - ('9' + 1)
152 1:      add     w0, w0, #'0'
153         b       putc
154 endfunction
156 // x0=data in, x1=size in, clobbers x0-x5,x8
157 function dumphex
158         str     x30, [sp, #-0x10]!
160         mov     x4, x0
161         mov     x5, x1
163 0:      subs    x5, x5, #1
164         b.lo    1f
165         ldrb    w0, [x4], #1
166         bl      puthexb
167         b       0b
169 1:      ldr     x30, [sp], #0x10
170         ret
171 endfunction
173 // Declare some storate space to shadow the SVE register contents:
174 .pushsection .text
175 .data
176 .align 4
177 zref:
178         .space  MAXVL_B * NZR
179 pref:
180         .space  MAXVL_B / 8 * NPR
181 ffrref:
182         .space  MAXVL_B / 8
183 scratch:
184         .space  MAXVL_B
185 .popsection
187 // Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
188 // Clobbers x0-x3
189 function memcpy
190         cmp     x2, #0
191         b.eq    1f
192 0:      ldrb    w3, [x1], #1
193         strb    w3, [x0], #1
194         subs    x2, x2, #1
195         b.ne    0b
196 1:      ret
197 endfunction
199 // Generate a test pattern for storage in SVE registers
200 // x0: pid      (16 bits)
201 // x1: register number (6 bits)
202 // x2: generation (4 bits)
204 // These values are used to constuct a 32-bit pattern that is repeated in the
205 // scratch buffer as many times as will fit:
206 // bits 31:28   generation number (increments once per test_loop)
207 // bits 27:22   32-bit lane index
208 // bits 21:16   register number
209 // bits 15: 0   pid
211 function pattern
212         orr     w1, w0, w1, lsl #16
213         orr     w2, w1, w2, lsl #28
215         ldr     x0, =scratch
216         mov     w1, #MAXVL_B / 4
218 0:      str     w2, [x0], #4
219         add     w2, w2, #(1 << 22)
220         subs    w1, w1, #1
221         bne     0b
223         ret
224 endfunction
226 // Get the address of shadow data for SVE Z-register Z<xn>
227 .macro _adrz xd, xn, nrtmp
228         ldr     \xd, =zref
229         rdvl    x\nrtmp, #1
230         madd    \xd, x\nrtmp, \xn, \xd
231 .endm
233 // Get the address of shadow data for SVE P-register P<xn - NZR>
234 .macro _adrp xd, xn, nrtmp
235         ldr     \xd, =pref
236         rdvl    x\nrtmp, #1
237         lsr     x\nrtmp, x\nrtmp, #3
238         sub     \xn, \xn, #NZR
239         madd    \xd, x\nrtmp, \xn, \xd
240 .endm
242 // Set up test pattern in a SVE Z-register
243 // x0: pid
244 // x1: register number
245 // x2: generation
246 function setup_zreg
247         mov     x4, x30
249         mov     x6, x1
250         bl      pattern
251         _adrz   x0, x6, 2
252         mov     x5, x0
253         ldr     x1, =scratch
254         bl      memcpy
256         mov     x0, x6
257         mov     x1, x5
258         bl      setz
260         ret     x4
261 endfunction
263 // Set up test pattern in a SVE P-register
264 // x0: pid
265 // x1: register number
266 // x2: generation
267 function setup_preg
268         mov     x4, x30
270         mov     x6, x1
271         bl      pattern
272         _adrp   x0, x6, 2
273         mov     x5, x0
274         ldr     x1, =scratch
275         bl      memcpy
277         mov     x0, x6
278         mov     x1, x5
279         bl      setp
281         ret     x4
282 endfunction
284 // Set up test pattern in the FFR
285 // x0: pid
286 // x2: generation
287 // Beware: corrupts P0.
288 function setup_ffr
289         mov     x4, x30
291         bl      pattern
292         ldr     x0, =ffrref
293         ldr     x1, =scratch
294         rdvl    x2, #1
295         lsr     x2, x2, #3
296         bl      memcpy
298         mov     x0, #0
299         ldr     x1, =ffrref
300         bl      setp
302         wrffr   p0.b
304         ret     x4
305 endfunction
307 // Fill x1 bytes starting at x0 with 0xae (for canary purposes)
308 // Clobbers x1, x2.
309 function memfill_ae
310         mov     w2, #0xae
311         b       memfill
312 endfunction
314 // Fill x1 bytes starting at x0 with 0.
315 // Clobbers x1, x2.
316 function memclr
317         mov     w2, #0
318 endfunction
319         // fall through to memfill
321 // Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
322 // Clobbers x1
323 function memfill
324         cmp     x1, #0
325         b.eq    1f
327 0:      strb    w2, [x0], #1
328         subs    x1, x1, #1
329         b.ne    0b
331 1:      ret
332 endfunction
334 // Trivial memory compare: compare x2 bytes starting at address x0 with
335 // bytes starting at address x1.
336 // Returns only if all bytes match; otherwise, the program is aborted.
337 // Clobbers x0-x5.
338 function memcmp
339         cbz     x2, 2f
341         stp     x0, x1, [sp, #-0x20]!
342         str     x2, [sp, #0x10]
344         mov     x5, #0
345 0:      ldrb    w3, [x0, x5]
346         ldrb    w4, [x1, x5]
347         add     x5, x5, #1
348         cmp     w3, w4
349         b.ne    1f
350         subs    x2, x2, #1
351         b.ne    0b
353 1:      ldr     x2, [sp, #0x10]
354         ldp     x0, x1, [sp], #0x20
355         b.ne    barf
357 2:      ret
358 endfunction
360 // Verify that a SVE Z-register matches its shadow in memory, else abort
361 // x0: reg number
362 // Clobbers x0-x7.
363 function check_zreg
364         mov     x3, x30
366         _adrz   x5, x0, 6
367         mov     x4, x0
368         ldr     x7, =scratch
370         mov     x0, x7
371         mov     x1, x6
372         bl      memfill_ae
374         mov     x0, x4
375         mov     x1, x7
376         bl      getz
378         mov     x0, x5
379         mov     x1, x7
380         mov     x2, x6
381         mov     x30, x3
382         b       memcmp
383 endfunction
385 // Verify that a SVE P-register matches its shadow in memory, else abort
386 // x0: reg number
387 // Clobbers x0-x7.
388 function check_preg
389         mov     x3, x30
391         _adrp   x5, x0, 6
392         mov     x4, x0
393         ldr     x7, =scratch
395         mov     x0, x7
396         mov     x1, x6
397         bl      memfill_ae
399         mov     x0, x4
400         mov     x1, x7
401         bl      getp
403         mov     x0, x5
404         mov     x1, x7
405         mov     x2, x6
406         mov     x30, x3
407         b       memcmp
408 endfunction
410 // Verify that the FFR matches its shadow in memory, else abort
411 // Beware -- corrupts P0.
412 // Clobbers x0-x5.
413 function check_ffr
414         mov     x3, x30
416         ldr     x4, =scratch
417         rdvl    x5, #1
418         lsr     x5, x5, #3
420         mov     x0, x4
421         mov     x1, x5
422         bl      memfill_ae
424         rdffr   p0.b
425         mov     x0, #0
426         mov     x1, x4
427         bl      getp
429         ldr     x0, =ffrref
430         mov     x1, x4
431         mov     x2, x5
432         mov     x30, x3
433         b       memcmp
434 endfunction
436 // Any SVE register modified here can cause corruption in the main
437 // thread -- but *only* the registers modified here.
438 function irritator_handler
439         // Increment the irritation signal count (x23):
440         ldr     x0, [x2, #ucontext_regs + 8 * 23]
441         add     x0, x0, #1
442         str     x0, [x2, #ucontext_regs + 8 * 23]
444         // Corrupt some random Z-regs
445         adr     x0, .text + (irritator_handler - .text) / 16 * 16
446         movi    v0.8b, #1
447         movi    v9.16b, #2
448         movi    v31.8b, #3
449         // And P0
450         rdffr   p0.b
451         // And FFR
452         wrffr   p15.b
454         ret
455 endfunction
457 function terminate_handler
458         mov     w21, w0
459         mov     x20, x2
461         puts    "Terminated by signal "
462         mov     w0, w21
463         bl      putdec
464         puts    ", no error, iterations="
465         ldr     x0, [x20, #ucontext_regs + 8 * 22]
466         bl      putdec
467         puts    ", signals="
468         ldr     x0, [x20, #ucontext_regs + 8 * 23]
469         bl      putdecn
471         mov     x0, #0
472         mov     x8, #__NR_exit
473         svc     #0
474 endfunction
476 // w0: signal number
477 // x1: sa_action
478 // w2: sa_flags
479 // Clobbers x0-x6,x8
480 function setsignal
481         str     x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
483         mov     w4, w0
484         mov     x5, x1
485         mov     w6, w2
487         add     x0, sp, #16
488         mov     x1, #sa_sz
489         bl      memclr
491         mov     w0, w4
492         add     x1, sp, #16
493         str     w6, [x1, #sa_flags]
494         str     x5, [x1, #sa_handler]
495         mov     x2, #0
496         mov     x3, #sa_mask_sz
497         mov     x8, #__NR_rt_sigaction
498         svc     #0
500         cbz     w0, 1f
502         puts    "sigaction failure\n"
503         b       .Labort
505 1:      ldr     x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
506         ret
507 endfunction
509 // Main program entry point
510 .globl _start
511 function _start
512 _start:
513         // Sanity-check and report the vector length
515         rdvl    x19, #8
516         cmp     x19, #128
517         b.lo    1f
518         cmp     x19, #2048
519         b.hi    1f
520         tst     x19, #(8 - 1)
521         b.eq    2f
523 1:      puts    "Bad vector length: "
524         mov     x0, x19
525         bl      putdecn
526         b       .Labort
528 2:      puts    "Vector length:\t"
529         mov     x0, x19
530         bl      putdec
531         puts    " bits\n"
533         // Obtain our PID, to ensure test pattern uniqueness between processes
535         mov     x8, #__NR_getpid
536         svc     #0
537         mov     x20, x0
539         puts    "PID:\t"
540         mov     x0, x20
541         bl      putdecn
543         mov     x23, #0         // Irritation signal count
545         mov     w0, #SIGINT
546         adr     x1, terminate_handler
547         mov     w2, #SA_SIGINFO
548         bl      setsignal
550         mov     w0, #SIGTERM
551         adr     x1, terminate_handler
552         mov     w2, #SA_SIGINFO
553         bl      setsignal
555         mov     w0, #SIGUSR1
556         adr     x1, irritator_handler
557         mov     w2, #SA_SIGINFO
558         orr     w2, w2, #SA_NODEFER
559         bl      setsignal
561         mov     x22, #0         // generation number, increments per iteration
562 .Ltest_loop:
563         rdvl    x0, #8
564         cmp     x0, x19
565         b.ne    vl_barf
567         mov     x21, #0         // Set up Z-regs & shadow with test pattern
568 0:      mov     x0, x20
569         mov     x1, x21
570         and     x2, x22, #0xf
571         bl      setup_zreg
572         add     x21, x21, #1
573         cmp     x21, #NZR
574         b.lo    0b
576         mov     x0, x20         // Set up FFR & shadow with test pattern
577         mov     x1, #NZR + NPR
578         and     x2, x22, #0xf
579         bl      setup_ffr
581 0:      mov     x0, x20         // Set up P-regs & shadow with test pattern
582         mov     x1, x21
583         and     x2, x22, #0xf
584         bl      setup_preg
585         add     x21, x21, #1
586         cmp     x21, #NZR + NPR
587         b.lo    0b
589 // Can't do this when SVE state is volatile across SVC:
590 //      mov     x8, #__NR_sched_yield   // Encourage preemption
591 //      svc     #0
593         mov     x21, #0
594 0:      mov     x0, x21
595         bl      check_zreg
596         add     x21, x21, #1
597         cmp     x21, #NZR
598         b.lo    0b
600 0:      mov     x0, x21
601         bl      check_preg
602         add     x21, x21, #1
603         cmp     x21, #NZR + NPR
604         b.lo    0b
606         bl      check_ffr
608         add     x22, x22, #1
609         b       .Ltest_loop
611 .Labort:
612         mov     x0, #0
613         mov     x1, #SIGABRT
614         mov     x8, #__NR_kill
615         svc     #0
616 endfunction
618 function barf
619 // fpsimd.c acitivty log dump hack
620 //      ldr     w0, =0xdeadc0de
621 //      mov     w8, #__NR_exit
622 //      svc     #0
623 // end hack
624         mov     x10, x0 // expected data
625         mov     x11, x1 // actual data
626         mov     x12, x2 // data size
628         puts    "Mistatch: PID="
629         mov     x0, x20
630         bl      putdec
631         puts    ", iteration="
632         mov     x0, x22
633         bl      putdec
634         puts    ", reg="
635         mov     x0, x21
636         bl      putdecn
637         puts    "\tExpected ["
638         mov     x0, x10
639         mov     x1, x12
640         bl      dumphex
641         puts    "]\n\tGot      ["
642         mov     x0, x11
643         mov     x1, x12
644         bl      dumphex
645         puts    "]\n"
647         mov     x8, #__NR_getpid
648         svc     #0
649 // fpsimd.c acitivty log dump hack
650 //      ldr     w0, =0xdeadc0de
651 //      mov     w8, #__NR_exit
652 //      svc     #0
653 // ^ end of hack
654         mov     x1, #SIGABRT
655         mov     x8, #__NR_kill
656         svc     #0
657 //      mov     x8, #__NR_exit
658 //      mov     x1, #1
659 //      svc     #0
660 endfunction
662 function vl_barf
663         mov     x10, x0
665         puts    "Bad active VL: "
666         mov     x0, x10
667         bl      putdecn
669         mov     x8, #__NR_exit
670         mov     x1, #1
671         svc     #0
672 endfunction