404 lines · plain
1// SPDX-License-Identifier: GPL-2.0-only2// Copyright (C) 2021 ARM Limited.3// Original author: Mark Brown <broonie@kernel.org>4//5// Scalable Matrix Extension ZA context switch test6// Repeatedly writes unique test patterns into each ZA tile7// and reads them back to verify integrity.8//9// for x in `seq 1 NR_CPUS`; do sve-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#include "sme-inst.h"17 18.arch_extension sve19 20#define MAXVL 204821#define MAXVL_B (MAXVL / 8)22 23// Declare some storage space to shadow ZA register contents and a24// scratch buffer for a vector.25.pushsection .text26.data27.align 428zaref:29 .space MAXVL_B * MAXVL_B30scratch:31 .space MAXVL_B32.popsection33 34// Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.35// Clobbers x0-x336function memcpy37 cmp x2, #038 b.eq 1f390: ldrb w3, [x1], #140 strb w3, [x0], #141 subs x2, x2, #142 b.ne 0b431: ret44endfunction45 46// Generate a test pattern for storage in ZA47// x0: pid48// x1: row in ZA49// x2: generation50 51// These values are used to constuct a 32-bit pattern that is repeated in the52// scratch buffer as many times as will fit:53// bits 31:28 generation number (increments once per test_loop)54// bits 27:16 pid55// bits 15: 8 row number56// bits 7: 0 32-bit lane index57 58function pattern59 mov w3, wzr60 bfi w3, w0, #16, #12 // PID61 bfi w3, w1, #8, #8 // Row62 bfi w3, w2, #28, #4 // Generation63 64 ldr x0, =scratch65 mov w1, #MAXVL_B / 466 670: str w3, [x0], #468 add w3, w3, #1 // Lane69 subs w1, w1, #170 b.ne 0b71 72 ret73endfunction74 75// Get the address of shadow data for ZA horizontal vector xn76.macro _adrza xd, xn, nrtmp77 ldr \xd, =zaref78 rdsvl \nrtmp, 179 madd \xd, x\nrtmp, \xn, \xd80.endm81 82// Set up test pattern in a ZA horizontal vector83// x0: pid84// x1: row number85// x2: generation86function setup_za87 mov x4, x3088 mov x12, x1 // Use x12 for vector select89 90 bl pattern // Get pattern in scratch buffer91 _adrza x0, x12, 2 // Shadow buffer pointer to x0 and x592 mov x5, x093 ldr x1, =scratch94 bl memcpy // length set up in x2 by _adrza95 96 _ldr_za 12, 5 // load vector w12 from pointer x597 98 ret x499endfunction100 101// Trivial memory compare: compare x2 bytes starting at address x0 with102// bytes starting at address x1.103// Returns only if all bytes match; otherwise, the program is aborted.104// Clobbers x0-x5.105function memcmp106 cbz x2, 2f107 108 stp x0, x1, [sp, #-0x20]!109 str x2, [sp, #0x10]110 111 mov x5, #01120: ldrb w3, [x0, x5]113 ldrb w4, [x1, x5]114 add x5, x5, #1115 cmp w3, w4116 b.ne 1f117 subs x2, x2, #1118 b.ne 0b119 1201: ldr x2, [sp, #0x10]121 ldp x0, x1, [sp], #0x20122 b.ne barf123 1242: ret125endfunction126 127// Verify that a ZA vector matches its shadow in memory, else abort128// x0: row number129// Clobbers x0-x7 and x12.130function check_za131 mov x3, x30132 133 mov x12, x0134 _adrza x5, x0, 6 // pointer to expected value in x5135 mov x4, x0136 ldr x7, =scratch // x7 is scratch137 138 mov x0, x7 // Poison scratch139 mov x1, x6140 bl memfill_ae141 142 _str_za 12, 7 // save vector w12 to pointer x7143 144 mov x0, x5145 mov x1, x7146 mov x2, x6147 mov x30, x3148 b memcmp149endfunction150 151// Any SME register modified here can cause corruption in the main152// thread -- but *only* the locations modified here.153function irritator_handler154 // Increment the irritation signal count (x23):155 ldr x0, [x2, #ucontext_regs + 8 * 23]156 add x0, x0, #1157 str x0, [x2, #ucontext_regs + 8 * 23]158 159 // Corrupt some random ZA data160#if 0161 adr x0, .text + (irritator_handler - .text) / 16 * 16162 movi v0.8b, #1163 movi v9.16b, #2164 movi v31.8b, #3165#endif166 167 ret168endfunction169 170function tickle_handler171 // Increment the signal count (x23):172 ldr x0, [x2, #ucontext_regs + 8 * 23]173 add x0, x0, #1174 str x0, [x2, #ucontext_regs + 8 * 23]175 176 ret177endfunction178 179function terminate_handler180 mov w21, w0181 mov x20, x2182 183 puts "Terminated by signal "184 mov w0, w21185 bl putdec186 puts ", no error, iterations="187 ldr x0, [x20, #ucontext_regs + 8 * 22]188 bl putdec189 puts ", signals="190 ldr x0, [x20, #ucontext_regs + 8 * 23]191 bl putdecn192 193 mov x0, #0194 mov x8, #__NR_exit195 svc #0196endfunction197 198// w0: signal number199// x1: sa_action200// w2: sa_flags201// Clobbers x0-x6,x8202function setsignal203 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!204 205 mov w4, w0206 mov x5, x1207 mov w6, w2208 209 add x0, sp, #16210 mov x1, #sa_sz211 bl memclr212 213 mov w0, w4214 add x1, sp, #16215 str w6, [x1, #sa_flags]216 str x5, [x1, #sa_handler]217 mov x2, #0218 mov x3, #sa_mask_sz219 mov x8, #__NR_rt_sigaction220 svc #0221 222 cbz w0, 1f223 224 puts "sigaction failure\n"225 b .Labort226 2271: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)228 ret229endfunction230 231// Main program entry point232.globl _start233function _start234 mov x23, #0 // signal count235 236 mov w0, #SIGINT237 adr x1, terminate_handler238 mov w2, #SA_SIGINFO239 bl setsignal240 241 mov w0, #SIGTERM242 adr x1, terminate_handler243 mov w2, #SA_SIGINFO244 bl setsignal245 246 mov w0, #SIGUSR1247 adr x1, irritator_handler248 mov w2, #SA_SIGINFO249 orr w2, w2, #SA_NODEFER250 bl setsignal251 252 mov w0, #SIGUSR2253 adr x1, tickle_handler254 mov w2, #SA_SIGINFO255 orr w2, w2, #SA_NODEFER256 bl setsignal257 258 puts "Streaming mode "259 smstart_za260 261 // Sanity-check and report the vector length262 263 rdsvl 19, 8264 cmp x19, #128265 b.lo 1f266 cmp x19, #2048267 b.hi 1f268 tst x19, #(8 - 1)269 b.eq 2f270 2711: puts "bad vector length: "272 mov x0, x19273 bl putdecn274 b .Labort275 2762: puts "vector length:\t"277 mov x0, x19278 bl putdec279 puts " bits\n"280 281 // Obtain our PID, to ensure test pattern uniqueness between processes282 mov x8, #__NR_getpid283 svc #0284 mov x20, x0285 286 puts "PID:\t"287 mov x0, x20288 bl putdecn289 290 mov x22, #0 // generation number, increments per iteration291.Ltest_loop:292 rdsvl 0, 8293 cmp x0, x19294 b.ne vl_barf295 296 rdsvl 21, 1 // Set up ZA & shadow with test pattern2970: mov x0, x20298 sub x1, x21, #1299 mov x2, x22300 bl setup_za301 subs x21, x21, #1302 b.ne 0b303 304 mov x8, #__NR_sched_yield // encourage preemption3051:306 svc #0307 308 mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=1,SM=0309 and x1, x0, #3310 cmp x1, #2311 b.ne svcr_barf312 313 rdsvl 21, 1 // Verify that the data made it through314 rdsvl 24, 1 // Verify that the data made it through3150: sub x0, x24, x21316 bl check_za317 subs x21, x21, #1318 bne 0b319 320 add x22, x22, #1 // Everything still working321 b .Ltest_loop322 323.Labort:324 mov x0, #0325 mov x1, #SIGABRT326 mov x8, #__NR_kill327 svc #0328endfunction329 330function barf331// fpsimd.c acitivty log dump hack332// ldr w0, =0xdeadc0de333// mov w8, #__NR_exit334// svc #0335// end hack336 337 mrs x13, S3_3_C4_C2_2338 339 smstop340 mov x10, x0 // expected data341 mov x11, x1 // actual data342 mov x12, x2 // data size343 344 puts "Mismatch: PID="345 mov x0, x20346 bl putdec347 puts ", iteration="348 mov x0, x22349 bl putdec350 puts ", row="351 mov x0, x21352 bl putdecn353 puts "\tExpected ["354 mov x0, x10355 mov x1, x12356 bl dumphex357 puts "]\n\tGot ["358 mov x0, x11359 mov x1, x12360 bl dumphex361 puts "]\n"362 puts "\tSVCR: "363 mov x0, x13364 bl putdecn365 366 mov x8, #__NR_getpid367 svc #0368// fpsimd.c acitivty log dump hack369// ldr w0, =0xdeadc0de370// mov w8, #__NR_exit371// svc #0372// ^ end of hack373 mov x1, #SIGABRT374 mov x8, #__NR_kill375 svc #0376// mov x8, #__NR_exit377// mov x1, #1378// svc #0379endfunction380 381function vl_barf382 mov x10, x0383 384 puts "Bad active VL: "385 mov x0, x10386 bl putdecn387 388 mov x8, #__NR_exit389 mov x1, #1390 svc #0391endfunction392 393function svcr_barf394 mov x10, x0395 396 puts "Bad SVCR: "397 mov x0, x10398 bl putdecn399 400 mov x8, #__NR_exit401 mov x1, #1402 svc #0403endfunction404