summaryrefslogtreecommitdiffstats
path: root/include/asm-arm/proc-armo/uaccess.h
blob: 1a6b950edb3ff688afaa8cf719e352da541f57c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * linux/include/asm-arm/proc-armo/segment.h
 *
 * Copyright (C) 1996 Russell King
 */

/*
 * The fs functions are implemented on the ARM2 and ARM3 architectures
 * manually.
 * Use *_user functions to access user memory with faulting behaving
 *   as though the user is accessing the memory.
 * Use set_fs(get_ds()) and then the *_user functions to allow them to
 *   access kernel memory.
 */

/*
 * These are the values used to represent the user `fs' and the kernel `ds'
 */
#define KERNEL_DS	0x03000000
#define USER_DS   	0x02000000

#define get_ds()	(KERNEL_DS)
#define get_fs()	(current->addr_limit)
#define segment_eq(a,b)	((a) == (b))

extern uaccess_t uaccess_user, uaccess_kernel;

extern __inline__ void set_fs (mm_segment_t fs)
{
	current->addr_limit = fs;
	current->tss.uaccess = fs == USER_DS ? &uaccess_user : &uaccess_kernel;
}

#define __range_ok(addr,size) ({					\
	unsigned long flag, sum;					\
	__asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \
		: "=&r" (flag), "=&r" (sum)				\
		: "r" (addr), "Ir" (size), "0" (current->addr_limit)	\
		: "cc");						\
	flag; })

#define __addr_ok(addr) ({						\
	unsigned long flag;						\
	__asm__ __volatile__("cmp %2, %0; movlo %0, #0"			\
		: "=&r" (flag)						\
		: "0" (current->addr_limit), "r" (addr)			\
		: "cc");						\
	(flag == 0); })

#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)

#define __put_user_asm_byte(x,addr,err)					\
	__asm__ __volatile__(						\
	"	mov	r0, %1\n"					\
	"	mov	r1, %2\n"					\
	"	mov	r2, %0\n"					\
	"	mov	lr, pc\n"					\
	"	mov	pc, %3\n"					\
	"	mov	%0, r2\n"					\
	: "=r" (err)							\
	: "r" (x), "r" (addr), "r" (current->tss.uaccess->put_byte),	\
	  "0" (err)							\
	: "r0", "r1", "r2", "lr")

#define __put_user_asm_half(x,addr,err)					\
	__asm__ __volatile__(						\
	"	mov	r0, %1\n"					\
	"	mov	r1, %2\n"					\
	"	mov	r2, %0\n"					\
	"	mov	lr, pc\n"					\
	"	mov	pc, %3\n"					\
	"	mov	%0, r2\n"					\
	: "=r" (err)							\
	: "r" (x), "r" (addr), "r" (current->tss.uaccess->put_half),	\
	  "0" (err)							\
	: "r0", "r1", "r2", "lr")

#define __put_user_asm_word(x,addr,err)					\
	__asm__ __volatile__(						\
	"	mov	r0, %1\n"					\
	"	mov	r1, %2\n"					\
	"	mov	r2, %0\n"					\
	"	mov	lr, pc\n"					\
	"	mov	pc, %3\n"					\
	"	mov	%0, r2\n"					\
	: "=r" (err)							\
	: "r" (x), "r" (addr), "r" (current->tss.uaccess->put_word),	\
	  "0" (err)							\
	: "r0", "r1", "r2", "lr")

#define __get_user_asm_byte(x,addr,err)					\
	__asm__ __volatile__(						\
	"	mov	r0, %2\n"					\
	"	mov	r1, %0\n"					\
	"	mov	lr, pc\n"					\
	"	mov	pc, %3\n"					\
	"	mov	%0, r1\n"					\
	"	mov	%1, r0\n"					\
	: "=r" (err), "=r" (x)						\
	: "r" (addr), "r" (current->tss.uaccess->get_byte), "0" (err)	\
	: "r0", "r1", "r2", "lr")

#define __get_user_asm_half(x,addr,err)					\
	__asm__ __volatile__(						\
	"	mov	r0, %2\n"					\
	"	mov	r1, %0\n"					\
	"	mov	lr, pc\n"					\
	"	mov	pc, %3\n"					\
	"	mov	%0, r1\n"					\
	"	mov	%1, r0\n"					\
	: "=r" (err), "=r" (x)						\
	: "r" (addr), "r" (current->tss.uaccess->get_half), "0" (err)	\
	: "r0", "r1", "r2", "lr")

#define __get_user_asm_word(x,addr,err)					\
	__asm__ __volatile__(						\
	"	mov	r0, %2\n"					\
	"	mov	r1, %0\n"					\
	"	mov	lr, pc\n"					\
	"	mov	pc, %3\n"					\
	"	mov	%0, r1\n"					\
	"	mov	%1, r0\n"					\
	: "=r" (err), "=r" (x)						\
	: "r" (addr), "r" (current->tss.uaccess->get_word), "0" (err)	\
	: "r0", "r1", "r2", "lr")

#define __do_copy_from_user(to,from,n)					\
	(n) = current->tss.uaccess->copy_from_user((to),(from),(n))

#define __do_copy_to_user(to,from,n)					\
	(n) = current->tss.uaccess->copy_to_user((to),(from),(n))

#define __do_clear_user(addr,sz)					\
	(sz) = current->tss.uaccess->clear_user((addr),(sz))

#define __do_strncpy_from_user(dst,src,count,res)			\
	(res) = current->tss.uaccess->strncpy_from_user(dst,src,count)

#define __do_strlen_user(s,res)						\
	(res) = current->tss.uaccess->strlen_user(s)