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