support.S revision 319202
1/*-
2 * Copyright (c) 2014 Andrew Turner
3 * Copyright (c) 2014-2015 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * Portions of this software were developed by Andrew Turner
7 * under sponsorship from the FreeBSD Foundation
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32#include <machine/asm.h>
33__FBSDID("$FreeBSD: stable/11/sys/arm64/arm64/support.S 319202 2017-05-30 12:26:36Z andrew $");
34
35#include <machine/setjmp.h>
36#include <machine/param.h>
37#include <machine/vmparam.h>
38
39#include "assym.s"
40
41/*
42 * One of the fu* or su* functions failed, return -1.
43 */
44ENTRY(fsu_fault)
45	SET_FAULT_HANDLER(xzr, x1)	/* Reset the handler function */
46	EXIT_USER_ACCESS_CHECK(w0, x1)
47fsu_fault_nopcb:
48	mov	x0, #-1
49	ret
50END(fsu_fault)
51
52/*
53 * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
54 */
55ENTRY(casueword32)
56	ldr	x4, =(VM_MAXUSER_ADDRESS-3)
57	cmp	x0, x4
58	b.cs	fsu_fault_nopcb
59	adr	x6, fsu_fault		/* Load the fault handler */
60	SET_FAULT_HANDLER(x6, x4)	/* And set it */
61	ENTER_USER_ACCESS(w6, x4)
621:	ldxr	w4, [x0]		/* Load-exclusive the data */
63	cmp	w4, w1			/* Compare */
64	b.ne	2f			/* Not equal, exit */
65	stxr	w5, w3, [x0]		/* Store the new data */
66	cbnz	w5, 1b			/* Retry on failure */
67	EXIT_USER_ACCESS(w6)
682:	SET_FAULT_HANDLER(xzr, x5)	/* Reset the fault handler */
69	str	w4, [x2]		/* Store the read data */
70	mov	x0, #0			/* Success */
71	ret				/* Return */
72END(casueword32)
73
74/*
75 * int casueword(volatile u_long *, u_long, u_long *, u_long)
76 */
77ENTRY(casueword)
78	ldr	x4, =(VM_MAXUSER_ADDRESS-7)
79	cmp	x0, x4
80	b.cs	fsu_fault_nopcb
81	adr	x6, fsu_fault		/* Load the fault handler */
82	SET_FAULT_HANDLER(x6, x4)	/* And set it */
83	ENTER_USER_ACCESS(w6, x4)
841:	ldxr	x4, [x0]		/* Load-exclusive the data */
85	cmp	x4, x1			/* Compare */
86	b.ne	2f			/* Not equal, exit */
87	stxr	w5, x3, [x0]		/* Store the new data */
88	cbnz	w5, 1b			/* Retry on failure */
89	EXIT_USER_ACCESS(w6)
902:	SET_FAULT_HANDLER(xzr, x5)	/* Reset the fault handler */
91	str	x4, [x2]		/* Store the read data */
92	mov	x0, #0			/* Success */
93	ret				/* Return */
94END(casueword)
95
96/*
97 * int fubyte(volatile const void *)
98 */
99ENTRY(fubyte)
100	ldr	x1, =VM_MAXUSER_ADDRESS
101	cmp	x0, x1
102	b.cs	fsu_fault_nopcb
103	adr	x6, fsu_fault		/* Load the fault handler */
104	SET_FAULT_HANDLER(x6, x1)	/* And set it */
105	ldtrb	w0, [x0]		/* Try loading the data */
106	SET_FAULT_HANDLER(xzr, x1)	/* Reset the fault handler */
107	ret				/* Return */
108END(fubyte)
109
110/*
111 * int fuword(volatile const void *)
112 */
113ENTRY(fuword16)
114	ldr	x1, =(VM_MAXUSER_ADDRESS-1)
115	cmp	x0, x1
116	b.cs	fsu_fault_nopcb
117	adr	x6, fsu_fault		/* Load the fault handler */
118	SET_FAULT_HANDLER(x6, x1)	/* And set it */
119	ldtrh	w0, [x0]		/* Try loading the data */
120	SET_FAULT_HANDLER(xzr, x1)	/* Reset the fault handler */
121	ret				/* Return */
122END(fuword16)
123
124/*
125 * int32_t fueword32(volatile const void *, int32_t *)
126 */
127ENTRY(fueword32)
128	ldr	x2, =(VM_MAXUSER_ADDRESS-3)
129	cmp	x0, x2
130	b.cs	fsu_fault_nopcb
131	adr	x6, fsu_fault		/* Load the fault handler */
132	SET_FAULT_HANDLER(x6, x2)	/* And set it */
133	ldtr	w0, [x0]		/* Try loading the data */
134	SET_FAULT_HANDLER(xzr, x2)	/* Reset the fault handler */
135	str	w0, [x1]		/* Save the data in kernel space */
136	mov	w0, #0			/* Success */
137	ret				/* Return */
138END(fueword32)
139
140/*
141 * long fueword(volatile const void *, int64_t *)
142 * int64_t fueword64(volatile const void *, int64_t *)
143 */
144ENTRY(fueword)
145EENTRY(fueword64)
146	ldr	x2, =(VM_MAXUSER_ADDRESS-7)
147	cmp	x0, x2
148	b.cs	fsu_fault_nopcb
149	adr	x6, fsu_fault		/* Load the fault handler */
150	SET_FAULT_HANDLER(x6, x2)	/* And set it */
151	ldtr	x0, [x0]		/* Try loading the data */
152	SET_FAULT_HANDLER(xzr, x2)	/* Reset the fault handler */
153	str	x0, [x1]		/* Save the data in kernel space */
154	mov	x0, #0			/* Success */
155	ret				/* Return */
156EEND(fueword64)
157END(fueword)
158
159/*
160 * int subyte(volatile void *, int)
161 */
162ENTRY(subyte)
163	ldr	x2, =VM_MAXUSER_ADDRESS
164	cmp	x0, x2
165	b.cs	fsu_fault_nopcb
166	adr	x6, fsu_fault		/* Load the fault handler */
167	SET_FAULT_HANDLER(x6, x2)	/* And set it */
168	sttrb	w1, [x0]		/* Try storing the data */
169	SET_FAULT_HANDLER(xzr, x2)	/* Reset the fault handler */
170	mov	x0, #0			/* Success */
171	ret				/* Return */
172END(subyte)
173
174/*
175 * int suword16(volatile void *, int)
176 */
177ENTRY(suword16)
178	ldr	x2, =(VM_MAXUSER_ADDRESS-1)
179	cmp	x0, x2
180	b.cs	fsu_fault_nopcb
181	adr	x6, fsu_fault		/* Load the fault handler */
182	SET_FAULT_HANDLER(x6, x2)	/* And set it */
183	sttrh	w1, [x0]		/* Try storing the data */
184	SET_FAULT_HANDLER(xzr, x2)	/* Reset the fault handler */
185	mov	x0, #0			/* Success */
186	ret				/* Return */
187END(suword16)
188
189/*
190 * int suword32(volatile void *, int)
191 */
192ENTRY(suword32)
193	ldr	x2, =(VM_MAXUSER_ADDRESS-3)
194	cmp	x0, x2
195	b.cs	fsu_fault_nopcb
196	adr	x6, fsu_fault		/* Load the fault handler */
197	SET_FAULT_HANDLER(x6, x2)	/* And set it */
198	sttr	w1, [x0]		/* Try storing the data */
199	SET_FAULT_HANDLER(xzr, x2)	/* Reset the fault handler */
200	mov	x0, #0			/* Success */
201	ret				/* Return */
202END(suword32)
203
204/*
205 * int suword(volatile void *, long)
206 */
207ENTRY(suword)
208EENTRY(suword64)
209	ldr	x2, =(VM_MAXUSER_ADDRESS-7)
210	cmp	x0, x2
211	b.cs	fsu_fault_nopcb
212	adr	x6, fsu_fault		/* Load the fault handler */
213	SET_FAULT_HANDLER(x6, x2)	/* And set it */
214	sttr	x1, [x0]		/* Try storing the data */
215	SET_FAULT_HANDLER(xzr, x2)	/* Reset the fault handler */
216	mov	x0, #0			/* Success */
217	ret				/* Return */
218EEND(suword64)
219END(suword)
220
221/*
222 * fuswintr and suswintr are just like fusword and susword except that if
223 * the page is not in memory or would cause a trap, then we return an error.
224 * The important thing is to prevent sleep() and switch().
225 */
226
227/*
228 * Special handler so the trap code knows not to sleep.
229 */
230ENTRY(fsu_intr_fault)
231	SET_FAULT_HANDLER(xzr, x1)	/* Reset the handler function */
232	EXIT_USER_ACCESS_CHECK(w0, x1)
233	mov	x0, #-1
234	ret
235END(fsu_fault)
236
237/*
238 * int fuswintr(void *)
239 */
240ENTRY(fuswintr)
241	ldr	x1, =(VM_MAXUSER_ADDRESS-3)
242	cmp	x0, x1
243	b.cs	fsu_fault_nopcb
244	adr	x6, fsu_intr_fault	/* Load the fault handler */
245	SET_FAULT_HANDLER(x6, x1)	/* And set it */
246	ldtr	w0, [x0]		/* Try loading the data */
247	SET_FAULT_HANDLER(xzr, x1)	/* Reset the fault handler */
248	ret				/* Return */
249END(fuswintr)
250
251/*
252 * int suswintr(void *base, int word)
253 */
254ENTRY(suswintr)
255	ldr	x2, =(VM_MAXUSER_ADDRESS-3)
256	cmp	x0, x2
257	b.cs	fsu_fault_nopcb
258	adr	x6, fsu_intr_fault	/* Load the fault handler */
259	SET_FAULT_HANDLER(x6, x2)	/* And set it */
260	sttr	w1, [x0]		/* Try storing the data */
261	SET_FAULT_HANDLER(xzr, x2)	/* Reset the fault handler */
262	mov	x0, #0			/* Success */
263	ret				/* Return */
264END(suswintr)
265
266ENTRY(setjmp)
267	/* Store the stack pointer */
268	mov	x8, sp
269	str	x8, [x0], #8
270
271	/* Store the general purpose registers and lr */
272	stp	x19, x20, [x0], #16
273	stp	x21, x22, [x0], #16
274	stp	x23, x24, [x0], #16
275	stp	x25, x26, [x0], #16
276	stp	x27, x28, [x0], #16
277	stp	x29, lr, [x0], #16
278
279	/* Return value */
280	mov	x0, #0
281	ret
282END(setjmp)
283
284ENTRY(longjmp)
285	/* Restore the stack pointer */
286	ldr	x8, [x0], #8
287	mov	sp, x8
288
289	/* Restore the general purpose registers and lr */
290	ldp	x19, x20, [x0], #16
291	ldp	x21, x22, [x0], #16
292	ldp	x23, x24, [x0], #16
293	ldp	x25, x26, [x0], #16
294	ldp	x27, x28, [x0], #16
295	ldp	x29, lr, [x0], #16
296
297	/* Load the return value */
298	mov	x0, x1
299	ret
300END(longjmp)
301
302/*
303 * pagezero, simple implementation
304 */
305ENTRY(pagezero_simple)
306	add	x1, x0, #PAGE_SIZE
307
3081:
309	stp	xzr, xzr, [x0], #0x10
310	stp	xzr, xzr, [x0], #0x10
311	stp	xzr, xzr, [x0], #0x10
312	stp	xzr, xzr, [x0], #0x10
313	cmp	x0, x1
314	b.ne	1b
315	ret
316
317END(pagezero_simple)
318
319/*
320 * pagezero, cache assisted
321 */
322ENTRY(pagezero_cache)
323	add	x1, x0, #PAGE_SIZE
324
325	ldr	x2, =dczva_line_size
326	ldr	x2, [x2]
327
3281:
329	dc	zva, x0
330	add	x0, x0, x2
331	cmp	x0, x1
332	b.ne	1b
333	ret
334
335END(pagezero_cache)
336