xref: /linux/tools/testing/selftests/arm64/fp/zt-test.S (revision cdd30ebb1b9f36159d66f088b61aee264e649d7a)
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