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 terminate_handler 155 mov w21, w0 156 mov x20, x2 157 158 puts "Terminated by signal " 159 mov w0, w21 160 bl putdec 161 puts ", no error, iterations=" 162 ldr x0, [x20, #ucontext_regs + 8 * 22] 163 bl putdec 164 puts ", signals=" 165 ldr x0, [x20, #ucontext_regs + 8 * 23] 166 bl putdecn 167 168 mov x0, #0 169 mov x8, #__NR_exit 170 svc #0 171endfunction 172 173// w0: signal number 174// x1: sa_action 175// w2: sa_flags 176// Clobbers x0-x6,x8 177function setsignal 178 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]! 179 180 mov w4, w0 181 mov x5, x1 182 mov w6, w2 183 184 add x0, sp, #16 185 mov x1, #sa_sz 186 bl memclr 187 188 mov w0, w4 189 add x1, sp, #16 190 str w6, [x1, #sa_flags] 191 str x5, [x1, #sa_handler] 192 mov x2, #0 193 mov x3, #sa_mask_sz 194 mov x8, #__NR_rt_sigaction 195 svc #0 196 197 cbz w0, 1f 198 199 puts "sigaction failure\n" 200 b .Labort 201 2021: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16) 203 ret 204endfunction 205 206// Main program entry point 207.globl _start 208function _start 209_start: 210 // Sanity-check and report the vector length 211 212 mov x19, #128 213 cmp x19, #128 214 b.lo 1f 215 cmp x19, #2048 216 b.hi 1f 217 tst x19, #(8 - 1) 218 b.eq 2f 219 2201: puts "Bad vector length: " 221 mov x0, x19 222 bl putdecn 223 b .Labort 224 2252: puts "Vector length:\t" 226 mov x0, x19 227 bl putdec 228 puts " bits\n" 229 230 // Obtain our PID, to ensure test pattern uniqueness between processes 231 232 mov x8, #__NR_getpid 233 svc #0 234 mov x20, x0 235 236 puts "PID:\t" 237 mov x0, x20 238 bl putdecn 239 240 mov x23, #0 // Irritation signal count 241 242 mov w0, #SIGINT 243 adr x1, terminate_handler 244 mov w2, #SA_SIGINFO 245 bl setsignal 246 247 mov w0, #SIGTERM 248 adr x1, terminate_handler 249 mov w2, #SA_SIGINFO 250 bl setsignal 251 252 mov w0, #SIGUSR1 253 adr x1, irritator_handler 254 mov w2, #SA_SIGINFO 255 orr w2, w2, #SA_NODEFER 256 bl setsignal 257 258 mov x22, #0 // generation number, increments per iteration 259.Ltest_loop: 260 261 mov x21, #0 // Set up V-regs & shadow with test pattern 2620: mov x0, x20 263 mov x1, x21 264 and x2, x22, #0xf 265 bl setup_vreg 266 add x21, x21, #1 267 cmp x21, #NVR 268 b.lo 0b 269 270// Can't do this when SVE state is volatile across SVC: 271 mov x8, #__NR_sched_yield // Encourage preemption 272 svc #0 273 274 mov x21, #0 2750: mov x0, x21 276 bl check_vreg 277 add x21, x21, #1 278 cmp x21, #NVR 279 b.lo 0b 280 281 add x22, x22, #1 282 b .Ltest_loop 283 284.Labort: 285 mov x0, #0 286 mov x1, #SIGABRT 287 mov x8, #__NR_kill 288 svc #0 289endfunction 290 291function barf 292 mov x10, x0 // expected data 293 mov x11, x1 // actual data 294 mov x12, x2 // data size 295 296 puts "Mismatch: PID=" 297 mov x0, x20 298 bl putdec 299 puts ", iteration=" 300 mov x0, x22 301 bl putdec 302 puts ", reg=" 303 mov x0, x21 304 bl putdecn 305 puts "\tExpected [" 306 mov x0, x10 307 mov x1, x12 308 bl dumphex 309 puts "]\n\tGot [" 310 mov x0, x11 311 mov x1, x12 312 bl dumphex 313 puts "]\n" 314 315 mov x8, #__NR_exit 316 mov x1, #1 317 svc #0 318endfunction 319