diff options
Diffstat (limited to 'arch/arm26/lib/uaccess-kernel.S')
-rw-r--r-- | arch/arm26/lib/uaccess-kernel.S | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/arch/arm26/lib/uaccess-kernel.S b/arch/arm26/lib/uaccess-kernel.S new file mode 100644 index 000000000000..3950a1f6bc99 --- /dev/null +++ b/arch/arm26/lib/uaccess-kernel.S | |||
@@ -0,0 +1,173 @@ | |||
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 | |||