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// Modify live register state, the signal return will undo our changes 138function 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] 143 144 // Corrupt some random V-regs 145 movi v0.8b, #7 146 movi v9.16b, #9 147 movi v31.8b, #31 148 149 ret 150endfunction 151 152function 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] 157 158 ret 159endfunction 160 161function terminate_handler 162 mov w21, w0 163 mov x20, x2 164 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 174 175 mov x0, #0 176 mov x8, #__NR_exit 177 svc #0 178endfunction 179 180// w0: signal number 181// x1: sa_action 182// w2: sa_flags 183// Clobbers x0-x6,x8 184function setsignal 185 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]! 186 187 mov w4, w0 188 mov x5, x1 189 mov w6, w2 190 191 add x0, sp, #16 192 mov x1, #sa_sz 193 bl memclr 194 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 203 204 cbz w0, 1f 205 206 puts "sigaction failure\n" 207 b .Labort 208 2091: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16) 210 ret 211endfunction 212 213// Main program entry point 214.globl _start 215function _start 216 mov x23, #0 // signal count 217 218 mov w0, #SIGINT 219 adr x1, terminate_handler 220 mov w2, #SA_SIGINFO 221 bl setsignal 222 223 mov w0, #SIGTERM 224 adr x1, terminate_handler 225 mov w2, #SA_SIGINFO 226 bl setsignal 227 228 mov w0, #SIGUSR1 229 adr x1, irritator_handler 230 mov w2, #SA_SIGINFO 231 orr w2, w2, #SA_NODEFER 232 bl setsignal 233 234 mov w0, #SIGUSR2 235 adr x1, tickle_handler 236 mov w2, #SA_SIGINFO 237 orr w2, w2, #SA_NODEFER 238 bl setsignal 239 240 // Sanity-check and report the vector length 241 242 mov x19, #128 243 cmp x19, #128 244 b.lo 1f 245 cmp x19, #2048 246 b.hi 1f 247 tst x19, #(8 - 1) 248 b.eq 2f 249 2501: puts "Bad vector length: " 251 mov x0, x19 252 bl putdecn 253 b .Labort 254 2552: puts "Vector length:\t" 256 mov x0, x19 257 bl putdec 258 puts " bits\n" 259 260 // Obtain our PID, to ensure test pattern uniqueness between processes 261 262 mov x8, #__NR_getpid 263 svc #0 264 mov x20, x0 265 266 puts "PID:\t" 267 mov x0, x20 268 bl putdecn 269 270 mov x22, #0 // generation number, increments per iteration 271.Ltest_loop: 272 273 mov x21, #0 // Set up V-regs & shadow with test pattern 2740: mov x0, x20 275 mov x1, x21 276 and x2, x22, #0xf 277 bl setup_vreg 278 add x21, x21, #1 279 cmp x21, #NVR 280 b.lo 0b 281 282// Can't do this when SVE state is volatile across SVC: 283 mov x8, #__NR_sched_yield // Encourage preemption 284 svc #0 285 286 mov x21, #0 2870: mov x0, x21 288 bl check_vreg 289 add x21, x21, #1 290 cmp x21, #NVR 291 b.lo 0b 292 293 add x22, x22, #1 294 b .Ltest_loop 295 296.Labort: 297 mov x0, #0 298 mov x1, #SIGABRT 299 mov x8, #__NR_kill 300 svc #0 301endfunction 302 303function barf 304 mov x10, x0 // expected data 305 mov x11, x1 // actual data 306 mov x12, x2 // data size 307 308 puts "Mismatch: PID=" 309 mov x0, x20 310 bl putdec 311 puts ", iteration=" 312 mov x0, x22 313 bl putdec 314 puts ", reg=" 315 mov x0, x21 316 bl putdecn 317 puts "\tExpected [" 318 mov x0, x10 319 mov x1, x12 320 bl dumphex 321 puts "]\n\tGot [" 322 mov x0, x11 323 mov x1, x12 324 bl dumphex 325 puts "]\n" 326 327 mov x8, #__NR_exit 328 mov x1, #1 329 svc #0 330endfunction 331