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
24 ztref:
25 	.space	ZT_B
26 scratch:
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 
41 function 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 
49 0:	str	w3, [x0], #4
50 	add	w3, w3, #1		// Lane
51 	subs	w1, w1, #1
52 	b.ne	0b
53 
54 	ret
55 endfunction
56 
57 // Set up test pattern in a ZT horizontal vector
58 // x0: pid
59 // x1: generation
60 function 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
73 endfunction
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.
79 function memcmp
80 	cbz	x2, 2f
81 
82 	stp	x0, x1, [sp, #-0x20]!
83 	str	x2, [sp, #0x10]
84 
85 	mov	x5, #0
86 0:	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 
94 1:	ldr	x2, [sp, #0x10]
95 	ldp	x0, x1, [sp], #0x20
96 	b.ne	barf
97 
98 2:	ret
99 endfunction
100 
101 // Verify that a ZT vector matches its shadow in memory, else abort
102 // Clobbers x0-x3
103 function 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
118 endfunction
119 
120 // Any SME register modified here can cause corruption in the main
121 // thread -- but *only* the locations modified here.
122 function irritator_handler
123 	// Increment the irritation signal count (x23):
124 	ldr	x0, [x2, #ucontext_regs + 8 * 23]
125 	add	x0, x0, #1
126 	str	x0, [x2, #ucontext_regs + 8 * 23]
127 
128 	// Corrupt some random ZT data
129 #if 0
130 	adr	x0, .text + (irritator_handler - .text) / 16 * 16
131 	movi	v0.8b, #1
132 	movi	v9.16b, #2
133 	movi	v31.8b, #3
134 #endif
135 
136 	ret
137 endfunction
138 
139 function tickle_handler
140 	// Increment the 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 	ret
146 endfunction
147 
148 function terminate_handler
149 	mov	w21, w0
150 	mov	x20, x2
151 
152 	puts	"Terminated by signal "
153 	mov	w0, w21
154 	bl	putdec
155 	puts	", no error, iterations="
156 	ldr	x0, [x20, #ucontext_regs + 8 * 22]
157 	bl	putdec
158 	puts	", signals="
159 	ldr	x0, [x20, #ucontext_regs + 8 * 23]
160 	bl	putdecn
161 
162 	mov	x0, #0
163 	mov	x8, #__NR_exit
164 	svc	#0
165 endfunction
166 
167 // w0: signal number
168 // x1: sa_action
169 // w2: sa_flags
170 // Clobbers x0-x6,x8
171 function setsignal
172 	str	x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
173 
174 	mov	w4, w0
175 	mov	x5, x1
176 	mov	w6, w2
177 
178 	add	x0, sp, #16
179 	mov	x1, #sa_sz
180 	bl	memclr
181 
182 	mov	w0, w4
183 	add	x1, sp, #16
184 	str	w6, [x1, #sa_flags]
185 	str	x5, [x1, #sa_handler]
186 	mov	x2, #0
187 	mov	x3, #sa_mask_sz
188 	mov	x8, #__NR_rt_sigaction
189 	svc	#0
190 
191 	cbz	w0, 1f
192 
193 	puts	"sigaction failure\n"
194 	b	.Labort
195 
196 1:	ldr	x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
197 	ret
198 endfunction
199 
200 // Main program entry point
201 .globl _start
202 function _start
203 	mov	x23, #0		// signal count
204 
205 	mov	w0, #SIGINT
206 	adr	x1, terminate_handler
207 	mov	w2, #SA_SIGINFO
208 	bl	setsignal
209 
210 	mov	w0, #SIGTERM
211 	adr	x1, terminate_handler
212 	mov	w2, #SA_SIGINFO
213 	bl	setsignal
214 
215 	mov	w0, #SIGUSR1
216 	adr	x1, irritator_handler
217 	mov	w2, #SA_SIGINFO
218 	orr	w2, w2, #SA_NODEFER
219 	bl	setsignal
220 
221 	mov	w0, #SIGUSR2
222 	adr	x1, tickle_handler
223 	mov	w2, #SA_SIGINFO
224 	orr	w2, w2, #SA_NODEFER
225 	bl	setsignal
226 
227 	smstart_za
228 
229 	// Obtain our PID, to ensure test pattern uniqueness between processes
230 	mov	x8, #__NR_getpid
231 	svc	#0
232 	mov	x20, x0
233 
234 	puts	"PID:\t"
235 	mov	x0, x20
236 	bl	putdecn
237 
238 	mov	x22, #0		// generation number, increments per iteration
239 .Ltest_loop:
240 	mov	x0, x20
241 	mov	x1, x22
242 	bl	setup_zt
243 
244 	mov	x8, #__NR_sched_yield	// Encourage preemption
245 	svc	#0
246 
247 	mrs	x0, S3_3_C4_C2_2	// SVCR should have ZA=1,SM=0
248 	and	x1, x0, #3
249 	cmp	x1, #2
250 	b.ne	svcr_barf
251 
252 	bl	check_zt
253 
254 	add	x22, x22, #1	// Everything still working
255 	b	.Ltest_loop
256 
257 .Labort:
258 	mov	x0, #0
259 	mov	x1, #SIGABRT
260 	mov	x8, #__NR_kill
261 	svc	#0
262 endfunction
263 
264 function barf
265 // fpsimd.c acitivty log dump hack
266 //	ldr	w0, =0xdeadc0de
267 //	mov	w8, #__NR_exit
268 //	svc	#0
269 // end hack
270 	smstop
271 	mov	x10, x0	// expected data
272 	mov	x11, x1	// actual data
273 	mov	x12, x2	// data size
274 
275 	puts	"Mismatch: PID="
276 	mov	x0, x20
277 	bl	putdec
278 	puts	", iteration="
279 	mov	x0, x22
280 	bl	putdec
281 	puts	"\tExpected ["
282 	mov	x0, x10
283 	mov	x1, x12
284 	bl	dumphex
285 	puts	"]\n\tGot      ["
286 	mov	x0, x11
287 	mov	x1, x12
288 	bl	dumphex
289 	puts	"]\n"
290 
291 	mov	x8, #__NR_getpid
292 	svc	#0
293 // fpsimd.c acitivty log dump hack
294 //	ldr	w0, =0xdeadc0de
295 //	mov	w8, #__NR_exit
296 //	svc	#0
297 // ^ end of hack
298 	mov	x1, #SIGABRT
299 	mov	x8, #__NR_kill
300 	svc	#0
301 //	mov	x8, #__NR_exit
302 //	mov	x1, #1
303 //	svc	#0
304 endfunction
305 
306 function svcr_barf
307 	mov	x10, x0
308 
309 	puts	"Bad SVCR: "
310 	mov	x0, x10
311 	bl	putdecn
312 
313 	mov	x8, #__NR_exit
314 	mov	x1, #1
315 	svc	#0
316 endfunction
317