]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/fusu.S
Mark more nodes as CTLFLAG_MPSAFE or CTLFLAG_NEEDGIANT (17 of many)
[FreeBSD/FreeBSD.git] / sys / arm / arm / fusu.S
1 /*      $NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $       */
2
3 /*-
4  * Copyright (c) 1996-1998 Mark Brinicombe.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Mark Brinicombe
18  * 4. The name of the company nor the name of the author may be used to
19  *    endorse or promote products derived from this software without specific
20  *    prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * 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
36 #include <machine/asm.h>
37 #include <machine/armreg.h>
38 #include "assym.inc"
39 __FBSDID("$FreeBSD$");
40
41         .syntax unified
42
43 #if __ARM_ARCH >= 6
44 #define GET_PCB(tmp) \
45         mrc p15, 0, tmp, c13, c0, 4; \
46         add     tmp, tmp, #(TD_PCB)
47 #else
48 .Lcurpcb:
49         .word   _C_LABEL(__pcpu) + PC_CURPCB
50 #define GET_PCB(tmp) \
51         ldr     tmp, .Lcurpcb
52 #endif
53
54 /*
55  * casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
56  *    uint32_t newval);
57  */
58
59 ENTRY(casueword)
60 EENTRY_NP(casueword32)
61         stmfd   sp!, {r4, r5, r6}
62
63         ldr     r4, =(VM_MAXUSER_ADDRESS-3)
64         cmp     r0, r4
65         mvncs   r0, #0
66         bcs     1f
67
68         GET_PCB(r6)
69         ldr     r6, [r6]
70
71 #ifdef DIAGNOSTIC
72         teq     r6, #0x00000000
73         ldmfdeq sp!, {r4, r5, r6}
74         beq     .Lfusupcbfault
75 #endif
76
77         adr     r4, .Lcasuwordfault
78         str     r4, [r6, #PCB_ONFAULT]
79
80 #if __ARM_ARCH >= 6
81         mov     r5, #1
82         ldrex   r4, [r0]
83         cmp     r4, r1
84         strexeq r5, r3, [r0]
85 #else
86         ldrt    r4, [r0]
87         cmp     r4, r1
88         strteq  r3, [r0]
89 #endif
90         str     r4, [r2]
91         mov     r0, #0
92         str     r0, [r6, #PCB_ONFAULT]
93 #if __ARM_ARCH >= 6
94         mov     r0, r5
95 #endif
96 1:
97         ldmfd   sp!, {r4, r5, r6}
98         RET
99 EEND(casueword32)
100 END(casueword)
101
102 /*
103  * Handle faults from casuword.  Clean up and return -1.
104  */
105
106 .Lcasuwordfault:
107         mov     r0, #0x00000000
108         str     r0, [r6, #PCB_ONFAULT]
109         mvn     r0, #0
110         ldmfd   sp!, {r4, r5, r6}
111         RET
112
113 /*
114  * fueword(caddr_t uaddr, long *val);
115  * Fetch an int from the user's address space.
116  */
117
118 ENTRY(fueword)
119 EENTRY_NP(fueword32)
120         ldr     r3, =(VM_MAXUSER_ADDRESS-3)
121         cmp     r0, r3
122         mvncs   r0, #0
123         RETc(cs)
124
125         GET_PCB(r2)
126         ldr     r2, [r2]
127
128 #ifdef DIAGNOSTIC
129         teq     r2, #0x00000000
130         beq     .Lfusupcbfault
131 #endif
132
133         adr     r3, .Lfusufault
134         str     r3, [r2, #PCB_ONFAULT]
135
136         ldrt    r3, [r0]
137         str     r3, [r1]
138
139         mov     r0, #0x00000000
140         str     r0, [r2, #PCB_ONFAULT]
141         RET
142 EEND(fueword32)
143 END(fueword)
144
145 /*
146  * fusword(caddr_t uaddr);
147  * Fetch a short from the user's address space.
148  */
149
150 ENTRY(fusword)
151         ldr     r3, =(VM_MAXUSER_ADDRESS-1)
152         cmp     r0, r3
153         mvncs   r0, #0
154         RETc(cs)
155
156         GET_PCB(r2)
157         ldr     r2, [r2]
158
159 #ifdef DIAGNOSTIC
160         teq     r2, #0x00000000
161         beq     .Lfusupcbfault
162 #endif
163
164         adr     r1, .Lfusufault
165         str     r1, [r2, #PCB_ONFAULT]
166
167         ldrbt   r3, [r0], #1
168         ldrbt   ip, [r0]
169 #ifdef __ARMEB__
170         orr     r0, ip, r3, asl #8
171 #else
172         orr     r0, r3, ip, asl #8
173 #endif
174         mov     r1, #0x00000000
175         str     r1, [r2, #PCB_ONFAULT]
176         RET
177 END(fusword)
178
179 /*
180  * fubyte(caddr_t uaddr);
181  * Fetch a byte from the user's address space.
182  */
183
184 ENTRY(fubyte)
185         ldr     r3, =VM_MAXUSER_ADDRESS
186         cmp     r0, r3
187         mvncs   r0, #0
188         RETc(cs)
189
190         GET_PCB(r2)
191         ldr     r2, [r2]
192
193 #ifdef DIAGNOSTIC
194         teq     r2, #0x00000000
195         beq     .Lfusupcbfault
196 #endif
197
198         adr     r1, .Lfusufault
199         str     r1, [r2, #PCB_ONFAULT]
200
201         ldrbt   r3, [r0]
202
203         mov     r1, #0x00000000
204         str     r1, [r2, #PCB_ONFAULT]
205         mov     r0, r3
206         RET
207 END(fubyte)
208
209 /*
210  * Handle faults from [fs]u*().  Clean up and return -1.
211  */
212
213 .Lfusufault:
214         mov     r0, #0x00000000
215         str     r0, [r2, #PCB_ONFAULT]
216         mvn     r0, #0x00000000
217         RET
218
219 #ifdef DIAGNOSTIC
220 /*
221  * Handle earlier faults from [fs]u*(), due to no pcb
222  */
223
224 .Lfusupcbfault:
225         mov     r1, r0
226         adr     r0, fusupcbfaulttext
227         b       _C_LABEL(panic)
228
229 fusupcbfaulttext:
230         .asciz  "Yikes - no valid PCB during fusuxxx() addr=%08x\n"
231         .align  2
232 #endif
233
234 /*
235  * suword(caddr_t uaddr, int x);
236  * Store an int in the user's address space.
237  */
238
239 ENTRY(suword)
240 EENTRY_NP(suword32)
241         ldr     r3, =(VM_MAXUSER_ADDRESS-3)
242         cmp     r0, r3
243         mvncs   r0, #0
244         RETc(cs)
245
246         GET_PCB(r2)
247         ldr     r2, [r2]
248
249 #ifdef DIAGNOSTIC
250         teq     r2, #0x00000000
251         beq     .Lfusupcbfault
252 #endif
253
254         adr     r3, .Lfusufault
255         str     r3, [r2, #PCB_ONFAULT]
256
257         strt    r1, [r0]
258
259         mov     r0, #0x00000000
260         str     r0, [r2, #PCB_ONFAULT]
261         RET
262 EEND(suword32)
263 END(suword)
264
265 /*
266  * susword(caddr_t uaddr, short x);
267  * Store a short in the user's address space.
268  */
269
270 ENTRY(susword)
271         ldr     r3, =(VM_MAXUSER_ADDRESS-1)
272         cmp     r0, r3
273         mvncs   r0, #0
274         RETc(cs)
275
276         GET_PCB(r2)
277         ldr     r2, [r2]
278
279 #ifdef DIAGNOSTIC
280         teq     r2, #0x00000000
281         beq     .Lfusupcbfault
282 #endif
283
284         adr     r3, .Lfusufault
285         str     r3, [r2, #PCB_ONFAULT]
286
287 #ifdef __ARMEB__
288         mov     ip, r1, lsr #8
289         strbt   ip, [r0], #1
290 #else
291         strbt   r1, [r0], #1
292         mov     r1, r1, lsr #8
293 #endif
294         strbt   r1, [r0]
295
296         mov     r0, #0x00000000
297         str     r0, [r2, #PCB_ONFAULT]
298         RET
299 END(susword)
300
301 /*
302  * subyte(caddr_t uaddr, char x);
303  * Store a byte in the user's address space.
304  */
305
306 ENTRY(subyte)
307         ldr     r3, =VM_MAXUSER_ADDRESS
308         cmp     r0, r3
309         mvncs   r0, #0
310         RETc(cs)
311
312         GET_PCB(r2)
313         ldr     r2, [r2]
314
315
316 #ifdef DIAGNOSTIC
317         teq     r2, #0x00000000
318         beq     .Lfusupcbfault
319 #endif
320
321         adr     r3, .Lfusufault
322         str     r3, [r2, #PCB_ONFAULT]
323
324         strbt   r1, [r0]
325         mov     r0, #0x00000000
326         str     r0, [r2, #PCB_ONFAULT]
327         RET
328 END(subyte)