Linux-2.6.12-rc2
[linux-2.6.git] / arch / arm26 / lib / uaccess-kernel.S
1 /*
2  *  linux/arch/arm26/lib/uaccess-kernel.S
3  *
4  *  Copyright (C) 1998 Russell King
5  *
6  *  Note!  Some code fragments found in here have a special calling
7  *  convention - they are not APCS compliant!
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 #include <linux/linkage.h>
14 #include <asm/assembler.h>
15
16                 .text
17
18 //FIXME - surely this can be done in C not asm, removing the problem of keeping C and asm in sync? (this is a struct uaccess_t)
19
20                 .globl  uaccess_kernel
21 uaccess_kernel:
22                 .word   uaccess_kernel_put_byte
23                 .word   uaccess_kernel_get_byte
24                 .word   uaccess_kernel_put_half
25                 .word   uaccess_kernel_get_half
26                 .word   uaccess_kernel_put_word
27                 .word   uaccess_kernel_get_word
28                 .word   uaccess_kernel_put_dword
29                 .word   uaccess_kernel_copy
30                 .word   uaccess_kernel_copy
31                 .word   uaccess_kernel_clear
32                 .word   uaccess_kernel_strncpy
33                 .word   uaccess_kernel_strnlen
34
35 @ In : r0 = x, r1 = addr, r2 = error
36 @ Out: r2 = error
37 uaccess_kernel_put_byte:
38                 stmfd   sp!, {lr}
39                 strb    r0, [r1]
40                 ldmfd   sp!, {pc}^
41
42 @ In : r0 = x, r1 = addr, r2 = error
43 @ Out: r2 = error
44 uaccess_kernel_put_half:
45                 stmfd   sp!, {lr}
46                 strb    r0, [r1]
47                 mov     r0, r0, lsr #8
48                 strb    r0, [r1, #1]
49                 ldmfd   sp!, {pc}^
50
51 @ In : r0 = x, r1 = addr, r2 = error
52 @ Out: r2 = error
53 uaccess_kernel_put_word:
54                 stmfd   sp!, {lr}
55                 str     r0, [r1]
56                 ldmfd   sp!, {pc}^
57
58 @ In : r0 = x, r1 = addr, r2 = error
59 @ Out: r2 = error
60 uaccess_kernel_put_dword:
61                 stmfd   sp!, {lr}
62                 str     r0, [r1], #4
63                 str     r0, [r1], #0
64                 ldmfd   sp!, {pc}^
65
66 @ In : r0 = addr, r1 = error
67 @ Out: r0 = x, r1 = error
68 uaccess_kernel_get_byte:
69                 stmfd   sp!, {lr}
70                 ldrb    r0, [r0]
71                 ldmfd   sp!, {pc}^
72
73 @ In : r0 = addr, r1 = error
74 @ Out: r0 = x, r1 = error
75 uaccess_kernel_get_half:
76                 stmfd   sp!, {lr}
77                 ldr     r0, [r0]
78                 mov     r0, r0, lsl #16
79                 mov     r0, r0, lsr #16
80                 ldmfd   sp!, {pc}^
81
82 @ In : r0 = addr, r1 = error
83 @ Out: r0 = x, r1 = error
84 uaccess_kernel_get_word:
85                 stmfd   sp!, {lr}
86                 ldr     r0, [r0]
87                 ldmfd   sp!, {pc}^
88
89
90 /* Prototype: int uaccess_kernel_copy(void *to, const char *from, size_t n)
91  * Purpose  : copy a block to kernel memory from kernel memory
92  * Params   : to   - kernel memory
93  *          : from - kernel memory
94  *          : n    - number of bytes to copy
95  * Returns  : Number of bytes NOT copied.
96  */
97 uaccess_kernel_copy:
98                 stmfd   sp!, {lr}
99                 bl      memcpy
100                 mov     r0, #0
101                 ldmfd   sp!, {pc}^
102
103 /* Prototype: int uaccess_kernel_clear(void *addr, size_t sz)
104  * Purpose  : clear some kernel memory
105  * Params   : addr - kernel memory address to clear
106  *          : sz   - number of bytes to clear
107  * Returns  : number of bytes NOT cleared
108  */
109 uaccess_kernel_clear:
110                 stmfd   sp!, {lr}
111                 mov     r2, #0
112                 cmp     r1, #4
113                 blt     2f
114                 ands    ip, r0, #3
115                 beq     1f
116                 cmp     ip, #1
117                 strb    r2, [r0], #1
118                 strleb  r2, [r0], #1
119                 strltb  r2, [r0], #1
120                 rsb     ip, ip, #4
121                 sub     r1, r1, ip              @  7  6  5  4  3  2  1
122 1:              subs    r1, r1, #8              @ -1 -2 -3 -4 -5 -6 -7
123                 bmi     2f
124                 str     r2, [r0], #4
125                 str     r2, [r0], #4
126                 b       1b
127 2:              adds    r1, r1, #4              @  3  2  1  0 -1 -2 -3
128                 strpl   r2, [r0], #4
129                 tst     r1, #2                  @ 1x 1x 0x 0x 1x 1x 0x
130                 strneb  r2, [r0], #1
131                 strneb  r2, [r0], #1
132                 tst     r1, #1                  @ x1 x0 x1 x0 x1 x0 x1
133                 strneb  r2, [r0], #1
134                 mov     r0, #0
135                 ldmfd   sp!, {pc}^
136
137 /* Prototype: size_t uaccess_kernel_strncpy(char *dst, char *src, size_t len)
138  * Purpose  : copy a string from kernel memory to kernel memory
139  * Params   : dst - kernel memory destination
140  *          : src - kernel memory source
141  *          : len - maximum length of string
142  * Returns  : number of characters copied
143  */
144 uaccess_kernel_strncpy:
145                 stmfd   sp!, {lr}
146                 mov     ip, r2
147 1:              subs    r2, r2, #1
148                 bmi     2f
149                 ldrb    r3, [r1], #1
150                 strb    r3, [r0], #1
151                 teq     r3, #0
152                 bne     1b
153 2:              subs    r0, ip, r2
154                 ldmfd   sp!, {pc}^
155
156 /* Prototype: int uaccess_kernel_strlen(char *str, long n)
157  * Purpose  : get length of a string in kernel memory
158  * Params   : str - address of string in kernel memory
159  * Returns  : length of string *including terminator*,
160  *            or zero on exception, or n + 1 if too long
161  */
162 uaccess_kernel_strnlen:
163                 stmfd   sp!, {lr}
164                 mov     r2, r0
165 1:              ldrb    r1, [r0], #1
166                 teq     r1, #0
167                 beq     2f
168                 subs    r1, r1, #1
169                 bne     1b
170                 add     r0, r0, #1
171 2:              sub     r0, r0, r2
172                 ldmfd   sp!, {pc}^
173