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