1/*
2 *  linux/include/asm-arm/proc-armo/segment.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/*
21 * These are the values used to represent the user `fs' and the kernel `ds'
22 */
23#define KERNEL_DS	0x03000000
24#define USER_DS   	0x02000000
25
26extern uaccess_t uaccess_user, uaccess_kernel;
27
28static inline void set_fs (mm_segment_t fs)
29{
30	current->addr_limit = fs;
31	current->thread.uaccess = fs == USER_DS ? &uaccess_user : &uaccess_kernel;
32}
33
34#define __range_ok(addr,size) ({					\
35	unsigned long flag, sum;					\
36	__asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \
37		: "=&r" (flag), "=&r" (sum)				\
38		: "r" (addr), "Ir" (size), "0" (current->addr_limit)	\
39		: "cc");						\
40	flag; })
41
42#define __addr_ok(addr) ({						\
43	unsigned long flag;						\
44	__asm__ __volatile__("cmp %2, %0; movlo %0, #0"			\
45		: "=&r" (flag)						\
46		: "0" (current->addr_limit), "r" (addr)			\
47		: "cc");						\
48	(flag == 0); })
49
50#define __put_user_asm_byte(x,addr,err)					\
51	__asm__ __volatile__(						\
52	"	mov	r0, %1\n"					\
53	"	mov	r1, %2\n"					\
54	"	mov	r2, %0\n"					\
55	"	mov	lr, pc\n"					\
56	"	mov	pc, %3\n"					\
57	"	mov	%0, r2\n"					\
58	: "=r" (err)							\
59	: "r" (x), "r" (addr), "r" (current->thread.uaccess->put_byte),	\
60	  "0" (err)							\
61	: "r0", "r1", "r2", "lr")
62
63#define __put_user_asm_half(x,addr,err)					\
64	__asm__ __volatile__(						\
65	"	mov	r0, %1\n"					\
66	"	mov	r1, %2\n"					\
67	"	mov	r2, %0\n"					\
68	"	mov	lr, pc\n"					\
69	"	mov	pc, %3\n"					\
70	"	mov	%0, r2\n"					\
71	: "=r" (err)							\
72	: "r" (x), "r" (addr), "r" (current->thread.uaccess->put_half),	\
73	  "0" (err)							\
74	: "r0", "r1", "r2", "lr")
75
76#define __put_user_asm_word(x,addr,err)					\
77	__asm__ __volatile__(						\
78	"	mov	r0, %1\n"					\
79	"	mov	r1, %2\n"					\
80	"	mov	r2, %0\n"					\
81	"	mov	lr, pc\n"					\
82	"	mov	pc, %3\n"					\
83	"	mov	%0, r2\n"					\
84	: "=r" (err)							\
85	: "r" (x), "r" (addr), "r" (current->thread.uaccess->put_word),	\
86	  "0" (err)							\
87	: "r0", "r1", "r2", "lr")
88
89#define __get_user_asm_byte(x,addr,err)					\
90	__asm__ __volatile__(						\
91	"	mov	r0, %2\n"					\
92	"	mov	r1, %0\n"					\
93	"	mov	lr, pc\n"					\
94	"	mov	pc, %3\n"					\
95	"	mov	%0, r1\n"					\
96	"	mov	%1, r0\n"					\
97	: "=r" (err), "=r" (x)						\
98	: "r" (addr), "r" (current->thread.uaccess->get_byte), "0" (err)	\
99	: "r0", "r1", "r2", "lr")
100
101#define __get_user_asm_half(x,addr,err)					\
102	__asm__ __volatile__(						\
103	"	mov	r0, %2\n"					\
104	"	mov	r1, %0\n"					\
105	"	mov	lr, pc\n"					\
106	"	mov	pc, %3\n"					\
107	"	mov	%0, r1\n"					\
108	"	mov	%1, r0\n"					\
109	: "=r" (err), "=r" (x)						\
110	: "r" (addr), "r" (current->thread.uaccess->get_half), "0" (err)	\
111	: "r0", "r1", "r2", "lr")
112
113#define __get_user_asm_word(x,addr,err)					\
114	__asm__ __volatile__(						\
115	"	mov	r0, %2\n"					\
116	"	mov	r1, %0\n"					\
117	"	mov	lr, pc\n"					\
118	"	mov	pc, %3\n"					\
119	"	mov	%0, r1\n"					\
120	"	mov	%1, r0\n"					\
121	: "=r" (err), "=r" (x)						\
122	: "r" (addr), "r" (current->thread.uaccess->get_word), "0" (err)	\
123	: "r0", "r1", "r2", "lr")
124
125#define __do_copy_from_user(to,from,n)					\
126	(n) = current->thread.uaccess->copy_from_user((to),(from),(n))
127
128#define __do_copy_to_user(to,from,n)					\
129	(n) = current->thread.uaccess->copy_to_user((to),(from),(n))
130
131#define __do_clear_user(addr,sz)					\
132	(sz) = current->thread.uaccess->clear_user((addr),(sz))
133
134#define __do_strncpy_from_user(dst,src,count,res)			\
135	(res) = current->thread.uaccess->strncpy_from_user(dst,src,count)
136
137#define __do_strnlen_user(s,n,res)					\
138	(res) = current->thread.uaccess->strnlen_user(s,n)
139