FreeBSD/Linux Kernel Cross Reference
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: releng/8.1/sys/arm/arm/fusu.S 163449 2006-10-17 02:24:47Z davidxu $");
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
Cache object: 678e1baa81b235f11852cf2205f66462
|