1/*
2 * Copy to/from userspace with optional address space checking.
3 *
4 * Copyright 2004-2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <asm/page.h>
11#include <asm/thread_info.h>
12#include <asm/asm.h>
13
14	/*
15	 * __kernel_size_t
16	 * __copy_user(void *to, const void *from, __kernel_size_t n)
17	 *
18	 * Returns the number of bytes not copied. Might be off by
19	 * max 3 bytes if we get a fault in the main loop.
20	 *
21	 * The address-space checking functions simply fall through to
22	 * the non-checking version.
23	 */
24	.text
25	.align	1
26	.global	copy_from_user
27	.type	copy_from_user, @function
28copy_from_user:
29	branch_if_kernel r8, __copy_user
30	ret_if_privileged r8, r11, r10, r10
31	rjmp	__copy_user
32	.size	copy_from_user, . - copy_from_user
33
34	.global	copy_to_user
35	.type	copy_to_user, @function
36copy_to_user:
37	branch_if_kernel r8, __copy_user
38	ret_if_privileged r8, r12, r10, r10
39	.size	copy_to_user, . - copy_to_user
40
41	.global	__copy_user
42	.type	__copy_user, @function
43__copy_user:
44	mov	r9, r11
45	andl	r9, 3, COH
46	brne	6f
47
48	/* At this point, from is word-aligned */
491:	sub	r10, 4
50	brlt	3f
51
522:
5310:	ld.w	r8, r11++
5411:	st.w	r12++, r8
55	sub	r10, 4
56	brge	2b
57
583:	sub	r10, -4
59	reteq	0
60
61	/*
62	 * Handle unaligned count. Need to be careful with r10 here so
63	 * that we return the correct value even if we get a fault
64	 */
654:
6620:	ld.ub	r8, r11++
6721:	st.b	r12++, r8
68	sub	r10, 1
69	reteq	0
7022:	ld.ub	r8, r11++
7123:	st.b	r12++, r8
72	sub	r10, 1
73	reteq	0
7424:	ld.ub	r8, r11++
7525:	st.b	r12++, r8
76	retal	0
77
78	/* Handle unaligned from-pointer */
796:	cp.w	r10, 4
80	brlt	4b
81	rsub	r9, r9, 4
82
8330:	ld.ub	r8, r11++
8431:	st.b	r12++, r8
85	sub	r10, 1
86	sub	r9, 1
87	breq	1b
8832:	ld.ub	r8, r11++
8933:	st.b	r12++, r8
90	sub	r10, 1
91	sub	r9, 1
92	breq	1b
9334:	ld.ub	r8, r11++
9435:	st.b	r12++, r8
95	sub	r10, 1
96	rjmp	1b
97	.size	__copy_user, . - __copy_user
98
99	.section .fixup,"ax"
100	.align	1
10119:	sub	r10, -4
10229:	retal	r10
103
104	.section __ex_table,"a"
105	.align	2
106	.long	10b, 19b
107	.long	11b, 19b
108	.long	20b, 29b
109	.long	21b, 29b
110	.long	22b, 29b
111	.long	23b, 29b
112	.long	24b, 29b
113	.long	25b, 29b
114	.long	30b, 29b
115	.long	31b, 29b
116	.long	32b, 29b
117	.long	33b, 29b
118	.long	34b, 29b
119	.long	35b, 29b
120