xref: /freebsd/sys/riscv/riscv/support.S (revision 4928135658a9d0eaee37003df6137ab363fcb0b4)
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.inc"
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
205ENTRY(setjmp)
206	/* Store the stack pointer */
207	sd	sp, 0(a0)
208	addi	a0, a0, 8
209
210	/* Store the general purpose registers and ra */
211	sd	s0, (0 * 8)(a0)
212	sd	s1, (1 * 8)(a0)
213	sd	s2, (2 * 8)(a0)
214	sd	s3, (3 * 8)(a0)
215	sd	s4, (4 * 8)(a0)
216	sd	s5, (5 * 8)(a0)
217	sd	s6, (6 * 8)(a0)
218	sd	s7, (7 * 8)(a0)
219	sd	s8, (8 * 8)(a0)
220	sd	s9, (9 * 8)(a0)
221	sd	s10, (10 * 8)(a0)
222	sd	s11, (11 * 8)(a0)
223	sd	ra, (12 * 8)(a0)
224
225	/* Return value */
226	li	a0, 0
227	ret
228END(setjmp)
229
230ENTRY(longjmp)
231	/* Restore the stack pointer */
232	ld	sp, 0(a0)
233	addi	a0, a0, 8
234
235	/* Restore the general purpose registers and ra */
236	ld	s0, (0 * 8)(a0)
237	ld	s1, (1 * 8)(a0)
238	ld	s2, (2 * 8)(a0)
239	ld	s3, (3 * 8)(a0)
240	ld	s4, (4 * 8)(a0)
241	ld	s5, (5 * 8)(a0)
242	ld	s6, (6 * 8)(a0)
243	ld	s7, (7 * 8)(a0)
244	ld	s8, (8 * 8)(a0)
245	ld	s9, (9 * 8)(a0)
246	ld	s10, (10 * 8)(a0)
247	ld	s11, (11 * 8)(a0)
248	ld	ra, (12 * 8)(a0)
249
250	/* Load the return value */
251	mv	a0, a1
252	ret
253END(longjmp)
254