xref: /linux/tools/testing/selftests/arm64/fp/fp-ptrace-asm.S (revision fcb3ad4366b9c810cbb9da34c076a9a52d8aa1e0)
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (C) 2021-3 ARM Limited.
3//
4// Assembly portion of the FP ptrace test
5
6//
7// Load values from memory into registers, break on a breakpoint, then
8// break on a further breakpoint
9//
10
11#include "fp-ptrace.h"
12#include "sme-inst.h"
13
14.arch_extension sve
15
16// Load and save register values with pauses for ptrace
17//
18// x0 - HAVE_ flags indicating which features are in use
19
20.globl load_and_save
21load_and_save:
22	stp	x11, x12, [sp, #-0x10]!
23
24	// This should be redundant in the SVE case
25	ldr	x7, =v_in
26	ldp	q0, q1, [x7]
27	ldp	q2, q3, [x7, #16 * 2]
28	ldp	q4, q5, [x7, #16 * 4]
29	ldp	q6, q7, [x7, #16 * 6]
30	ldp	q8, q9, [x7, #16 * 8]
31	ldp	q10, q11, [x7, #16 * 10]
32	ldp	q12, q13, [x7, #16 * 12]
33	ldp	q14, q15, [x7, #16 * 14]
34	ldp	q16, q17, [x7, #16 * 16]
35	ldp	q18, q19, [x7, #16 * 18]
36	ldp	q20, q21, [x7, #16 * 20]
37	ldp	q22, q23, [x7, #16 * 22]
38	ldp	q24, q25, [x7, #16 * 24]
39	ldp	q26, q27, [x7, #16 * 26]
40	ldp	q28, q29, [x7, #16 * 28]
41	ldp	q30, q31, [x7, #16 * 30]
42
43	// SME?
44	tbz	x0, #HAVE_SME_SHIFT, check_sve_in
45
46	adrp	x7, svcr_in
47	ldr	x7, [x7, :lo12:svcr_in]
48	// SVCR is 0 by default, avoid triggering SME if not in use
49	cbz	x7, check_sve_in
50	msr	S3_3_C4_C2_2, x7
51
52	// ZA?
53	tbz	x7, #SVCR_ZA_SHIFT, check_sm_in
54	rdsvl	11, 1
55	mov	w12, #0
56	ldr	x6, =za_in
571:	_ldr_za 12, 6
58	add	x6, x6, x11
59	add	x12, x12, #1
60	cmp	x11, x12
61	bne	1b
62
63	// ZT?
64	tbz	x0, #HAVE_SME2_SHIFT, check_sm_in
65	adrp	x6, zt_in
66	add	x6, x6, :lo12:zt_in
67	_ldr_zt 6
68
69	// In streaming mode?
70check_sm_in:
71	tbz	x7, #SVCR_SM_SHIFT, check_sve_in
72
73	// Load FFR if we have FA64
74	ubfx	x4, x0, #HAVE_FA64_SHIFT, #1
75	b	load_sve
76
77	// SVE?
78check_sve_in:
79	tbz	x0, #HAVE_SVE_SHIFT, check_fpmr_in
80	mov	x4, #1
81
82load_sve:
83	ldr	x7, =z_in
84	ldr	z0, [x7, #0, MUL VL]
85	ldr	z1, [x7, #1, MUL VL]
86	ldr	z2, [x7, #2, MUL VL]
87	ldr	z3, [x7, #3, MUL VL]
88	ldr	z4, [x7, #4, MUL VL]
89	ldr	z5, [x7, #5, MUL VL]
90	ldr	z6, [x7, #6, MUL VL]
91	ldr	z7, [x7, #7, MUL VL]
92	ldr	z8, [x7, #8, MUL VL]
93	ldr	z9, [x7, #9, MUL VL]
94	ldr	z10, [x7, #10, MUL VL]
95	ldr	z11, [x7, #11, MUL VL]
96	ldr	z12, [x7, #12, MUL VL]
97	ldr	z13, [x7, #13, MUL VL]
98	ldr	z14, [x7, #14, MUL VL]
99	ldr	z15, [x7, #15, MUL VL]
100	ldr	z16, [x7, #16, MUL VL]
101	ldr	z17, [x7, #17, MUL VL]
102	ldr	z18, [x7, #18, MUL VL]
103	ldr	z19, [x7, #19, MUL VL]
104	ldr	z20, [x7, #20, MUL VL]
105	ldr	z21, [x7, #21, MUL VL]
106	ldr	z22, [x7, #22, MUL VL]
107	ldr	z23, [x7, #23, MUL VL]
108	ldr	z24, [x7, #24, MUL VL]
109	ldr	z25, [x7, #25, MUL VL]
110	ldr	z26, [x7, #26, MUL VL]
111	ldr	z27, [x7, #27, MUL VL]
112	ldr	z28, [x7, #28, MUL VL]
113	ldr	z29, [x7, #29, MUL VL]
114	ldr	z30, [x7, #30, MUL VL]
115	ldr	z31, [x7, #31, MUL VL]
116
117	// FFR is not present in base SME
118	cbz	x4, 1f
119	ldr	x7, =ffr_in
120	ldr	p0, [x7]
121	ldr	x7, [x7, #0]
122	cbz	x7, 1f
123	wrffr	p0.b
1241:
125
126	ldr	x7, =p_in
127	ldr	p0, [x7, #0, MUL VL]
128	ldr	p1, [x7, #1, MUL VL]
129	ldr	p2, [x7, #2, MUL VL]
130	ldr	p3, [x7, #3, MUL VL]
131	ldr	p4, [x7, #4, MUL VL]
132	ldr	p5, [x7, #5, MUL VL]
133	ldr	p6, [x7, #6, MUL VL]
134	ldr	p7, [x7, #7, MUL VL]
135	ldr	p8, [x7, #8, MUL VL]
136	ldr	p9, [x7, #9, MUL VL]
137	ldr	p10, [x7, #10, MUL VL]
138	ldr	p11, [x7, #11, MUL VL]
139	ldr	p12, [x7, #12, MUL VL]
140	ldr	p13, [x7, #13, MUL VL]
141	ldr	p14, [x7, #14, MUL VL]
142	ldr	p15, [x7, #15, MUL VL]
143
144	// This has to come after we set PSTATE.SM
145check_fpmr_in:
146	tbz	x0, #HAVE_FPMR_SHIFT, wait_for_writes
147	adrp	x7, fpmr_in
148	ldr	x7, [x7, :lo12:fpmr_in]
149	msr	REG_FPMR, x7
150
151wait_for_writes:
152	// Wait for the parent
153	brk #0
154
155	// Save values
156	ldr	x7, =v_out
157	stp	q0, q1, [x7]
158	stp	q2, q3, [x7, #16 * 2]
159	stp	q4, q5, [x7, #16 * 4]
160	stp	q6, q7, [x7, #16 * 6]
161	stp	q8, q9, [x7, #16 * 8]
162	stp	q10, q11, [x7, #16 * 10]
163	stp	q12, q13, [x7, #16 * 12]
164	stp	q14, q15, [x7, #16 * 14]
165	stp	q16, q17, [x7, #16 * 16]
166	stp	q18, q19, [x7, #16 * 18]
167	stp	q20, q21, [x7, #16 * 20]
168	stp	q22, q23, [x7, #16 * 22]
169	stp	q24, q25, [x7, #16 * 24]
170	stp	q26, q27, [x7, #16 * 26]
171	stp	q28, q29, [x7, #16 * 28]
172	stp	q30, q31, [x7, #16 * 30]
173
174	tbz	x0, #HAVE_FPMR_SHIFT, check_sme_out
175	mrs	x7, REG_FPMR
176	adrp	x6, fpmr_out
177	str	x7, [x6, :lo12:fpmr_out]
178
179check_sme_out:
180	tbz	x0, #HAVE_SME_SHIFT, check_sve_out
181
182	rdsvl	11, 1
183	adrp	x6, sme_vl_out
184	str	x11, [x6, :lo12:sme_vl_out]
185
186	mrs	x7, S3_3_C4_C2_2
187	adrp	x6, svcr_out
188	str	x7, [x6, :lo12:svcr_out]
189
190	// ZA?
191	tbz	x7, #SVCR_ZA_SHIFT, check_sm_out
192	mov	w12, #0
193	ldr	x6, =za_out
1941:	_str_za 12, 6
195	add	x6, x6, x11
196	add	x12, x12, #1
197	cmp	x11, x12
198	bne	1b
199
200	// ZT?
201	tbz	x0, #HAVE_SME2_SHIFT, check_sm_out
202	adrp	x6, zt_out
203	add	x6, x6, :lo12:zt_out
204	_str_zt 6
205
206	// In streaming mode?
207check_sm_out:
208	tbz	x7, #SVCR_SM_SHIFT, check_sve_out
209
210	// Do we have FA64 and FFR?
211	ubfx	x4, x0, #HAVE_FA64_SHIFT, #1
212	b	read_sve
213
214	// SVE?
215check_sve_out:
216	tbz	x0, #HAVE_SVE_SHIFT, wait_for_reads
217	mov	x4, #1
218
219	rdvl	x7, #1
220	adrp	x6, sve_vl_out
221	str	x7, [x6, :lo12:sve_vl_out]
222
223read_sve:
224	ldr	x7, =z_out
225	str	z0, [x7, #0, MUL VL]
226	str	z1, [x7, #1, MUL VL]
227	str	z2, [x7, #2, MUL VL]
228	str	z3, [x7, #3, MUL VL]
229	str	z4, [x7, #4, MUL VL]
230	str	z5, [x7, #5, MUL VL]
231	str	z6, [x7, #6, MUL VL]
232	str	z7, [x7, #7, MUL VL]
233	str	z8, [x7, #8, MUL VL]
234	str	z9, [x7, #9, MUL VL]
235	str	z10, [x7, #10, MUL VL]
236	str	z11, [x7, #11, MUL VL]
237	str	z12, [x7, #12, MUL VL]
238	str	z13, [x7, #13, MUL VL]
239	str	z14, [x7, #14, MUL VL]
240	str	z15, [x7, #15, MUL VL]
241	str	z16, [x7, #16, MUL VL]
242	str	z17, [x7, #17, MUL VL]
243	str	z18, [x7, #18, MUL VL]
244	str	z19, [x7, #19, MUL VL]
245	str	z20, [x7, #20, MUL VL]
246	str	z21, [x7, #21, MUL VL]
247	str	z22, [x7, #22, MUL VL]
248	str	z23, [x7, #23, MUL VL]
249	str	z24, [x7, #24, MUL VL]
250	str	z25, [x7, #25, MUL VL]
251	str	z26, [x7, #26, MUL VL]
252	str	z27, [x7, #27, MUL VL]
253	str	z28, [x7, #28, MUL VL]
254	str	z29, [x7, #29, MUL VL]
255	str	z30, [x7, #30, MUL VL]
256	str	z31, [x7, #31, MUL VL]
257
258	ldr	x7, =p_out
259	str	p0, [x7, #0, MUL VL]
260	str	p1, [x7, #1, MUL VL]
261	str	p2, [x7, #2, MUL VL]
262	str	p3, [x7, #3, MUL VL]
263	str	p4, [x7, #4, MUL VL]
264	str	p5, [x7, #5, MUL VL]
265	str	p6, [x7, #6, MUL VL]
266	str	p7, [x7, #7, MUL VL]
267	str	p8, [x7, #8, MUL VL]
268	str	p9, [x7, #9, MUL VL]
269	str	p10, [x7, #10, MUL VL]
270	str	p11, [x7, #11, MUL VL]
271	str	p12, [x7, #12, MUL VL]
272	str	p13, [x7, #13, MUL VL]
273	str	p14, [x7, #14, MUL VL]
274	str	p15, [x7, #15, MUL VL]
275
276	// Only save FFR if it exists
277	cbz	x4, wait_for_reads
278	ldr	x7, =ffr_out
279	rdffr	p0.b
280	str	p0, [x7]
281
282wait_for_reads:
283	// Wait for the parent
284	brk #0
285
286	// Ensure we don't leave ourselves in streaming mode
287	tbz	x0, #HAVE_SME_SHIFT, out
288	msr	S3_3_C4_C2_2, xzr
289
290out:
291	ldp	x11, x12, [sp, #-0x10]
292	ret
293