aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-arm26/uaccess-asm.h
blob: ade76ec02995c96b48a4493aea5812523d3105af (plain) (blame)
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
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 *  linux/include/asm-arm/proc-armo/uaccess.h
 *
 *  Copyright (C) 1996 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

/*
 * 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'
 * FIXME - the KERNEL_DS should end at 0x03000000 but we want to access ROM at
 * 0x03400000. ideally we want to forbid access to the IO space inbetween.
 */
#define KERNEL_DS	0x03FFFFFF
#define USER_DS   	0x02000000

extern uaccess_t uaccess_user, uaccess_kernel;

static inline void set_fs (mm_segment_t fs)
{
	current_thread_info()->addr_limit = fs;
	current->thread.uaccess = (fs == USER_DS ? &uaccess_user : &uaccess_kernel);
}

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

#define __addr_ok(addr) ({						\
	unsigned long flag;						\
	__asm__ __volatile__("cmp %2, %0; movlo %0, #0"			\
		: "=&r" (flag)						\
		: "0" (current_thread_info()->addr_limit), "r" (addr)	\
		: "cc");						\
	(flag == 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->thread.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->thread.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->thread.uaccess->put_word),	\
	  "0" (err)							\
	: "r0", "r1", "r2", "lr")

#define __put_user_asm_dword(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->thread.uaccess->put_dword), \
          "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->thread.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->thread.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->thread.uaccess->get_word), "0" (err)	\
	: "r0", "r1", "r2", "lr")

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

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

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

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

#define __do_strnlen_user(s,n,res)					\
	(res) = current->thread.uaccess->strnlen_user(s,n)