]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/support.S
Allocate right number of pages for the bounced buffers crossing the page.
[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 casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
60  */
61 ENTRY(casueword32)
62         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
63         adr     x6, fsu_fault           /* Load the fault handler */
64         mov     w5, #1
65         SET_FAULT_HANDLER(x6, x4)       /* And set it */
66         ENTER_USER_ACCESS(w6, x4)
67         ldxr    w4, [x0]                /* Load-exclusive the data */
68         cmp     w4, w1                  /* Compare */
69         b.ne    1f                      /* Not equal, exit */
70         stxr    w5, w3, [x0]            /* Store the new data */
71 1:      EXIT_USER_ACCESS(w6)
72         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
73         str     w4, [x2]                /* Store the read data */
74         mov     w0, w5                  /* Result same as store status */
75         ret                             /* Return */
76 END(casueword32)
77
78 /*
79  * int casueword(volatile u_long *, u_long, u_long *, u_long)
80  */
81 ENTRY(casueword)
82         check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
83         adr     x6, fsu_fault           /* Load the fault handler */
84         mov     w5, #1
85         SET_FAULT_HANDLER(x6, x4)       /* And set it */
86         ENTER_USER_ACCESS(w6, x4)
87         ldxr    x4, [x0]                /* Load-exclusive the data */
88         cmp     x4, x1                  /* Compare */
89         b.ne    1f                      /* Not equal, exit */
90         stxr    w5, x3, [x0]            /* Store the new data */
91 1:      EXIT_USER_ACCESS(w6)
92         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
93         str     x4, [x2]                /* Store the read data */
94         mov     w0, w5                  /* Result same as store status */
95         ret                             /* Return */
96 END(casueword)
97
98 .macro fsudata insn, ret_reg, user_arg
99         adr     x7, fsu_fault           /* Load the fault handler */
100         SET_FAULT_HANDLER(x7, x6)       /* And set it */
101         \insn   \ret_reg, [x\user_arg]  /* Try accessing the data */
102         SET_FAULT_HANDLER(xzr, x6)      /* Reset the fault handler */
103 .endm
104
105 /*
106  * int fubyte(volatile const void *)
107  */
108 ENTRY(fubyte)
109         check_user_access 0, (VM_MAXUSER_ADDRESS), fsu_fault_nopcb
110         fsudata ldtrb, w0, 0
111         ret                             /* Return */
112 END(fubyte)
113
114 /*
115  * int fuword(volatile const void *)
116  */
117 ENTRY(fuword16)
118         check_user_access 0, (VM_MAXUSER_ADDRESS-1), fsu_fault_nopcb
119         fsudata ldtrh, w0, 0
120         ret                             /* Return */
121 END(fuword16)
122
123 /*
124  * int32_t fueword32(volatile const void *, int32_t *)
125  */
126 ENTRY(fueword32)
127         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
128         fsudata ldtr, w0, 0
129         str     w0, [x1]                /* Save the data in kernel space */
130         mov     w0, #0                  /* Success */
131         ret                             /* Return */
132 END(fueword32)
133
134 /*
135  * long fueword(volatile const void *, int64_t *)
136  * int64_t fueword64(volatile const void *, int64_t *)
137  */
138 ENTRY(fueword)
139 EENTRY(fueword64)
140         check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
141         fsudata ldtr, x0, 0
142         str     x0, [x1]                /* Save the data in kernel space */
143         mov     x0, #0                  /* Success */
144         ret                             /* Return */
145 EEND(fueword64)
146 END(fueword)
147
148 /*
149  * int subyte(volatile void *, int)
150  */
151 ENTRY(subyte)
152         check_user_access 0, (VM_MAXUSER_ADDRESS), fsu_fault_nopcb
153         fsudata sttrb, w1, 0
154         mov     x0, #0                  /* Success */
155         ret                             /* Return */
156 END(subyte)
157
158 /*
159  * int suword16(volatile void *, int)
160  */
161 ENTRY(suword16)
162         check_user_access 0, (VM_MAXUSER_ADDRESS-1), fsu_fault_nopcb
163         fsudata sttrh, w1, 0
164         mov     x0, #0                  /* Success */
165         ret                             /* Return */
166 END(suword16)
167
168 /*
169  * int suword32(volatile void *, int)
170  */
171 ENTRY(suword32)
172         check_user_access 0, (VM_MAXUSER_ADDRESS-3), fsu_fault_nopcb
173         fsudata sttr, w1, 0
174         mov     x0, #0                  /* Success */
175         ret                             /* Return */
176 END(suword32)
177
178 /*
179  * int suword(volatile void *, long)
180  */
181 ENTRY(suword)
182 EENTRY(suword64)
183         check_user_access 0, (VM_MAXUSER_ADDRESS-7), fsu_fault_nopcb
184         fsudata sttr, x1, 0
185         mov     x0, #0                  /* Success */
186         ret                             /* Return */
187 EEND(suword64)
188 END(suword)
189
190 ENTRY(setjmp)
191         /* Store the stack pointer */
192         mov     x8, sp
193         str     x8, [x0], #8
194
195         /* Store the general purpose registers and lr */
196         stp     x19, x20, [x0], #16
197         stp     x21, x22, [x0], #16
198         stp     x23, x24, [x0], #16
199         stp     x25, x26, [x0], #16
200         stp     x27, x28, [x0], #16
201         stp     x29, lr, [x0], #16
202
203         /* Return value */
204         mov     x0, #0
205         ret
206 END(setjmp)
207
208 ENTRY(longjmp)
209         /* Restore the stack pointer */
210         ldr     x8, [x0], #8
211         mov     sp, x8
212
213         /* Restore the general purpose registers and lr */
214         ldp     x19, x20, [x0], #16
215         ldp     x21, x22, [x0], #16
216         ldp     x23, x24, [x0], #16
217         ldp     x25, x26, [x0], #16
218         ldp     x27, x28, [x0], #16
219         ldp     x29, lr, [x0], #16
220
221         /* Load the return value */
222         mov     x0, x1
223         ret
224 END(longjmp)
225
226 /*
227  * pagezero, simple implementation
228  */
229 ENTRY(pagezero_simple)
230         add     x1, x0, #PAGE_SIZE
231
232 1:
233         stp     xzr, xzr, [x0], #0x10
234         stp     xzr, xzr, [x0], #0x10
235         stp     xzr, xzr, [x0], #0x10
236         stp     xzr, xzr, [x0], #0x10
237         cmp     x0, x1
238         b.ne    1b
239         ret
240
241 END(pagezero_simple)
242
243 /*
244  * pagezero, cache assisted
245  */
246 ENTRY(pagezero_cache)
247         add     x1, x0, #PAGE_SIZE
248
249         ldr     x2, =dczva_line_size
250         ldr     x2, [x2]
251
252 1:
253         dc      zva, x0
254         add     x0, x0, x2
255         cmp     x0, x1
256         b.ne    1b
257         ret
258
259 END(pagezero_cache)