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/armreg.h>
38 #include "assym.s"
39 __FBSDID("$FreeBSD: releng/10.2/sys/arm/arm/fusu.S 278652 2015-02-13 00:49:47Z ian $");
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)
Cache object: 5072765cc302281599a23e478b13ac8b
|