333 lines · plain
1// SPDX-License-Identifier: GPL-2.0-only2// Copyright (C) 2015-2019 ARM Limited.3// Original author: Dave Martin <Dave.Martin@arm.com>4//5// Simple FPSIMD context switch test6// Repeatedly writes unique test patterns into each FPSIMD register7// and reads them back to verify integrity.8//9// for x in `seq 1 NR_CPUS`; do fpsimd-test & pids=$pids\ $! ; done10// (leave it running for as long as you want...)11// kill $pids12 13#include <asm/unistd.h>14#include "assembler.h"15#include "asm-offsets.h"16 17#define NVR 3218#define MAXVL_B (128 / 8)19 20.macro _vldr Vn:req, Xt:req21 ld1 {v\Vn\().2d}, [x\Xt]22.endm23 24.macro _vstr Vn:req, Xt:req25 st1 {v\Vn\().2d}, [x\Xt]26.endm27 28// Generate accessor functions to read/write programmatically selected29// FPSIMD registers.30// x0 is the register index to access31// x1 is the memory address to read from (getv,setp) or store to (setv,setp)32// All clobber x0-x233define_accessor setv, NVR, _vldr34define_accessor getv, NVR, _vstr35 36// Declare some storate space to shadow the SVE register contents:37.pushsection .text38.data39.align 440vref:41 .space MAXVL_B * NVR42scratch:43 .space MAXVL_B44.popsection45 46// Generate a test pattern for storage in SVE registers47// x0: pid (16 bits)48// x1: register number (6 bits)49// x2: generation (4 bits)50function pattern51 orr w1, w0, w1, lsl #1652 orr w2, w1, w2, lsl #2853 54 ldr x0, =scratch55 mov w1, #MAXVL_B / 456 570: str w2, [x0], #458 add w2, w2, #(1 << 22)59 subs w1, w1, #160 bne 0b61 62 ret63endfunction64 65// Get the address of shadow data for FPSIMD V-register V<xn>66.macro _adrv xd, xn, nrtmp67 ldr \xd, =vref68 mov x\nrtmp, #1669 madd \xd, x\nrtmp, \xn, \xd70.endm71 72// Set up test pattern in a FPSIMD V-register73// x0: pid74// x1: register number75// x2: generation76function setup_vreg77 mov x4, x3078 79 mov x6, x180 bl pattern81 _adrv x0, x6, 282 mov x5, x083 ldr x1, =scratch84 bl memcpy85 86 mov x0, x687 mov x1, x588 bl setv89 90 ret x491endfunction92 93// Trivial memory compare: compare x2 bytes starting at address x0 with94// bytes starting at address x1.95// Returns only if all bytes match; otherwise, the program is aborted.96// Clobbers x0-x5.97function memcmp98 cbz x2, 1f99 100 mov x5, #01010: ldrb w3, [x0, x5]102 ldrb w4, [x1, x5]103 add x5, x5, #1104 cmp w3, w4105 b.ne barf106 subs x2, x2, #1107 b.ne 0b108 1091: ret110endfunction111 112// Verify that a FPSIMD V-register matches its shadow in memory, else abort113// x0: reg number114// Clobbers x0-x5.115function check_vreg116 mov x3, x30117 118 _adrv x5, x0, 6119 mov x4, x0120 ldr x7, =scratch121 122 mov x0, x7123 mov x1, x6124 bl memfill_ae125 126 mov x0, x4127 mov x1, x7128 bl getv129 130 mov x0, x5131 mov x1, x7132 mov x2, x6133 mov x30, x3134 b memcmp135endfunction136 137// Any SVE register modified here can cause corruption in the main138// thread -- but *only* the registers modified here.139function irritator_handler140 // Increment the irritation signal count (x23):141 ldr x0, [x2, #ucontext_regs + 8 * 23]142 add x0, x0, #1143 str x0, [x2, #ucontext_regs + 8 * 23]144 145 // Corrupt some random V-regs146 adr x0, .text + (irritator_handler - .text) / 16 * 16147 movi v0.8b, #7148 movi v9.16b, #9149 movi v31.8b, #31150 151 ret152endfunction153 154function tickle_handler155 // Increment the signal count (x23):156 ldr x0, [x2, #ucontext_regs + 8 * 23]157 add x0, x0, #1158 str x0, [x2, #ucontext_regs + 8 * 23]159 160 ret161endfunction162 163function terminate_handler164 mov w21, w0165 mov x20, x2166 167 puts "Terminated by signal "168 mov w0, w21169 bl putdec170 puts ", no error, iterations="171 ldr x0, [x20, #ucontext_regs + 8 * 22]172 bl putdec173 puts ", signals="174 ldr x0, [x20, #ucontext_regs + 8 * 23]175 bl putdecn176 177 mov x0, #0178 mov x8, #__NR_exit179 svc #0180endfunction181 182// w0: signal number183// x1: sa_action184// w2: sa_flags185// Clobbers x0-x6,x8186function setsignal187 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!188 189 mov w4, w0190 mov x5, x1191 mov w6, w2192 193 add x0, sp, #16194 mov x1, #sa_sz195 bl memclr196 197 mov w0, w4198 add x1, sp, #16199 str w6, [x1, #sa_flags]200 str x5, [x1, #sa_handler]201 mov x2, #0202 mov x3, #sa_mask_sz203 mov x8, #__NR_rt_sigaction204 svc #0205 206 cbz w0, 1f207 208 puts "sigaction failure\n"209 b .Labort210 2111: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)212 ret213endfunction214 215// Main program entry point216.globl _start217function _start218 mov x23, #0 // signal count219 220 mov w0, #SIGINT221 adr x1, terminate_handler222 mov w2, #SA_SIGINFO223 bl setsignal224 225 mov w0, #SIGTERM226 adr x1, terminate_handler227 mov w2, #SA_SIGINFO228 bl setsignal229 230 mov w0, #SIGUSR1231 adr x1, irritator_handler232 mov w2, #SA_SIGINFO233 orr w2, w2, #SA_NODEFER234 bl setsignal235 236 mov w0, #SIGUSR2237 adr x1, tickle_handler238 mov w2, #SA_SIGINFO239 orr w2, w2, #SA_NODEFER240 bl setsignal241 242 // Sanity-check and report the vector length243 244 mov x19, #128245 cmp x19, #128246 b.lo 1f247 cmp x19, #2048248 b.hi 1f249 tst x19, #(8 - 1)250 b.eq 2f251 2521: puts "Bad vector length: "253 mov x0, x19254 bl putdecn255 b .Labort256 2572: puts "Vector length:\t"258 mov x0, x19259 bl putdec260 puts " bits\n"261 262 // Obtain our PID, to ensure test pattern uniqueness between processes263 264 mov x8, #__NR_getpid265 svc #0266 mov x20, x0267 268 puts "PID:\t"269 mov x0, x20270 bl putdecn271 272 mov x22, #0 // generation number, increments per iteration273.Ltest_loop:274 275 mov x21, #0 // Set up V-regs & shadow with test pattern2760: mov x0, x20277 mov x1, x21278 and x2, x22, #0xf279 bl setup_vreg280 add x21, x21, #1281 cmp x21, #NVR282 b.lo 0b283 284// Can't do this when SVE state is volatile across SVC:285 mov x8, #__NR_sched_yield // Encourage preemption286 svc #0287 288 mov x21, #02890: mov x0, x21290 bl check_vreg291 add x21, x21, #1292 cmp x21, #NVR293 b.lo 0b294 295 add x22, x22, #1296 b .Ltest_loop297 298.Labort:299 mov x0, #0300 mov x1, #SIGABRT301 mov x8, #__NR_kill302 svc #0303endfunction304 305function barf306 mov x10, x0 // expected data307 mov x11, x1 // actual data308 mov x12, x2 // data size309 310 puts "Mismatch: PID="311 mov x0, x20312 bl putdec313 puts ", iteration="314 mov x0, x22315 bl putdec316 puts ", reg="317 mov x0, x21318 bl putdecn319 puts "\tExpected ["320 mov x0, x10321 mov x1, x12322 bl dumphex323 puts "]\n\tGot ["324 mov x0, x11325 mov x1, x12326 bl dumphex327 puts "]\n"328 329 mov x8, #__NR_exit330 mov x1, #1331 svc #0332endfunction333