1/*
2 *  linux/include/asm-arm/proc-armv/uaccess.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <asm/arch/memory.h>
9#include <asm/proc/domain.h>
10
11/*
12 * Note that this is actually 0x1,0000,0000
13 */
14#define KERNEL_DS	0x00000000
15#define USER_DS		PAGE_OFFSET
16
17static inline void set_fs (mm_segment_t fs)
18{
19	current->addr_limit = fs;
20
21	modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
22}
23
24/* We use 33-bit arithmetic here... */
25#define __range_ok(addr,size) ({ \
26	unsigned long flag, sum; \
27	__asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
28		: "=&r" (flag), "=&r" (sum) \
29		: "r" (addr), "Ir" (size), "0" (current->addr_limit) \
30		: "cc"); \
31	flag; })
32
33#define __addr_ok(addr) ({ \
34	unsigned long flag; \
35	__asm__("cmp %2, %0; movlo %0, #0" \
36		: "=&r" (flag) \
37		: "0" (current->addr_limit), "r" (addr) \
38		: "cc"); \
39	(flag == 0); })
40
41#define __put_user_asm_byte(x,addr,err)				\
42	__asm__ __volatile__(					\
43	"1:	strbt	%1,[%2],#0\n"				\
44	"2:\n"							\
45	"	.section .fixup,\"ax\"\n"			\
46	"	.align	2\n"					\
47	"3:	mov	%0, %3\n"				\
48	"	b	2b\n"					\
49	"	.previous\n"					\
50	"	.section __ex_table,\"a\"\n"			\
51	"	.align	3\n"					\
52	"	.long	1b, 3b\n"				\
53	"	.previous"					\
54	: "=r" (err)						\
55	: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
56
57#define __put_user_asm_half(x,addr,err)				\
58({								\
59	unsigned long __temp = (unsigned long)(x);		\
60	unsigned long __ptr  = (unsigned long)(addr);		\
61	__put_user_asm_byte(__temp, __ptr, err);		\
62	__put_user_asm_byte(__temp >> 8, __ptr + 1, err);	\
63})
64
65#define __put_user_asm_word(x,addr,err)				\
66	__asm__ __volatile__(					\
67	"1:	strt	%1,[%2],#0\n"				\
68	"2:\n"							\
69	"	.section .fixup,\"ax\"\n"			\
70	"	.align	2\n"					\
71	"3:	mov	%0, %3\n"				\
72	"	b	2b\n"					\
73	"	.previous\n"					\
74	"	.section __ex_table,\"a\"\n"			\
75	"	.align	3\n"					\
76	"	.long	1b, 3b\n"				\
77	"	.previous"					\
78	: "=r" (err)						\
79	: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
80
81#define __get_user_asm_byte(x,addr,err)				\
82	__asm__ __volatile__(					\
83	"1:	ldrbt	%1,[%2],#0\n"				\
84	"2:\n"							\
85	"	.section .fixup,\"ax\"\n"			\
86	"	.align	2\n"					\
87	"3:	mov	%0, %3\n"				\
88	"	mov	%1, #0\n"				\
89	"	b	2b\n"					\
90	"	.previous\n"					\
91	"	.section __ex_table,\"a\"\n"			\
92	"	.align	3\n"					\
93	"	.long	1b, 3b\n"				\
94	"	.previous"					\
95	: "=r" (err), "=&r" (x)					\
96	: "r" (addr), "i" (-EFAULT), "0" (err))
97
98#define __get_user_asm_half(x,addr,err)				\
99({								\
100	unsigned long __b1, __b2, __ptr = (unsigned long)addr;	\
101	__get_user_asm_byte(__b1, __ptr, err);			\
102	__get_user_asm_byte(__b2, __ptr + 1, err);		\
103	(x) = __b1 | (__b2 << 8);				\
104})
105
106
107#define __get_user_asm_word(x,addr,err)				\
108	__asm__ __volatile__(					\
109	"1:	ldrt	%1,[%2],#0\n"				\
110	"2:\n"							\
111	"	.section .fixup,\"ax\"\n"			\
112	"	.align	2\n"					\
113	"3:	mov	%0, %3\n"				\
114	"	mov	%1, #0\n"				\
115	"	b	2b\n"					\
116	"	.previous\n"					\
117	"	.section __ex_table,\"a\"\n"			\
118	"	.align	3\n"					\
119	"	.long	1b, 3b\n"				\
120	"	.previous"					\
121	: "=r" (err), "=&r" (x)					\
122	: "r" (addr), "i" (-EFAULT), "0" (err))
123
124extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n);
125#define __do_copy_from_user(to,from,n)				\
126	(n) = __arch_copy_from_user(to,from,n)
127
128extern unsigned long __arch_copy_to_user(void *to, const void *from, unsigned long n);
129#define __do_copy_to_user(to,from,n)				\
130	(n) = __arch_copy_to_user(to,from,n)
131
132extern unsigned long __arch_clear_user(void *addr, unsigned long n);
133#define __do_clear_user(addr,sz)				\
134	(sz) = __arch_clear_user(addr,sz)
135
136extern unsigned long __arch_strncpy_from_user(char *to, const char *from, unsigned long count);
137#define __do_strncpy_from_user(dst,src,count,res)		\
138	(res) = __arch_strncpy_from_user(dst,src,count)
139
140extern unsigned long __arch_strnlen_user(const char *s, long n);
141#define __do_strnlen_user(s,n,res)					\
142	(res) = __arch_strnlen_user(s,n)
143