]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/arm/arm/fusu.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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/asmacros.h>
38 #include <machine/armreg.h>
39 #include "assym.s"
40 __FBSDID("$FreeBSD$");
41
42 #ifdef _ARM_ARCH_6
43 #define GET_PCB(tmp) \
44         mrc p15, 0, tmp, c13, c0, 4; \
45         add     tmp, tmp, #(PC_CURPCB)
46 #else
47 .Lcurpcb:
48         .word   _C_LABEL(__pcpu) + PC_CURPCB
49 #define GET_PCB(tmp) \
50         ldr     tmp, .Lcurpcb
51 #endif
52
53 /*
54  * fuword(caddr_t uaddr);
55  * Fetch an int from the user's address space.
56  */
57
58 ENTRY_NP(casuword32)
59 ENTRY(casuword)
60         GET_PCB(r3)
61         ldr     r3, [r3]
62
63 #ifdef DIAGNOSTIC
64         teq     r3, #0x00000000
65         beq     .Lfusupcbfault
66 #endif
67         stmfd   sp!, {r4, r5}
68         adr     r4, .Lcasuwordfault
69         str     r4, [r3, #PCB_ONFAULT]
70         ldrt    r5, [r0]
71         cmp     r5, r1
72         movne   r0, r5
73         streqt  r2, [r0]
74         moveq   r0, r1
75         ldmfd   sp!, {r4, r5}
76         mov     r1, #0x00000000
77         str     r1, [r3, #PCB_ONFAULT]
78         RET
79 END(casuword32)
80 END(casuword)
81
82 /*
83  * Handle faults from casuword.  Clean up and return -1.
84  */
85
86 .Lcasuwordfault:
87         mov     r0, #0x00000000
88         str     r0, [r3, #PCB_ONFAULT]
89         mvn     r0, #0x00000000
90         ldmfd   sp!, {r4, r5}
91         RET     
92
93 /*
94  * fuword(caddr_t uaddr);
95  * Fetch an int from the user's address space.
96  */
97
98 ENTRY_NP(fuword32)
99 ENTRY(fuword)
100         GET_PCB(r2)
101         ldr     r2, [r2]
102
103 #ifdef DIAGNOSTIC
104         teq     r2, #0x00000000
105         beq     .Lfusupcbfault
106 #endif
107
108         adr     r1, .Lfusufault
109         str     r1, [r2, #PCB_ONFAULT]
110
111         ldrt    r3, [r0]
112
113         mov     r1, #0x00000000
114         str     r1, [r2, #PCB_ONFAULT]
115         mov     r0, r3
116         RET
117 END(fuword32)
118 END(fuword)
119
120 /*
121  * fusword(caddr_t uaddr);
122  * Fetch a short from the user's address space.
123  */
124
125 ENTRY(fusword)
126         GET_PCB(r2)
127         ldr     r2, [r2]
128
129 #ifdef DIAGNOSTIC
130         teq     r2, #0x00000000
131         beq     .Lfusupcbfault
132 #endif
133
134         adr     r1, .Lfusufault
135         str     r1, [r2, #PCB_ONFAULT]
136
137         ldrbt   r3, [r0], #1
138         ldrbt   ip, [r0]
139 #ifdef __ARMEB__
140         orr     r0, ip, r3, asl #8
141 #else
142         orr     r0, r3, ip, asl #8
143 #endif
144         mov     r1, #0x00000000
145         str     r1, [r2, #PCB_ONFAULT]
146         RET
147 END(fusword)
148
149 /*
150  * fuswintr(caddr_t uaddr);
151  * Fetch a short from the user's address space.  Can be called during an
152  * interrupt.
153  */
154
155 ENTRY(fuswintr)
156         ldr     r2, Lblock_userspace_access
157         ldr     r2, [r2]
158         teq     r2, #0
159         mvnne   r0, #0x00000000
160         RETne
161
162         GET_PCB(r2)
163         ldr     r2, [r2]
164
165 #ifdef DIAGNOSTIC
166         teq     r2, #0x00000000
167         beq     .Lfusupcbfault
168 #endif
169
170         adr     r1, _C_LABEL(fusubailout)
171         str     r1, [r2, #PCB_ONFAULT]
172
173         ldrbt   r3, [r0], #1
174         ldrbt   ip, [r0]
175 #ifdef __ARMEB__
176         orr     r0, ip, r3, asl #8
177 #else
178         orr     r0, r3, ip, asl #8
179 #endif
180
181         mov     r1, #0x00000000
182         str     r1, [r2, #PCB_ONFAULT]
183         RET
184 END(fuswintr)
185
186 Lblock_userspace_access:
187         .word   _C_LABEL(block_userspace_access)
188
189         .data
190         .align  0
191         .global _C_LABEL(block_userspace_access)
192 _C_LABEL(block_userspace_access):
193         .word   0
194         .text
195
196 /*
197  * fubyte(caddr_t uaddr);
198  * Fetch a byte from the user's address space.
199  */
200
201 ENTRY(fubyte)
202         GET_PCB(r2)
203         ldr     r2, [r2]
204
205 #ifdef DIAGNOSTIC
206         teq     r2, #0x00000000
207         beq     .Lfusupcbfault
208 #endif
209
210         adr     r1, .Lfusufault
211         str     r1, [r2, #PCB_ONFAULT]
212
213         ldrbt   r3, [r0]
214
215         mov     r1, #0x00000000
216         str     r1, [r2, #PCB_ONFAULT]
217         mov     r0, r3
218         RET
219 END(fubyte)
220
221 /*
222  * Handle faults from [fs]u*().  Clean up and return -1.
223  */
224
225 .Lfusufault:
226         mov     r0, #0x00000000
227         str     r0, [r2, #PCB_ONFAULT]
228         mvn     r0, #0x00000000
229         RET
230
231 /*
232  * Handle faults from [fs]u*().  Clean up and return -1.  This differs from
233  * fusufault() in that trap() will recognise it and return immediately rather
234  * than trying to page fault.
235  */
236
237 /* label must be global as fault.c references it */
238         .global _C_LABEL(fusubailout)
239 _C_LABEL(fusubailout):
240         mov     r0, #0x00000000
241         str     r0, [r2, #PCB_ONFAULT]
242         mvn     r0, #0x00000000
243         RET
244
245 #ifdef DIAGNOSTIC
246 /*
247  * Handle earlier faults from [fs]u*(), due to no pcb
248  */
249
250 .Lfusupcbfault:
251         mov     r1, r0
252         adr     r0, fusupcbfaulttext
253         b       _C_LABEL(panic)
254
255 fusupcbfaulttext:
256         .asciz  "Yikes - no valid PCB during fusuxxx() addr=%08x\n"
257         .align  0
258 #endif
259
260 /*
261  * suword(caddr_t uaddr, int x);
262  * Store an int in the user's address space.
263  */
264
265 ENTRY_NP(suword32)
266 ENTRY(suword)
267         GET_PCB(r2)
268         ldr     r2, [r2]
269
270 #ifdef DIAGNOSTIC
271         teq     r2, #0x00000000
272         beq     .Lfusupcbfault
273 #endif
274
275         adr     r3, .Lfusufault
276         str     r3, [r2, #PCB_ONFAULT]
277
278         strt    r1, [r0]
279
280         mov     r0, #0x00000000
281         str     r0, [r2, #PCB_ONFAULT]
282         RET
283 END(suword32)
284 END(suword)
285
286 /*
287  * suswintr(caddr_t uaddr, short x);
288  * Store a short in the user's address space.  Can be called during an
289  * interrupt.
290  */
291
292 ENTRY(suswintr)
293         ldr     r2, Lblock_userspace_access
294         ldr     r2, [r2]
295         teq     r2, #0
296         mvnne   r0, #0x00000000
297         RETne
298
299         GET_PCB(r2)
300         ldr     r2, [r2]
301
302 #ifdef DIAGNOSTIC
303         teq     r2, #0x00000000
304         beq     .Lfusupcbfault
305 #endif
306
307         adr     r3, _C_LABEL(fusubailout)
308         str     r3, [r2, #PCB_ONFAULT]
309
310 #ifdef __ARMEB__
311         mov     ip, r1, lsr #8
312         strbt   ip, [r0], #1
313 #else
314         strbt   r1, [r0], #1
315         mov     r1, r1, lsr #8
316 #endif
317         strbt   r1, [r0]
318
319         mov     r0, #0x00000000
320         str     r0, [r2, #PCB_ONFAULT]
321         RET
322 END(suswintr)
323
324 /*
325  * susword(caddr_t uaddr, short x);
326  * Store a short in the user's address space.
327  */
328
329 ENTRY(susword)
330         GET_PCB(r2)
331         ldr     r2, [r2]
332
333 #ifdef DIAGNOSTIC
334         teq     r2, #0x00000000
335         beq     .Lfusupcbfault
336 #endif
337
338         adr     r3, .Lfusufault
339         str     r3, [r2, #PCB_ONFAULT]
340
341 #ifdef __ARMEB__
342         mov     ip, r1, lsr #8
343         strbt   ip, [r0], #1
344 #else
345         strbt   r1, [r0], #1
346         mov     r1, r1, lsr #8
347 #endif
348         strbt   r1, [r0]
349
350         mov     r0, #0x00000000
351         str     r0, [r2, #PCB_ONFAULT]
352         RET
353 END(susword)
354
355 /*
356  * subyte(caddr_t uaddr, char x);
357  * Store a byte in the user's address space.
358  */
359
360 ENTRY(subyte)
361         GET_PCB(r2)
362         ldr     r2, [r2]
363
364
365 #ifdef DIAGNOSTIC
366         teq     r2, #0x00000000
367         beq     .Lfusupcbfault
368 #endif
369
370         adr     r3, .Lfusufault
371         str     r3, [r2, #PCB_ONFAULT]
372
373         strbt   r1, [r0]
374         mov     r0, #0x00000000
375         str     r0, [r2, #PCB_ONFAULT]
376         RET
377 END(subyte)
378