1// SPDX-License-Identifier: GPL-2.0-only 2// Copyright (C) 2021-2 ARM Limited. 3// Original author: Mark Brown <broonie@kernel.org> 4// 5// Scalable Matrix Extension ZT context switch test 6// Repeatedly writes unique test patterns into ZT0 7// and reads them back to verify integrity. 8 9#include <asm/unistd.h> 10#include "assembler.h" 11#include "asm-offsets.h" 12#include "sme-inst.h" 13 14.arch_extension sve 15 16#define ZT_SZ 512 17#define ZT_B (ZT_SZ / 8) 18 19// Declare some storage space to shadow ZT register contents and a 20// scratch buffer. 21.pushsection .text 22.data 23.align 4 24ztref: 25 .space ZT_B 26scratch: 27 .space ZT_B 28.popsection 29 30 31// Generate a test pattern for storage in ZT 32// x0: pid 33// x1: generation 34 35// These values are used to construct a 32-bit pattern that is repeated in the 36// scratch buffer as many times as will fit: 37// bits 31:24 generation number (increments once per test_loop) 38// bits 23: 8 pid 39// bits 7: 0 32-bit lane index 40 41function pattern 42 mov w3, wzr 43 bfi w3, w0, #8, #16 // PID 44 bfi w3, w1, #24, #8 // Generation 45 46 ldr x0, =scratch 47 mov w1, #ZT_B / 4 48 490: str w3, [x0], #4 50 add w3, w3, #1 // Lane 51 subs w1, w1, #1 52 b.ne 0b 53 54 ret 55endfunction 56 57// Set up test pattern in a ZT horizontal vector 58// x0: pid 59// x1: generation 60function setup_zt 61 mov x4, x30 62 63 bl pattern // Get pattern in scratch buffer 64 ldr x0, =ztref 65 ldr x1, =scratch 66 mov x2, #ZT_B 67 bl memcpy 68 69 ldr x0, =ztref 70 _ldr_zt 0 // load zt0 from pointer x0 71 72 ret x4 73endfunction 74 75// Trivial memory compare: compare x2 bytes starting at address x0 with 76// bytes starting at address x1. 77// Returns only if all bytes match; otherwise, the program is aborted. 78// Clobbers x0-x5. 79function memcmp 80 cbz x2, 2f 81 82 stp x0, x1, [sp, #-0x20]! 83 str x2, [sp, #0x10] 84 85 mov x5, #0 860: ldrb w3, [x0, x5] 87 ldrb w4, [x1, x5] 88 add x5, x5, #1 89 cmp w3, w4 90 b.ne 1f 91 subs x2, x2, #1 92 b.ne 0b 93 941: ldr x2, [sp, #0x10] 95 ldp x0, x1, [sp], #0x20 96 b.ne barf 97 982: ret 99endfunction 100 101// Verify that a ZT vector matches its shadow in memory, else abort 102// Clobbers x0-x3 103function check_zt 104 mov x3, x30 105 106 ldr x0, =scratch // Poison scratch 107 mov x1, #ZT_B 108 bl memfill_ae 109 110 ldr x0, =scratch 111 _str_zt 0 112 113 ldr x0, =ztref 114 ldr x1, =scratch 115 mov x2, #ZT_B 116 mov x30, x3 117 b memcmp 118endfunction 119 120// Modify the live SME register state, signal return will undo our changes 121function irritator_handler 122 // Increment the irritation signal count (x23): 123 ldr x0, [x2, #ucontext_regs + 8 * 23] 124 add x0, x0, #1 125 str x0, [x2, #ucontext_regs + 8 * 23] 126 127 // This will reset ZT to all bits 0 128 smstop 129 smstart_za 130 131 ret 132endfunction 133 134function tickle_handler 135 // Increment the signal count (x23): 136 ldr x0, [x2, #ucontext_regs + 8 * 23] 137 add x0, x0, #1 138 str x0, [x2, #ucontext_regs + 8 * 23] 139 140 ret 141endfunction 142 143function terminate_handler 144 mov w21, w0 145 mov x20, x2 146 147 puts "Terminated by signal " 148 mov w0, w21 149 bl putdec 150 puts ", no error, iterations=" 151 ldr x0, [x20, #ucontext_regs + 8 * 22] 152 bl putdec 153 puts ", signals=" 154 ldr x0, [x20, #ucontext_regs + 8 * 23] 155 bl putdecn 156 157 mov x0, #0 158 mov x8, #__NR_exit 159 svc #0 160endfunction 161 162// w0: signal number 163// x1: sa_action 164// w2: sa_flags 165// Clobbers x0-x6,x8 166function setsignal 167 str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]! 168 169 mov w4, w0 170 mov x5, x1 171 mov w6, w2 172 173 add x0, sp, #16 174 mov x1, #sa_sz 175 bl memclr 176 177 mov w0, w4 178 add x1, sp, #16 179 str w6, [x1, #sa_flags] 180 str x5, [x1, #sa_handler] 181 mov x2, #0 182 mov x3, #sa_mask_sz 183 mov x8, #__NR_rt_sigaction 184 svc #0 185 186 cbz w0, 1f 187 188 puts "sigaction failure\n" 189 b .Labort 190 1911: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16) 192 ret 193endfunction 194 195// Main program entry point 196.globl _start 197function _start 198 enable_gcs 199 200 mov x23, #0 // signal count 201 202 mov w0, #SIGINT 203 adr x1, terminate_handler 204 mov w2, #SA_SIGINFO 205 bl setsignal 206 207 mov w0, #SIGTERM 208 adr x1, terminate_handler 209 mov w2, #SA_SIGINFO 210 bl setsignal 211 212 mov w0, #SIGUSR1 213 adr x1, irritator_handler 214 mov w2, #SA_SIGINFO 215 orr w2, w2, #SA_NODEFER 216 bl setsignal 217 218 mov w0, #SIGUSR2 219 adr x1, tickle_handler 220 mov w2, #SA_SIGINFO 221 orr w2, w2, #SA_NODEFER 222 bl setsignal 223 224 smstart_za 225 226 // Obtain our PID, to ensure test pattern uniqueness between processes 227 mov x8, #__NR_getpid 228 svc #0 229 mov x20, x0 230 231 puts "PID:\t" 232 mov x0, x20 233 bl putdecn 234 235 mov x22, #0 // generation number, increments per iteration 236.Ltest_loop: 237 mov x0, x20 238 mov x1, x22 239 bl setup_zt 240 241 mov x8, #__NR_sched_yield // Encourage preemption 242 svc #0 243 244 mrs x0, S3_3_C4_C2_2 // SVCR should have ZA=1,SM=0 245 and x1, x0, #3 246 cmp x1, #2 247 b.ne svcr_barf 248 249 bl check_zt 250 251 add x22, x22, #1 // Everything still working 252 b .Ltest_loop 253 254.Labort: 255 mov x0, #0 256 mov x1, #SIGABRT 257 mov x8, #__NR_kill 258 svc #0 259endfunction 260 261function barf 262// fpsimd.c acitivty log dump hack 263// ldr w0, =0xdeadc0de 264// mov w8, #__NR_exit 265// svc #0 266// end hack 267 268 mrs x13, S3_3_C4_C2_2 269 smstop 270 mov x10, x0 // expected data 271 mov x11, x1 // actual data 272 mov x12, x2 // data size 273 274 puts "Mismatch: PID=" 275 mov x0, x20 276 bl putdec 277 puts ", iteration=" 278 mov x0, x22 279 bl putdec 280 puts "\tExpected [" 281 mov x0, x10 282 mov x1, x12 283 bl dumphex 284 puts "]\n\tGot [" 285 mov x0, x11 286 mov x1, x12 287 bl dumphex 288 puts "]\n" 289 puts "\tSVCR: " 290 mov x0, x13 291 bl putdecn 292 293 mov x8, #__NR_getpid 294 svc #0 295// fpsimd.c acitivty log dump hack 296// ldr w0, =0xdeadc0de 297// mov w8, #__NR_exit 298// svc #0 299// ^ end of hack 300 mov x1, #SIGABRT 301 mov x8, #__NR_kill 302 svc #0 303// mov x8, #__NR_exit 304// mov x1, #1 305// svc #0 306endfunction 307 308function svcr_barf 309 mov x10, x0 310 311 puts "Bad SVCR: " 312 mov x0, x10 313 bl putdecn 314 315 mov x8, #__NR_exit 316 mov x1, #1 317 svc #0 318endfunction 319