1/*
2 *  linux/include/asm-arm/proc-armo/uaccess.h
3 *
4 *  Copyright (C) 1996 Russell King
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
11/*
12 * The fs functions are implemented on the ARM2 and ARM3 architectures
13 * manually.
14 * Use *_user functions to access user memory with faulting behaving
15 *   as though the user is accessing the memory.
16 * Use set_fs(get_ds()) and then the *_user functions to allow them to
17 *   access kernel memory.
18 */
19
20#define KERNEL_DS	0x03FFFFFF
21#define USER_DS   	0x02000000
22
23extern uaccess_t uaccess_user, uaccess_kernel;
24
25static inline void set_fs (mm_segment_t fs)
26{
27	current_thread_info()->addr_limit = fs;
28	current->thread.uaccess = (fs == USER_DS ? &uaccess_user : &uaccess_kernel);
29}
30
31#define __range_ok(addr,size) ({					\
32	unsigned long flag, roksum;					\
33	__asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \
34		: "=&r" (flag), "=&r" (roksum)				\
35		: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit)	\
36		: "cc");						\
37	flag; })
38
39#define __addr_ok(addr) ({						\
40	unsigned long flag;						\
41	__asm__ __volatile__("cmp %2, %0; movlo %0, #0"			\
42		: "=&r" (flag)						\
43		: "0" (current_thread_info()->addr_limit), "r" (addr)	\
44		: "cc");						\
45	(flag == 0); })
46
47#define __put_user_asm_byte(x,addr,err)					\
48	__asm__ __volatile__(						\
49	"	mov	r0, %1\n"					\
50	"	mov	r1, %2\n"					\
51	"	mov	r2, %0\n"					\
52	"	mov	lr, pc\n"					\
53	"	mov	pc, %3\n"					\
54	"	mov	%0, r2\n"					\
55	: "=r" (err)							\
56	: "r" (x), "r" (addr), "r" (current->thread.uaccess->put_byte),	\
57	  "0" (err)							\
58	: "r0", "r1", "r2", "lr")
59
60#define __put_user_asm_half(x,addr,err)					\
61	__asm__ __volatile__(						\
62	"	mov	r0, %1\n"					\
63	"	mov	r1, %2\n"					\
64	"	mov	r2, %0\n"					\
65	"	mov	lr, pc\n"					\
66	"	mov	pc, %3\n"					\
67	"	mov	%0, r2\n"					\
68	: "=r" (err)							\
69	: "r" (x), "r" (addr), "r" (current->thread.uaccess->put_half),	\
70	  "0" (err)							\
71	: "r0", "r1", "r2", "lr")
72
73#define __put_user_asm_word(x,addr,err)					\
74	__asm__ __volatile__(						\
75	"	mov	r0, %1\n"					\
76	"	mov	r1, %2\n"					\
77	"	mov	r2, %0\n"					\
78	"	mov	lr, pc\n"					\
79	"	mov	pc, %3\n"					\
80	"	mov	%0, r2\n"					\
81	: "=r" (err)							\
82	: "r" (x), "r" (addr), "r" (current->thread.uaccess->put_word),	\
83	  "0" (err)							\
84	: "r0", "r1", "r2", "lr")
85
86#define __put_user_asm_dword(x,addr,err)                                 \
87        __asm__ __volatile__(                                           \
88        "       mov     r0, %1\n"                                       \
89        "       mov     r1, %2\n"                                       \
90        "       mov     r2, %0\n"                                       \
91        "       mov     lr, pc\n"                                       \
92        "       mov     pc, %3\n"                                       \
93        "       mov     %0, r2\n"                                       \
94        : "=r" (err)                                                    \
95        : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_dword), \
96          "0" (err)                                                     \
97        : "r0", "r1", "r2", "lr")
98
99#define __get_user_asm_byte(x,addr,err)					\
100	__asm__ __volatile__(						\
101	"	mov	r0, %2\n"					\
102	"	mov	r1, %0\n"					\
103	"	mov	lr, pc\n"					\
104	"	mov	pc, %3\n"					\
105	"	mov	%0, r1\n"					\
106	"	mov	%1, r0\n"					\
107	: "=r" (err), "=r" (x)						\
108	: "r" (addr), "r" (current->thread.uaccess->get_byte), "0" (err)	\
109	: "r0", "r1", "r2", "lr")
110
111#define __get_user_asm_half(x,addr,err)					\
112	__asm__ __volatile__(						\
113	"	mov	r0, %2\n"					\
114	"	mov	r1, %0\n"					\
115	"	mov	lr, pc\n"					\
116	"	mov	pc, %3\n"					\
117	"	mov	%0, r1\n"					\
118	"	mov	%1, r0\n"					\
119	: "=r" (err), "=r" (x)						\
120	: "r" (addr), "r" (current->thread.uaccess->get_half), "0" (err)	\
121	: "r0", "r1", "r2", "lr")
122
123#define __get_user_asm_word(x,addr,err)					\
124	__asm__ __volatile__(						\
125	"	mov	r0, %2\n"					\
126	"	mov	r1, %0\n"					\
127	"	mov	lr, pc\n"					\
128	"	mov	pc, %3\n"					\
129	"	mov	%0, r1\n"					\
130	"	mov	%1, r0\n"					\
131	: "=r" (err), "=r" (x)						\
132	: "r" (addr), "r" (current->thread.uaccess->get_word), "0" (err)	\
133	: "r0", "r1", "r2", "lr")
134
135#define __do_copy_from_user(to,from,n)					\
136	(n) = current->thread.uaccess->copy_from_user((to),(from),(n))
137
138#define __do_copy_to_user(to,from,n)					\
139	(n) = current->thread.uaccess->copy_to_user((to),(from),(n))
140
141#define __do_clear_user(addr,sz)					\
142	(sz) = current->thread.uaccess->clear_user((addr),(sz))
143
144#define __do_strncpy_from_user(dst,src,count,res)			\
145	(res) = current->thread.uaccess->strncpy_from_user(dst,src,count)
146
147#define __do_strnlen_user(s,n,res)					\
148	(res) = current->thread.uaccess->strnlen_user(s,n)
149