]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/support.S
MFV r289003:
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / support.S
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$");
34
35 #include <machine/setjmp.h>
36
37 #include "assym.s"
38
39 /*
40  * One of the fu* or su* functions failed, return -1.
41  */
42 ENTRY(fsu_fault)
43         SET_FAULT_HANDLER(xzr, x1)      /* Reset the handler function */
44 fsu_fault_nopcb:
45         mov     x0, #-1
46         ret
47 END(fsu_fault)
48
49 /*
50  * int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
51  */
52 ENTRY(casueword32)
53         ldr     x4, =(VM_MAXUSER_ADDRESS-3)
54         cmp     x0, x4
55         b.cs    fsu_fault_nopcb
56         adr     x6, fsu_fault           /* Load the fault handler */
57         SET_FAULT_HANDLER(x6, x4)       /* And set it */
58 1:      ldxr    w4, [x0]                /* Load-exclusive the data */
59         cmp     w4, w1                  /* Compare */
60         b.ne    2f                      /* Not equal, exit */
61         stxr    w5, w3, [x0]            /* Store the new data */
62         cbnz    w5, 1b                  /* Retry on failure */
63 2:      SET_FAULT_HANDLER(xzr, x5)      /* Reset the fault handler */
64         str     w4, [x2]                /* Store the read data */
65         mov     x0, #0                  /* Success */
66         ret                             /* Return */
67 END(casueword32)
68
69 /*
70  * int casueword(volatile u_long *, u_long, u_long *, u_long)
71  */
72 ENTRY(casueword)
73         ldr     x4, =(VM_MAXUSER_ADDRESS-7)
74         cmp     x0, x4
75         b.cs    fsu_fault_nopcb
76         adr     x6, fsu_fault           /* Load the fault handler */
77         SET_FAULT_HANDLER(x6, x4)       /* And set it */
78 1:      ldxr    x4, [x0]                /* Load-exclusive the data */
79         cmp     x4, x1                  /* Compare */
80         b.ne    2f                      /* Not equal, exit */
81         stxr    w5, x3, [x0]            /* Store the new data */
82         cbnz    w5, 1b                  /* Retry on failure */
83 2:      SET_FAULT_HANDLER(xzr, x5)      /* Reset the fault handler */
84         str     x4, [x2]                /* Store the read data */
85         mov     x0, #0                  /* Success */
86         ret                             /* Return */
87 END(casueword)
88
89 /*
90  * int fubyte(volatile const void *)
91  */
92 ENTRY(fubyte)
93         ldr     x1, =VM_MAXUSER_ADDRESS
94         cmp     x0, x1
95         b.cs    fsu_fault_nopcb
96         adr     x6, fsu_fault           /* Load the fault handler */
97         SET_FAULT_HANDLER(x6, x1)       /* And set it */
98         ldrb    w0, [x0]                /* Try loading the data */
99         SET_FAULT_HANDLER(xzr, x1)      /* Reset the fault handler */
100         ret                             /* Return */
101 END(fubyte)
102
103 /*
104  * int fuword(volatile const void *)
105  */
106 ENTRY(fuword16)
107         ldr     x1, =(VM_MAXUSER_ADDRESS-1)
108         cmp     x0, x1
109         b.cs    fsu_fault_nopcb
110         adr     x6, fsu_fault           /* Load the fault handler */
111         SET_FAULT_HANDLER(x6, x1)       /* And set it */
112         ldrh    w0, [x0]                /* Try loading the data */
113         SET_FAULT_HANDLER(xzr, x1)      /* Reset the fault handler */
114         ret                             /* Return */
115 END(fuword16)
116
117 /*
118  * int32_t fueword32(volatile const void *, int32_t *)
119  */
120 ENTRY(fueword32)
121         ldr     x2, =(VM_MAXUSER_ADDRESS-3)
122         cmp     x0, x2
123         b.cs    fsu_fault_nopcb
124         adr     x6, fsu_fault           /* Load the fault handler */
125         SET_FAULT_HANDLER(x6, x2)       /* And set it */
126         ldr     w0, [x0]                /* Try loading the data */
127         SET_FAULT_HANDLER(xzr, x2)      /* Reset the fault handler */
128         str     w0, [x1]                /* Save the data in kernel space */
129         mov     w0, #0                  /* Success */
130         ret                             /* Return */
131 END(fueword32)
132
133 /*
134  * long fueword(volatile const void *, int64_t *)
135  * int64_t fueword64(volatile const void *, int64_t *)
136  */
137 ENTRY(fueword)
138 EENTRY(fueword64)
139         ldr     x2, =(VM_MAXUSER_ADDRESS-7)
140         cmp     x0, x2
141         b.cs    fsu_fault_nopcb
142         adr     x6, fsu_fault           /* Load the fault handler */
143         SET_FAULT_HANDLER(x6, x2)       /* And set it */
144         ldr     x0, [x0]                /* Try loading the data */
145         SET_FAULT_HANDLER(xzr, x2)      /* Reset the fault handler */
146         str     x0, [x1]                /* Save the data in kernel space */
147         mov     x0, #0                  /* Success */
148         ret                             /* Return */
149 EEND(fueword64)
150 END(fueword)
151
152 /*
153  * int subyte(volatile void *, int)
154  */
155 ENTRY(subyte)
156         ldr     x2, =VM_MAXUSER_ADDRESS
157         cmp     x0, x2
158         b.cs    fsu_fault_nopcb
159         adr     x6, fsu_fault           /* Load the fault handler */
160         SET_FAULT_HANDLER(x6, x2)       /* And set it */
161         strb    w1, [x0]                /* Try storing the data */
162         SET_FAULT_HANDLER(xzr, x2)      /* Reset the fault handler */
163         mov     x0, #0                  /* Success */
164         ret                             /* Return */
165 END(subyte)
166
167 /*
168  * int suword16(volatile void *, int)
169  */
170 ENTRY(suword16)
171         ldr     x2, =(VM_MAXUSER_ADDRESS-1)
172         cmp     x0, x2
173         b.cs    fsu_fault_nopcb
174         adr     x6, fsu_fault           /* Load the fault handler */
175         SET_FAULT_HANDLER(x6, x2)       /* And set it */
176         strh    w1, [x0]                /* Try storing the data */
177         SET_FAULT_HANDLER(xzr, x2)      /* Reset the fault handler */
178         mov     x0, #0                  /* Success */
179         ret                             /* Return */
180 END(suword16)
181
182 /*
183  * int suword32(volatile void *, int)
184  */
185 ENTRY(suword32)
186         ldr     x2, =(VM_MAXUSER_ADDRESS-3)
187         cmp     x0, x2
188         b.cs    fsu_fault_nopcb
189         adr     x6, fsu_fault           /* Load the fault handler */
190         SET_FAULT_HANDLER(x6, x2)       /* And set it */
191         str     w1, [x0]                /* Try storing the data */
192         SET_FAULT_HANDLER(xzr, x2)      /* Reset the fault handler */
193         mov     x0, #0                  /* Success */
194         ret                             /* Return */
195 END(suword32)
196
197 /*
198  * int suword(volatile void *, long)
199  */
200 ENTRY(suword)
201 EENTRY(suword64)
202         ldr     x2, =(VM_MAXUSER_ADDRESS-7)
203         cmp     x0, x2
204         b.cs    fsu_fault_nopcb
205         adr     x6, fsu_fault           /* Load the fault handler */
206         SET_FAULT_HANDLER(x6, x2)       /* And set it */
207         str     x1, [x0]                /* Try storing the data */
208         SET_FAULT_HANDLER(xzr, x2)      /* Reset the fault handler */
209         mov     x0, #0                  /* Success */
210         ret                             /* Return */
211 EEND(suword64)
212 END(suword)
213
214 /*
215  * fuswintr and suswintr are just like fusword and susword except that if
216  * the page is not in memory or would cause a trap, then we return an error.
217  * The important thing is to prevent sleep() and switch().
218  */
219
220 /*
221  * Special handler so the trap code knows not to sleep.
222  */
223 ENTRY(fsu_intr_fault)
224         SET_FAULT_HANDLER(xzr, x1)      /* Reset the handler function */
225         mov     x0, #-1
226         ret
227 END(fsu_fault)
228
229 /*
230  * int fuswintr(void *)
231  */
232 ENTRY(fuswintr)
233         ldr     x1, =(VM_MAXUSER_ADDRESS-3)
234         cmp     x0, x1
235         b.cs    fsu_fault_nopcb
236         adr     x6, fsu_intr_fault      /* Load the fault handler */
237         SET_FAULT_HANDLER(x6, x1)       /* And set it */
238         ldr     w0, [x0]                /* Try loading the data */
239         SET_FAULT_HANDLER(xzr, x1)      /* Reset the fault handler */
240         ret                             /* Return */
241 END(fuswintr)
242
243 /*
244  * int suswintr(void *base, int word)
245  */
246 ENTRY(suswintr)
247         ldr     x2, =(VM_MAXUSER_ADDRESS-3)
248         cmp     x0, x2
249         b.cs    fsu_fault_nopcb
250         adr     x6, fsu_intr_fault      /* Load the fault handler */
251         SET_FAULT_HANDLER(x6, x2)       /* And set it */
252         str     w1, [x0]                /* Try storing the data */
253         SET_FAULT_HANDLER(xzr, x2)      /* Reset the fault handler */
254         mov     x0, #0                  /* Success */
255         ret                             /* Return */
256 END(suswintr)
257
258 ENTRY(setjmp)
259         /* Store the stack pointer */
260         mov     x8, sp
261         str     x8, [x0], #8
262
263         /* Store the general purpose registers and lr */
264         stp     x19, x20, [x0], #16
265         stp     x21, x22, [x0], #16
266         stp     x23, x24, [x0], #16
267         stp     x25, x26, [x0], #16
268         stp     x27, x28, [x0], #16
269         stp     x29, lr, [x0], #16
270
271         /* Return value */
272         mov     x0, #0
273         ret
274 END(setjmp)
275
276 ENTRY(longjmp)
277         /* Restore the stack pointer */
278         ldr     x8, [x0], #8
279         mov     sp, x8
280
281         /* Restore the general purpose registers and lr */
282         ldp     x19, x20, [x0], #16
283         ldp     x21, x22, [x0], #16
284         ldp     x23, x24, [x0], #16
285         ldp     x25, x26, [x0], #16
286         ldp     x27, x28, [x0], #16
287         ldp     x29, lr, [x0], #16
288
289         /* Load the return value */
290         mov     x0, x1
291         ret
292 END(longjmp)