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 33define_accessor setv, NVR, _vldr 34define_accessor getv, NVR, _vstr 35 36// Declare some storate space to shadow the SVE register contents: 37.pushsection .text 38.data 39.align 4 40vref: 41 .space MAXVL_B * NVR 42scratch: 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) 50function 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 570: str w2, [x0], #4 58 add w2, w2, #(1 << 22) 59 subs w1, w1, #1 60 bne 0b 61 62 ret 63endfunction 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 76function 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 91endfunction 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. 97function memcmp 98 cbz x2, 1f 99 100 mov x5, #0 1010: 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 1091: ret 110endfunction 111 112// Verify that a FPSIMD V-register matches its shadow in memory, else abort 113// x0: reg number 114// Clobbers x0-x5. 115function 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 135endfunction 136 137// Any SVE register modified here can cause corruption in the main 138// thread -- but *only* the registers modified here. 139function irritator_handler 140 // Increment the irritation signal count (x23): 141 ldr x0, [x2, #ucontext_regs + 8 * 23] 142 add x0, x0, #1 143 str x0, [x2, #ucontext_regs + 8 * 23] 144 145 // Corrupt some random V-regs 146 adr x0, .text + (irritator_handler - .text) / 16 * 16 147 movi v0.8b, #7 148 movi v9.16b, #9 149 movi v31.8b, #31 150 151 ret 152endfunction 153 154function tickle_handler 155 // Increment the signal count (x23): 156 ldr x0, [x2, #ucontext_regs + 8 * 23] 157 add x0, x0, #1 158 str x0, [x2, #ucontext_regs + 8 * 23] 159 160 ret 161endfunction 162 163function terminate_handler 164 mov w21, w0 165 mov x20, x2 166 167 puts "Terminated by signal " 168 mov w0, w21 169 bl putdec 170 puts ", no error, iterations=" 171 ldr x0, [x20, #ucontext_regs + 8 * 22] 172 bl putdec 173 puts ", signals=" 174 ldr x0, [x20, #ucontext_regs + 8 * 23] 175 bl putdecn 176 177 mov x0, #0 178 mov x8, #__NR_exit 179 svc #0 180endfunction 181 182// w0: signal number 183// x1: sa_action 184// w2: sa_flags 185// Clobbers x0-x6,x8 186function setsignal 187 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]! 188 189 mov w4, w0 190 mov x5, x1 191 mov w6, w2 192 193 add x0, sp, #16 194 mov x1, #sa_sz 195 bl memclr 196 197 mov w0, w4 198 add x1, sp, #16 199 str w6, [x1, #sa_flags] 200 str x5, [x1, #sa_handler] 201 mov x2, #0 202 mov x3, #sa_mask_sz 203 mov x8, #__NR_rt_sigaction 204 svc #0 205 206 cbz w0, 1f 207 208 puts "sigaction failure\n" 209 b .Labort 210 2111: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16) 212 ret 213endfunction 214 215// Main program entry point 216.globl _start 217function _start 218_start: 219 mov x23, #0 // signal count 220 221 mov w0, #SIGINT 222 adr x1, terminate_handler 223 mov w2, #SA_SIGINFO 224 bl setsignal 225 226 mov w0, #SIGTERM 227 adr x1, terminate_handler 228 mov w2, #SA_SIGINFO 229 bl setsignal 230 231 mov w0, #SIGUSR1 232 adr x1, irritator_handler 233 mov w2, #SA_SIGINFO 234 orr w2, w2, #SA_NODEFER 235 bl setsignal 236 237 mov w0, #SIGUSR2 238 adr x1, tickle_handler 239 mov w2, #SA_SIGINFO 240 orr w2, w2, #SA_NODEFER 241 bl setsignal 242 243 // Sanity-check and report the vector length 244 245 mov x19, #128 246 cmp x19, #128 247 b.lo 1f 248 cmp x19, #2048 249 b.hi 1f 250 tst x19, #(8 - 1) 251 b.eq 2f 252 2531: puts "Bad vector length: " 254 mov x0, x19 255 bl putdecn 256 b .Labort 257 2582: puts "Vector length:\t" 259 mov x0, x19 260 bl putdec 261 puts " bits\n" 262 263 // Obtain our PID, to ensure test pattern uniqueness between processes 264 265 mov x8, #__NR_getpid 266 svc #0 267 mov x20, x0 268 269 puts "PID:\t" 270 mov x0, x20 271 bl putdecn 272 273 mov x22, #0 // generation number, increments per iteration 274.Ltest_loop: 275 276 mov x21, #0 // Set up V-regs & shadow with test pattern 2770: mov x0, x20 278 mov x1, x21 279 and x2, x22, #0xf 280 bl setup_vreg 281 add x21, x21, #1 282 cmp x21, #NVR 283 b.lo 0b 284 285// Can't do this when SVE state is volatile across SVC: 286 mov x8, #__NR_sched_yield // Encourage preemption 287 svc #0 288 289 mov x21, #0 2900: mov x0, x21 291 bl check_vreg 292 add x21, x21, #1 293 cmp x21, #NVR 294 b.lo 0b 295 296 add x22, x22, #1 297 b .Ltest_loop 298 299.Labort: 300 mov x0, #0 301 mov x1, #SIGABRT 302 mov x8, #__NR_kill 303 svc #0 304endfunction 305 306function barf 307 mov x10, x0 // expected data 308 mov x11, x1 // actual data 309 mov x12, x2 // data size 310 311 puts "Mismatch: PID=" 312 mov x0, x20 313 bl putdec 314 puts ", iteration=" 315 mov x0, x22 316 bl putdec 317 puts ", reg=" 318 mov x0, x21 319 bl putdecn 320 puts "\tExpected [" 321 mov x0, x10 322 mov x1, x12 323 bl dumphex 324 puts "]\n\tGot [" 325 mov x0, x11 326 mov x1, x12 327 bl dumphex 328 puts "]\n" 329 330 mov x8, #__NR_exit 331 mov x1, #1 332 svc #0 333endfunction 334