xref: /freebsd/sys/riscv/riscv/support.S (revision d6b92ffa)
1/*-
2 * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
3 * All rights reserved.
4 *
5 * Portions of this software were developed by SRI International and the
6 * University of Cambridge Computer Laboratory under DARPA/AFRL contract
7 * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
8 *
9 * Portions of this software were developed by the University of Cambridge
10 * Computer Laboratory as part of the CTSRD Project, with support from the
11 * UK Higher Education Innovation Fund (HEIF).
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <machine/asm.h>
36__FBSDID("$FreeBSD$");
37
38#include <machine/setjmp.h>
39
40#include "assym.s"
41
42/*
43 * One of the fu* or su* functions failed, return -1.
44 */
45ENTRY(fsu_fault)
46	SET_FAULT_HANDLER(x0, a1)	/* Reset the handler function */
47fsu_fault_nopcb:
48	li	a0, -1
49	ret
50END(fsu_fault)
51
52/*
53 * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
54 */
55ENTRY(casueword32)
56	li	a4, (VM_MAXUSER_ADDRESS-3)
57	bgt	a0, a4, fsu_fault_nopcb
58	la	a6, fsu_fault		/* Load the fault handler */
59	SET_FAULT_HANDLER(a6, a4)	/* And set it */
601:	lr.w	a4, 0(a0)		/* Load-exclusive the data */
61	bne	a4, a1, 2f		/* If not equal then exit */
62	sc.w	a5, a3, 0(a0)		/* Store the new data */
63	bnez	a5, 1b			/* Retry on failure */
642:	SET_FAULT_HANDLER(x0, a5)	/* Reset the fault handler */
65	sw	a4, 0(a2)		/* Store the read data */
66	li	a0, 0			/* Success */
67	ret				/* Return */
68END(casueword32)
69
70/*
71 * int casueword(volatile u_long *, u_long, u_long *, u_long)
72 */
73ENTRY(casueword)
74	li	a4, (VM_MAXUSER_ADDRESS-7)
75	bgt	a0, a4, fsu_fault_nopcb
76	la	a6, fsu_fault		/* Load the fault handler */
77	SET_FAULT_HANDLER(a6, a4)	/* And set it */
781:	lr.d	a4, 0(a0)		/* Load-exclusive the data */
79	bne	a4, a1, 2f		/* If not equal then exit */
80	sc.d	a5, a3, 0(a0)		/* Store the new data */
81	bnez	a5, 1b			/* Retry on failure */
822:	SET_FAULT_HANDLER(x0, a5)	/* Reset the fault handler */
83	sd	a4, 0(a2)		/* Store the read data */
84	li	a0, 0			/* Success */
85	ret				/* Return */
86END(casueword)
87
88/*
89 * int fubyte(volatile const void *)
90 */
91ENTRY(fubyte)
92	li	a1, VM_MAXUSER_ADDRESS
93	bgt	a0, a1, fsu_fault_nopcb
94	la	a6, fsu_fault		/* Load the fault handler */
95	SET_FAULT_HANDLER(a6, a1)	/* And set it */
96	lb	a0, 0(a0)		/* Try loading the data */
97	SET_FAULT_HANDLER(x0, a1)	/* Reset the fault handler */
98	ret				/* Return */
99END(fubyte)
100
101/*
102 * int fuword(volatile const void *)
103 */
104ENTRY(fuword16)
105	li	a1, (VM_MAXUSER_ADDRESS-1)
106	bgt	a0, a1, fsu_fault_nopcb
107	la	a6, fsu_fault		/* Load the fault handler */
108	SET_FAULT_HANDLER(a6, a1)	/* And set it */
109	lh	a0, 0(a0)		/* Try loading the data */
110	SET_FAULT_HANDLER(x0, a1)	/* Reset the fault handler */
111	ret				/* Return */
112END(fuword16)
113
114/*
115 * int32_t fueword32(volatile const void *, int32_t *)
116 */
117ENTRY(fueword32)
118	li	a2, (VM_MAXUSER_ADDRESS-3)
119	bgt	a0, a2, fsu_fault_nopcb
120	la	a6, fsu_fault		/* Load the fault handler */
121	SET_FAULT_HANDLER(a6, a2)	/* And set it */
122	lw	a0, 0(a0)		/* Try loading the data */
123	SET_FAULT_HANDLER(x0, a2)	/* Reset the fault handler */
124	sw	a0, 0(a1)		/* Save the data in kernel space */
125	li	a0, 0			/* Success */
126	ret				/* Return */
127END(fueword32)
128
129/*
130 * long fueword(volatile const void *, int64_t *)
131 * int64_t fueword64(volatile const void *, int64_t *)
132 */
133ENTRY(fueword)
134EENTRY(fueword64)
135	li	a2, (VM_MAXUSER_ADDRESS-7)
136	bgt	a0, a2, fsu_fault_nopcb
137	la	a6, fsu_fault		/* Load the fault handler */
138	SET_FAULT_HANDLER(a6, a2)	/* And set it */
139	ld	a0, 0(a0)		/* Try loading the data */
140	SET_FAULT_HANDLER(x0, a2)	/* Reset the fault handler */
141	sd	a0, 0(a1)		/* Save the data in kernel space */
142	li	a0, 0			/* Success */
143	ret				/* Return */
144EEND(fueword64)
145END(fueword)
146
147/*
148 * int subyte(volatile void *, int)
149 */
150ENTRY(subyte)
151	li	a2, VM_MAXUSER_ADDRESS
152	bgt	a0, a2, fsu_fault_nopcb
153	la	a6, fsu_fault		/* Load the fault handler */
154	SET_FAULT_HANDLER(a6, a2)	/* And set it */
155	sb	a1, 0(a0)		/* Try storing the data */
156	SET_FAULT_HANDLER(x0, a2)	/* Reset the fault handler */
157	li	a0, 0			/* Success */
158	ret				/* Return */
159END(subyte)
160
161/*
162 * int suword16(volatile void *, int)
163 */
164ENTRY(suword16)
165	li	a2, (VM_MAXUSER_ADDRESS-1)
166	bgt	a0, a2, fsu_fault_nopcb
167	la	a6, fsu_fault		/* Load the fault handler */
168	SET_FAULT_HANDLER(a6, a2)	/* And set it */
169	sh	a1, 0(a0)		/* Try storing the data */
170	SET_FAULT_HANDLER(x0, a2)	/* Reset the fault handler */
171	li	a0, 0			/* Success */
172	ret				/* Return */
173END(suword16)
174
175/*
176 * int suword32(volatile void *, int)
177 */
178ENTRY(suword32)
179	li	a2, (VM_MAXUSER_ADDRESS-3)
180	bgt	a0, a2, fsu_fault_nopcb
181	la	a6, fsu_fault		/* Load the fault handler */
182	SET_FAULT_HANDLER(a6, a2)	/* And set it */
183	sw	a1, 0(a0)		/* Try storing the data */
184	SET_FAULT_HANDLER(x0, a2)	/* Reset the fault handler */
185	li	a0, 0			/* Success */
186	ret				/* Return */
187END(suword32)
188
189/*
190 * int suword(volatile void *, long)
191 */
192ENTRY(suword)
193EENTRY(suword64)
194	li	a2, (VM_MAXUSER_ADDRESS-7)
195	bgt	a0, a2, fsu_fault_nopcb
196	la	a6, fsu_fault		/* Load the fault handler */
197	SET_FAULT_HANDLER(a6, a2)	/* And set it */
198	sd	a1, 0(a0)		/* Try storing the data */
199	SET_FAULT_HANDLER(x0, a2)	/* Reset the fault handler */
200	li	a0, 0			/* Success */
201	ret				/* Return */
202EEND(suword64)
203END(suword)
204
205/*
206 * fuswintr and suswintr are just like fusword and susword except that if
207 * the page is not in memory or would cause a trap, then we return an error.
208 * The important thing is to prevent sleep() and switch().
209 */
210
211/*
212 * Special handler so the trap code knows not to sleep.
213 */
214ENTRY(fsu_intr_fault)
215	SET_FAULT_HANDLER(x0, a1)	/* Reset the handler function */
216	li	a0, -1
217	ret
218END(fsu_fault)
219
220/*
221 * int fuswintr(void *)
222 */
223ENTRY(fuswintr)
224	li	a1, (VM_MAXUSER_ADDRESS-3)
225	bgt	a0, a1, fsu_fault_nopcb
226	la	a6, fsu_intr_fault	/* Load the fault handler */
227	SET_FAULT_HANDLER(a6, a1)	/* And set it */
228	lw	a0, 0(a0)		/* Try loading the data */
229	SET_FAULT_HANDLER(x0, x1)	/* Reset the fault handler */
230	ret				/* Return */
231END(fuswintr)
232
233/*
234 * int suswintr(void *base, int word)
235 */
236ENTRY(suswintr)
237	li	a2, (VM_MAXUSER_ADDRESS-3)
238	bgt	a0, a2, fsu_fault_nopcb
239	la	a6, fsu_intr_fault	/* Load the fault handler */
240	SET_FAULT_HANDLER(a6, a2)	/* And set it */
241	sw	a1, 0(a0)		/* Try storing the data */
242	SET_FAULT_HANDLER(x0, a2)	/* Reset the fault handler */
243	li	a0, 0			/* Success */
244	ret				/* Return */
245END(suswintr)
246
247ENTRY(setjmp)
248	/* Store the stack pointer */
249	sd	sp, 0(a0)
250	addi	a0, a0, 8
251
252	/* Store the general purpose registers and ra */
253	sd	s0, (0 * 8)(a0)
254	sd	s1, (1 * 8)(a0)
255	sd	s2, (2 * 8)(a0)
256	sd	s3, (3 * 8)(a0)
257	sd	s4, (4 * 8)(a0)
258	sd	s5, (5 * 8)(a0)
259	sd	s6, (6 * 8)(a0)
260	sd	s7, (7 * 8)(a0)
261	sd	s8, (8 * 8)(a0)
262	sd	s9, (9 * 8)(a0)
263	sd	s10, (10 * 8)(a0)
264	sd	s11, (11 * 8)(a0)
265	sd	ra, (12 * 8)(a0)
266
267	/* Return value */
268	li	a0, 0
269	ret
270END(setjmp)
271
272ENTRY(longjmp)
273	/* Restore the stack pointer */
274	ld	sp, 0(a0)
275	addi	a0, a0, 8
276
277	/* Restore the general purpose registers and ra */
278	ld	s0, (0 * 8)(a0)
279	ld	s1, (1 * 8)(a0)
280	ld	s2, (2 * 8)(a0)
281	ld	s3, (3 * 8)(a0)
282	ld	s4, (4 * 8)(a0)
283	ld	s5, (5 * 8)(a0)
284	ld	s6, (6 * 8)(a0)
285	ld	s7, (7 * 8)(a0)
286	ld	s8, (8 * 8)(a0)
287	ld	s9, (9 * 8)(a0)
288	ld	s10, (10 * 8)(a0)
289	ld	s11, (11 * 8)(a0)
290	ld	ra, (12 * 8)(a0)
291
292	/* Load the return value */
293	mv	a0, a1
294	ret
295END(longjmp)
296