1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (C) 2015-2019 ARM Limited.
3 // Original author: Dave Martin <Dave.Martin@arm.com>
5 // Simple FPSIMD context switch test
6 // Repeatedly writes unique test patterns into each FPSIMD register
7 // and reads them back to verify integrity.
9 // for x in `seq 1 NR_CPUS`; do fpsimd-test & pids=$pids\ $! ; done
10 // (leave it running for as long as you want...)
13 #include <asm/unistd.h>
14 #include "assembler.h"
15 #include "asm-offsets.h"
18 #define MAXVL_B (128 / 8)
20 .macro _vldr Vn:req, Xt:req
21 ld1 {v\Vn\().2d}, [x\Xt]
24 .macro _vstr Vn:req, Xt:req
25 st1 {v\Vn\().2d}, [x\Xt]
28 // Generate accessor functions to read/write programmatically selected
30 // x0 is the register index to access
31 // x1 is the memory address to read from (getv,setp) or store to (setv,setp)
33 define_accessor setv, NVR, _vldr
34 define_accessor getv, NVR, _vstr
36 // Print a single character x0 to stdout
41 mov x0, #1 // STDOUT_FILENO
51 // Print a NUL-terminated string starting at address x0 to stdout
62 1: mov w0, #1 // STDOUT_FILENO
69 // Utility macro to print a literal string
72 .pushsection .rodata.str1.1, "aMS", 1
73 .L__puts_literal\@: .string "\string"
76 ldr x0, =.L__puts_literal\@
80 // Print an unsigned decimal number x0 to stdout
84 str x30, [sp, #-32]! // Result can't be > 20 digits
87 strb w2, [x1, #-1]! // Write the NUL terminator
90 0: udiv x3, x0, x2 // div-mod loop to generate the digits
99 mov w0, #'0' // Print "0" for 0, not ""
109 // Print an unsigned decimal number x0 to stdout, followed by a newline
124 str x30, [sp, #-0x10]!
132 // fall through to puthexnibble
135 function puthexnibble
139 add w0, w0, #'a' - ('9' + 1)
144 // x0=data in, x1=size in, clobbers x0-x5,x8
146 str x30, [sp, #-0x10]!
157 1: ldr x30, [sp], #0x10
161 // Declare some storate space to shadow the SVE register contents:
171 // Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
183 // Generate a test pattern for storage in SVE registers
185 // x1: register number (6 bits)
186 // x2: generation (4 bits)
188 orr w1, w0, w1, lsl #16
189 orr w2, w1, w2, lsl #28
195 add w2, w2, #(1 << 22)
202 // Get the address of shadow data for FPSIMD V-register V<xn>
203 .macro _adrv xd, xn, nrtmp
206 madd \xd, x\nrtmp, \xn, \xd
209 // Set up test pattern in a FPSIMD V-register
211 // x1: register number
230 // Fill x1 bytes starting at x0 with 0xae (for canary purposes)
237 // Fill x1 bytes starting at x0 with 0.
242 // fall through to memfill
244 // Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
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.
276 // Verify that a FPSIMD V-register matches its shadow in memory, else abort
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]
307 str x0, [x2, #ucontext_regs + 8 * 23]
309 // Corrupt some random V-regs
310 adr x0, .text + (irritator_handler - .text) / 16 * 16
318 function terminate_handler
322 puts "Terminated by signal "
325 puts ", no error, iterations="
326 ldr x0, [x20, #ucontext_regs + 8 * 22]
329 ldr x0, [x20, #ucontext_regs + 8 * 23]
342 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
354 str w6, [x1, #sa_flags]
355 str x5, [x1, #sa_handler]
358 mov x8, #__NR_rt_sigaction
363 puts "sigaction failure\n"
366 1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
370 // Main program entry point
374 // Sanity-check and report the vector length
384 1: puts "Bad vector length: "
389 2: puts "Vector length:\t"
394 // Obtain our PID, to ensure test pattern uniqueness between processes
404 mov x23, #0 // Irritation signal count
407 adr x1, terminate_handler
412 adr x1, terminate_handler
417 adr x1, irritator_handler
419 orr w2, w2, #SA_NODEFER
422 mov x22, #0 // generation number, increments per iteration
425 mov x21, #0 // Set up V-regs & shadow with test pattern
434 // Can't do this when SVE state is volatile across SVC:
435 mov x8, #__NR_sched_yield // Encourage preemption
456 mov x10, x0 // expected data
457 mov x11, x1 // actual data
458 mov x12, x2 // data size
460 puts "Mistatch: PID="