]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/support.S
arm64: Comment out some ID registers
[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 #include <machine/param.h>
37 #include <machine/vmparam.h>
38
39 #include "assym.inc"
40
41 .macro check_user_access user_arg, limit, bad_addr_func
42         ldr     x7, =(\limit)
43         cmp     x\user_arg, x7
44         b.cs    \bad_addr_func
45 .endm
46
47 /*
48  * One of the fu* or su* functions failed, return -1.
49  */
50 ENTRY(fsu_fault)
51         SET_FAULT_HANDLER(xzr, x1)      /* Reset the handler function */
52         EXIT_USER_ACCESS_CHECK(w0, x1)
53 fsu_fault_nopcb:
54         mov     x0, #-1
55         ret
56 END(fsu_fault)
57
58 /*
59  * int swapueword8_llsc(volatile uint8_t *, uint8_t *)
60  */
61 ENTRY(swapueword8_llsc)
62         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
63         adr     x6, fsu_fault           /* Load the fault handler */
64         SET_FAULT_HANDLER(x6, x4)       /* And set it */
65         ENTER_USER_ACCESS(w6, x4)
66
67         ldrb    w7, [x1]
68
69         ldxrb   w2, [x0]
70         stxrb   w3, w7, [x0]
71         cbnz    w3, 1f
72
73         strb    w2, [x1]                /* Stash old value in *val */
74
75 1:      EXIT_USER_ACCESS(w6)
76         SET_FAULT_HANDLER(xzr, x6)
77         mov     w0, w3
78         ret
79 END(swapueword8_llsc)
80
81 /*
82  * int swapueword8_lse(volatile uint8_t *, uint8_t *)
83  */
84 ENTRY(swapueword8_lse)
85         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
86         adr     x6, fsu_fault           /* Load the fault handler */
87         SET_FAULT_HANDLER(x6, x4)       /* And set it */
88         ENTER_USER_ACCESS(w6, x4)
89
90         ldrb    w7, [x1]
91
92         .arch_extension lse
93         swpb    w7, w2, [x0]
94         .arch_extension nolse
95
96         strb    w2, [x1]                /* Stash old value in *val */
97
98         EXIT_USER_ACCESS(w6)
99         SET_FAULT_HANDLER(xzr, x6)
100         mov     w0, #0
101         ret
102 END(swapueword8_lse)
103
104 /*
105  * int swapueword32_llsc(volatile uint32_t *, uint32_t *)
106  */
107 ENTRY(swapueword32_llsc)
108         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
109         adr     x6, fsu_fault           /* Load the fault handler */
110         SET_FAULT_HANDLER(x6, x4)       /* And set it */
111         ENTER_USER_ACCESS(w6, x4)
112
113         ldr     w7, [x1]
114
115         ldxr    w2, [x0]                /* Stash the old value in w2 */
116         stxr    w3, w7, [x0]            /* Store new value */
117         cbnz    w3, 1f
118
119         str     w2, [x1]                /* Stash old value in *val */
120
121 1:      EXIT_USER_ACCESS(w6)
122         SET_FAULT_HANDLER(xzr, x6)
123         mov     w0, w3
124         ret
125 END(swapueword32_llsc)
126
127 /*
128  * int swapueword32_lse(volatile uint32_t *, uint32_t *)
129  */
130 ENTRY(swapueword32_lse)
131         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
132         adr     x6, fsu_fault           /* Load the fault handler */
133         SET_FAULT_HANDLER(x6, x4)       /* And set it */
134         ENTER_USER_ACCESS(w6, x4)
135
136         ldr     w7, [x1]
137
138         .arch_extension lse
139         swp     w7, w2, [x0]
140         .arch_extension nolse
141
142         str     w2, [x1]                /* Stash old value in *val */
143
144         EXIT_USER_ACCESS(w6)
145         SET_FAULT_HANDLER(xzr, x6)
146         mov     w0, #0
147         ret
148 END(swapueword32_llsc)
149
150 /*
151  * int casueword32_llsc(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
152  */
153 ENTRY(casueword32_llsc)
154         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
155         adr     x6, fsu_fault           /* Load the fault handler */
156         mov     w5, #1
157         SET_FAULT_HANDLER(x6, x4)       /* And set it */
158         ENTER_USER_ACCESS(w6, x4)
159         ldxr    w4, [x0]                /* Load-exclusive the data */
160         cmp     w4, w1                  /* Compare */
161         b.ne    1f                      /* Not equal, exit */
162         stxr    w5, w3, [x0]            /* Store the new data */
163 1:      EXIT_USER_ACCESS(w6)
164         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
165         str     w4, [x2]                /* Store the read data */
166         mov     w0, w5                  /* Result same as store status */
167         ret                             /* Return */
168 END(casueword32_llsc)
169
170 /*
171  * int casueword32_lse(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
172  */
173 ENTRY(casueword32_lse)
174         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
175         adr     x6, fsu_fault           /* Load the fault handler */
176         SET_FAULT_HANDLER(x6, x4)       /* And set it */
177         ENTER_USER_ACCESS(w6, x4)
178         mov     w7, w1                  /* Back up the compare value */
179         .arch_extension lse
180         cas     w1, w3, [x0]            /* Compare and Swap */
181         .arch_extension nolse
182         cmp     w1, w7                  /* Check if successful */
183         cset    w0, ne                  /* Return 0 on success, 1 on failure */
184         EXIT_USER_ACCESS(w6)
185         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
186         str     w1, [x2]                /* Store the read data */
187         ret                             /* Return */
188 END(casueword32_lse)
189
190 /*
191  * int casueword_llsc(volatile u_long *, u_long, u_long *, u_long)
192  */
193 ENTRY(casueword_llsc)
194         check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
195         adr     x6, fsu_fault           /* Load the fault handler */
196         mov     w5, #1
197         SET_FAULT_HANDLER(x6, x4)       /* And set it */
198         ENTER_USER_ACCESS(w6, x4)
199         ldxr    x4, [x0]                /* Load-exclusive the data */
200         cmp     x4, x1                  /* Compare */
201         b.ne    1f                      /* Not equal, exit */
202         stxr    w5, x3, [x0]            /* Store the new data */
203 1:      EXIT_USER_ACCESS(w6)
204         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
205         str     x4, [x2]                /* Store the read data */
206         mov     w0, w5                  /* Result same as store status */
207         ret                             /* Return */
208 END(casueword_llsc)
209
210 /*
211  * int casueword_lse(volatile u_long *, u_long, u_long *, u_long)
212  */
213 ENTRY(casueword_lse)
214         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
215         adr     x6, fsu_fault           /* Load the fault handler */
216         SET_FAULT_HANDLER(x6, x4)       /* And set it */
217         ENTER_USER_ACCESS(w6, x4)
218         mov     x7, x1                  /* Back up the compare value */
219         .arch_extension lse
220         cas     x1, x3, [x0]            /* Compare and Swap */
221         .arch_extension nolse
222         cmp     x1, x7                  /* Check if successful */
223         cset    w0, ne                  /* Return 0 on success, 1 on failure */
224         EXIT_USER_ACCESS(w6)
225         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
226         str     x1, [x2]                /* Store the read data */
227         ret                             /* Return */
228 END(casueword_lse)
229
230 .macro fsudata insn, ret_reg, user_arg
231         adr     x7, fsu_fault           /* Load the fault handler */
232         SET_FAULT_HANDLER(x7, x6)       /* And set it */
233         \insn   \ret_reg, [x\user_arg]  /* Try accessing the data */
234         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
235 .endm
236
237 /*
238  * int fubyte(volatile const void *)
239  */
240 ENTRY(fubyte)
241         check_user_access 0, (VM_MAXUSER_ADDRESS), fsu_fault_nopcb
242         fsudata ldtrb, w0, 0
243         ret                             /* Return */
244 END(fubyte)
245
246 /*
247  * int fuword(volatile const void *)
248  */
249 ENTRY(fuword16)
250         check_user_access 0, (VM_MAXUSER_ADDRESS-1), fsu_fault_nopcb
251         fsudata ldtrh, w0, 0
252         ret                             /* Return */
253 END(fuword16)
254
255 /*
256  * int32_t fueword32(volatile const void *, int32_t *)
257  */
258 ENTRY(fueword32)
259         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
260         fsudata ldtr, w0, 0
261         str     w0, [x1]                /* Save the data in kernel space */
262         mov     w0, #0                  /* Success */
263         ret                             /* Return */
264 END(fueword32)
265
266 /*
267  * long fueword(volatile const void *, int64_t *)
268  * int64_t fueword64(volatile const void *, int64_t *)
269  */
270 EENTRY(fueword64)
271 ENTRY(fueword)
272         check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
273         fsudata ldtr, x0, 0
274         str     x0, [x1]                /* Save the data in kernel space */
275         mov     x0, #0                  /* Success */
276         ret                             /* Return */
277 END(fueword)
278 EEND(fueword64)
279
280 /*
281  * int subyte(volatile void *, int)
282  */
283 ENTRY(subyte)
284         check_user_access 0, (VM_MAXUSER_ADDRESS), fsu_fault_nopcb
285         fsudata sttrb, w1, 0
286         mov     x0, #0                  /* Success */
287         ret                             /* Return */
288 END(subyte)
289
290 /*
291  * int suword16(volatile void *, int)
292  */
293 ENTRY(suword16)
294         check_user_access 0, (VM_MAXUSER_ADDRESS-1), fsu_fault_nopcb
295         fsudata sttrh, w1, 0
296         mov     x0, #0                  /* Success */
297         ret                             /* Return */
298 END(suword16)
299
300 /*
301  * int suword32(volatile void *, int)
302  */
303 ENTRY(suword32)
304         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
305         fsudata sttr, w1, 0
306         mov     x0, #0                  /* Success */
307         ret                             /* Return */
308 END(suword32)
309
310 /*
311  * int suword(volatile void *, long)
312  */
313 EENTRY(suword64)
314 ENTRY(suword)
315         check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
316         fsudata sttr, x1, 0
317         mov     x0, #0                  /* Success */
318         ret                             /* Return */
319 END(suword)
320 EEND(suword64)
321
322 ENTRY(setjmp)
323         /* Store the stack pointer */
324         mov     x8, sp
325         str     x8, [x0], #8
326
327         /* Store the general purpose registers and lr */
328         stp     x19, x20, [x0], #16
329         stp     x21, x22, [x0], #16
330         stp     x23, x24, [x0], #16
331         stp     x25, x26, [x0], #16
332         stp     x27, x28, [x0], #16
333         stp     x29, lr, [x0], #16
334
335         /* Return value */
336         mov     x0, #0
337         ret
338 END(setjmp)
339
340 ENTRY(longjmp)
341         /* Restore the stack pointer */
342         ldr     x8, [x0], #8
343         mov     sp, x8
344
345         /* Restore the general purpose registers and lr */
346         ldp     x19, x20, [x0], #16
347         ldp     x21, x22, [x0], #16
348         ldp     x23, x24, [x0], #16
349         ldp     x25, x26, [x0], #16
350         ldp     x27, x28, [x0], #16
351         ldp     x29, lr, [x0], #16
352
353         /* Load the return value */
354         mov     x0, x1
355         ret
356 END(longjmp)
357
358 /*
359  * pagezero, simple implementation
360  */
361 ENTRY(pagezero_simple)
362         add     x1, x0, #PAGE_SIZE
363
364 1:
365         stp     xzr, xzr, [x0], #0x10
366         stp     xzr, xzr, [x0], #0x10
367         stp     xzr, xzr, [x0], #0x10
368         stp     xzr, xzr, [x0], #0x10
369         cmp     x0, x1
370         b.ne    1b
371         ret
372
373 END(pagezero_simple)
374
375 /*
376  * pagezero, cache assisted
377  */
378 ENTRY(pagezero_cache)
379         add     x1, x0, #PAGE_SIZE
380
381         ldr     x2, =dczva_line_size
382         ldr     x2, [x2]
383
384 1:
385         dc      zva, x0
386         add     x0, x0, x2
387         cmp     x0, x1
388         b.ne    1b
389         ret
390
391 END(pagezero_cache)