1/*
2 *  linux/arch/arm/lib/uaccess-armo.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		.globl	SYMBOL_NAME(uaccess_user)
19SYMBOL_NAME(uaccess_user):
20		.word	uaccess_user_put_byte
21		.word	uaccess_user_get_byte
22		.word	uaccess_user_put_half
23		.word	uaccess_user_get_half
24		.word	uaccess_user_put_word
25		.word	uaccess_user_get_word
26		.word	__arch_copy_from_user
27		.word	__arch_copy_to_user
28		.word	__arch_clear_user
29		.word	__arch_strncpy_from_user
30		.word	__arch_strnlen_user
31
32
33@ In : r0 = x, r1 = addr, r2 = error
34@ Out: r2 = error
35uaccess_user_put_byte:
36		stmfd	sp!, {lr}
37USER(		strbt	r0, [r1])
38		ldmfd	sp!, {pc}^
39
40@ In : r0 = x, r1 = addr, r2 = error
41@ Out: r2 = error
42uaccess_user_put_half:
43		stmfd	sp!, {lr}
44USER(		strbt	r0, [r1], #1)
45		mov	r0, r0, lsr #8
46USER(		strbt	r0, [r1])
47		ldmfd	sp!, {pc}^
48
49@ In : r0 = x, r1 = addr, r2 = error
50@ Out: r2 = error
51uaccess_user_put_word:
52		stmfd	sp!, {lr}
53USER(		strt	r0, [r1])
54		ldmfd	sp!, {pc}^
55
569001:		mov	r2, #-EFAULT
57		ldmfd	sp!, {pc}^
58
59@ In : r0 = addr, r1 = error
60@ Out: r0 = x, r1 = error
61uaccess_user_get_byte:
62		stmfd	sp!, {lr}
63USER(		ldrbt	r0, [r0])
64		ldmfd	sp!, {pc}^
65
66@ In : r0 = addr, r1 = error
67@ Out: r0 = x, r1 = error
68uaccess_user_get_half:
69		stmfd	sp!, {lr}
70USER(		ldrt	r0, [r0])
71		mov	r0, r0, lsl #16
72		mov	r0, r0, lsr #16
73		ldmfd	sp!, {pc}^
74
75@ In : r0 = addr, r1 = error
76@ Out: r0 = x, r1 = error
77uaccess_user_get_word:
78		stmfd	sp!, {lr}
79USER(		ldrt	r0, [r0])
80		ldmfd	sp!, {pc}^
81
829001:		mov	r1, #-EFAULT
83		ldmfd	sp!, {pc}^
84
85
86
87		.globl	SYMBOL_NAME(uaccess_kernel)
88SYMBOL_NAME(uaccess_kernel):
89		.word	uaccess_kernel_put_byte
90		.word	uaccess_kernel_get_byte
91		.word	uaccess_kernel_put_half
92		.word	uaccess_kernel_get_half
93		.word	uaccess_kernel_put_word
94		.word	uaccess_kernel_get_word
95		.word	uaccess_kernel_copy
96		.word	uaccess_kernel_copy
97		.word	uaccess_kernel_clear
98		.word	uaccess_kernel_strncpy_from
99		.word	uaccess_kernel_strnlen
100
101@ In : r0 = x, r1 = addr, r2 = error
102@ Out: r2 = error
103uaccess_kernel_put_byte:
104		stmfd	sp!, {lr}
105		strb	r0, [r1]
106		ldmfd	sp!, {pc}^
107
108@ In : r0 = x, r1 = addr, r2 = error
109@ Out: r2 = error
110uaccess_kernel_put_half:
111		stmfd	sp!, {lr}
112		strb	r0, [r1]
113		mov	r0, r0, lsr #8
114		strb	r0, [r1, #1]
115		ldmfd	sp!, {pc}^
116
117@ In : r0 = x, r1 = addr, r2 = error
118@ Out: r2 = error
119uaccess_kernel_put_word:
120		stmfd	sp!, {lr}
121		str	r0, [r1]
122		ldmfd	sp!, {pc}^
123
124@ In : r0 = addr, r1 = error
125@ Out: r0 = x, r1 = error
126uaccess_kernel_get_byte:
127		stmfd	sp!, {lr}
128		ldrb	r0, [r0]
129		ldmfd	sp!, {pc}^
130
131@ In : r0 = addr, r1 = error
132@ Out: r0 = x, r1 = error
133uaccess_kernel_get_half:
134		stmfd	sp!, {lr}
135		ldr	r0, [r0]
136		mov	r0, r0, lsl #16
137		mov	r0, r0, lsr #16
138		ldmfd	sp!, {pc}^
139
140@ In : r0 = addr, r1 = error
141@ Out: r0 = x, r1 = error
142uaccess_kernel_get_word:
143		stmfd	sp!, {lr}
144		ldr	r0, [r0]
145		ldmfd	sp!, {pc}^
146
147
148/* Prototype: int uaccess_kernel_copy(void *to, const char *from, size_t n)
149 * Purpose  : copy a block to kernel memory from kernel memory
150 * Params   : to   - kernel memory
151 *          : from - kernel memory
152 *          : n    - number of bytes to copy
153 * Returns  : Number of bytes NOT copied.
154 */
155uaccess_kernel_copy:
156		stmfd	sp!, {lr}
157		bl	SYMBOL_NAME(memcpy)
158		mov	r0, #0
159		ldmfd	sp!, {pc}^
160
161/* Prototype: int uaccess_kernel_clear(void *addr, size_t sz)
162 * Purpose  : clear some kernel memory
163 * Params   : addr - kernel memory address to clear
164 *          : sz   - number of bytes to clear
165 * Returns  : number of bytes NOT cleared
166 */
167uaccess_kernel_clear:
168		stmfd	sp!, {lr}
169		mov	r2, #0
170		cmp	r1, #4
171		blt	2f
172		ands	ip, r0, #3
173		beq	1f
174		cmp	ip, #1
175		strb	r2, [r0], #1
176		strleb	r2, [r0], #1
177		strltb	r2, [r0], #1
178		rsb	ip, ip, #4
179		sub	r1, r1, ip		@  7  6  5  4  3  2  1
1801:		subs	r1, r1, #8		@ -1 -2 -3 -4 -5 -6 -7
181		bmi	2f
182		str	r2, [r0], #4
183		str	r2, [r0], #4
184		b	1b
1852:		adds	r1, r1, #4		@  3  2  1  0 -1 -2 -3
186		strpl	r2, [r0], #4
187		tst	r1, #2			@ 1x 1x 0x 0x 1x 1x 0x
188		strneb	r2, [r0], #1
189		strneb	r2, [r0], #1
190		tst	r1, #1			@ x1 x0 x1 x0 x1 x0 x1
191		strneb	r2, [r0], #1
192		mov	r0, #0
193		ldmfd	sp!, {pc}^
194
195/* Prototype: size_t uaccess_kernel_strncpy_from(char *dst, char *src, size_t len)
196 * Purpose  : copy a string from kernel memory to kernel memory
197 * Params   : dst - kernel memory destination
198 *          : src - kernel memory source
199 *          : len - maximum length of string
200 * Returns  : number of characters copied
201 */
202uaccess_kernel_strncpy_from:
203		stmfd	sp!, {lr}
204		mov	ip, r2
2051:		subs	r2, r2, #1
206		bmi	2f
207		ldrb	r3, [r1], #1
208		strb	r3, [r0], #1
209		teq	r3, #0
210		bne	1b
2112:		subs	r0, ip, r2
212		ldmfd	sp!, {pc}^
213
214/* Prototype: int uaccess_kernel_strlen(char *str, long n)
215 * Purpose  : get length of a string in kernel memory
216 * Params   : str - address of string in kernel memory
217 * Returns  : length of string *including terminator*,
218 *            or zero on exception, or n + 1 if too long
219 */
220uaccess_kernel_strnlen:
221		stmfd	sp!, {lr}
222		mov	r2, r0
2231:		ldrb	r1, [r0], #1
224		teq	r1, #0
225		beq	2f
226		subs	r1, r1, #1
227		bne	1b
228		add	r0, r0, #1
2292:		sub	r0, r0, r2
230		ldmfd	sp!, {pc}^
231
232