Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
parisc
include
asm
uaccess.h
Go to the documentation of this file.
1
#ifndef __PARISC_UACCESS_H
2
#define __PARISC_UACCESS_H
3
4
/*
5
* User space memory access functions
6
*/
7
#include <asm/page.h>
8
#include <asm/cache.h>
9
#include <asm/errno.h>
10
#include <
asm-generic/uaccess-unaligned.h
>
11
12
#define VERIFY_READ 0
13
#define VERIFY_WRITE 1
14
15
#define KERNEL_DS ((mm_segment_t){0})
16
#define USER_DS ((mm_segment_t){1})
17
18
#define segment_eq(a,b) ((a).seg == (b).seg)
19
20
#define get_ds() (KERNEL_DS)
21
#define get_fs() (current_thread_info()->addr_limit)
22
#define set_fs(x) (current_thread_info()->addr_limit = (x))
23
24
/*
25
* Note that since kernel addresses are in a separate address space on
26
* parisc, we don't need to do anything for access_ok().
27
* We just let the page fault handler do the right thing. This also means
28
* that put_user is the same as __put_user, etc.
29
*/
30
31
extern
int
__get_kernel_bad
(
void
);
32
extern
int
__get_user_bad
(
void
);
33
extern
int
__put_kernel_bad
(
void
);
34
extern
int
__put_user_bad
(
void
);
35
36
static
inline
long
access_ok
(
int
type
,
const
void
__user *
addr
,
37
unsigned
long
size
)
38
{
39
return
1;
40
}
41
42
#define put_user __put_user
43
#define get_user __get_user
44
45
#if !defined(CONFIG_64BIT)
46
#define LDD_KERNEL(ptr) __get_kernel_bad();
47
#define LDD_USER(ptr) __get_user_bad();
48
#define STD_KERNEL(x, ptr) __put_kernel_asm64(x,ptr)
49
#define STD_USER(x, ptr) __put_user_asm64(x,ptr)
50
#define ASM_WORD_INSN ".word\t"
51
#else
52
#define LDD_KERNEL(ptr) __get_kernel_asm("ldd",ptr)
53
#define LDD_USER(ptr) __get_user_asm("ldd",ptr)
54
#define STD_KERNEL(x, ptr) __put_kernel_asm("std",x,ptr)
55
#define STD_USER(x, ptr) __put_user_asm("std",x,ptr)
56
#define ASM_WORD_INSN ".dword\t"
57
#endif
58
59
/*
60
* The exception table contains two values: the first is an address
61
* for an instruction that is allowed to fault, and the second is
62
* the address to the fixup routine.
63
*/
64
65
struct
exception_table_entry
{
66
unsigned
long
insn
;
/* address of insn that is allowed to fault. */
67
long
fixup
;
/* fixup routine */
68
};
69
70
#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
71
".section __ex_table,\"aw\"\n" \
72
ASM_WORD_INSN #fault_addr ", " #except_addr "\n\t" \
73
".previous\n"
74
75
/*
76
* The page fault handler stores, in a per-cpu area, the following information
77
* if a fixup routine is available.
78
*/
79
struct
exception_data
{
80
unsigned
long
fault_ip
;
81
unsigned
long
fault_space
;
82
unsigned
long
fault_addr
;
83
};
84
85
#define __get_user(x,ptr) \
86
({ \
87
register long __gu_err __asm__ ("r8") = 0; \
88
register long __gu_val __asm__ ("r9") = 0; \
89
\
90
if (segment_eq(get_fs(),KERNEL_DS)) { \
91
switch (sizeof(*(ptr))) { \
92
case 1: __get_kernel_asm("ldb",ptr); break; \
93
case 2: __get_kernel_asm("ldh",ptr); break; \
94
case 4: __get_kernel_asm("ldw",ptr); break; \
95
case 8: LDD_KERNEL(ptr); break; \
96
default: __get_kernel_bad(); break; \
97
} \
98
} \
99
else { \
100
switch (sizeof(*(ptr))) { \
101
case 1: __get_user_asm("ldb",ptr); break; \
102
case 2: __get_user_asm("ldh",ptr); break; \
103
case 4: __get_user_asm("ldw",ptr); break; \
104
case 8: LDD_USER(ptr); break; \
105
default: __get_user_bad(); break; \
106
} \
107
} \
108
\
109
(x) = (__typeof__(*(ptr))) __gu_val; \
110
__gu_err; \
111
})
112
113
#define __get_kernel_asm(ldx,ptr) \
114
__asm__("\n1:\t" ldx "\t0(%2),%0\n\t" \
115
ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\
116
: "=r"(__gu_val), "=r"(__gu_err) \
117
: "r"(ptr), "1"(__gu_err) \
118
: "r1");
119
120
#define __get_user_asm(ldx,ptr) \
121
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n\t" \
122
ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_get_user_skip_1)\
123
: "=r"(__gu_val), "=r"(__gu_err) \
124
: "r"(ptr), "1"(__gu_err) \
125
: "r1");
126
127
#define __put_user(x,ptr) \
128
({ \
129
register long __pu_err __asm__ ("r8") = 0; \
130
__typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
131
\
132
if (segment_eq(get_fs(),KERNEL_DS)) { \
133
switch (sizeof(*(ptr))) { \
134
case 1: __put_kernel_asm("stb",__x,ptr); break; \
135
case 2: __put_kernel_asm("sth",__x,ptr); break; \
136
case 4: __put_kernel_asm("stw",__x,ptr); break; \
137
case 8: STD_KERNEL(__x,ptr); break; \
138
default: __put_kernel_bad(); break; \
139
} \
140
} \
141
else { \
142
switch (sizeof(*(ptr))) { \
143
case 1: __put_user_asm("stb",__x,ptr); break; \
144
case 2: __put_user_asm("sth",__x,ptr); break; \
145
case 4: __put_user_asm("stw",__x,ptr); break; \
146
case 8: STD_USER(__x,ptr); break; \
147
default: __put_user_bad(); break; \
148
} \
149
} \
150
\
151
__pu_err; \
152
})
153
154
/*
155
* The "__put_user/kernel_asm()" macros tell gcc they read from memory
156
* instead of writing. This is because they do not write to any memory
157
* gcc knows about, so there are no aliasing issues. These macros must
158
* also be aware that "fixup_put_user_skip_[12]" are executed in the
159
* context of the fault, and any registers used there must be listed
160
* as clobbers. In this case only "r1" is used by the current routines.
161
* r8/r9 are already listed as err/val.
162
*/
163
164
#define __put_kernel_asm(stx,x,ptr) \
165
__asm__ __volatile__ ( \
166
"\n1:\t" stx "\t%2,0(%1)\n\t" \
167
ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\
168
: "=r"(__pu_err) \
169
: "r"(ptr), "r"(x), "0"(__pu_err) \
170
: "r1")
171
172
#define __put_user_asm(stx,x,ptr) \
173
__asm__ __volatile__ ( \
174
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n\t" \
175
ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\
176
: "=r"(__pu_err) \
177
: "r"(ptr), "r"(x), "0"(__pu_err) \
178
: "r1")
179
180
181
#if !defined(CONFIG_64BIT)
182
183
#define __put_kernel_asm64(__val,ptr) do { \
184
u64 __val64 = (u64)(__val); \
185
u32 hi = (__val64) >> 32; \
186
u32 lo = (__val64) & 0xffffffff; \
187
__asm__ __volatile__ ( \
188
"\n1:\tstw %2,0(%1)" \
189
"\n2:\tstw %3,4(%1)\n\t" \
190
ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
191
ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
192
: "=r"(__pu_err) \
193
: "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
194
: "r1"); \
195
} while (0)
196
197
#define __put_user_asm64(__val,ptr) do { \
198
u64 __val64 = (u64)(__val); \
199
u32 hi = (__val64) >> 32; \
200
u32 lo = (__val64) & 0xffffffff; \
201
__asm__ __volatile__ ( \
202
"\n1:\tstw %2,0(%%sr3,%1)" \
203
"\n2:\tstw %3,4(%%sr3,%1)\n\t" \
204
ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
205
ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
206
: "=r"(__pu_err) \
207
: "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
208
: "r1"); \
209
} while (0)
210
211
#endif
/* !defined(CONFIG_64BIT) */
212
213
214
/*
215
* Complex access routines -- external declarations
216
*/
217
218
extern
unsigned
long
lcopy_to_user
(
void
__user *,
const
void
*,
unsigned
long
);
219
extern
unsigned
long
lcopy_from_user
(
void
*,
const
void
__user *,
unsigned
long
);
220
extern
unsigned
long
lcopy_in_user
(
void
__user *,
const
void
__user *,
unsigned
long
);
221
extern
long
strncpy_from_user
(
char
*,
const
char
__user *,
long
);
222
extern
unsigned
lclear_user
(
void
__user *,
unsigned
long
);
223
extern
long
lstrnlen_user
(
const
char
__user *,
long
);
224
/*
225
* Complex access routines -- macros
226
*/
227
#define user_addr_max() (~0UL)
228
229
#define strnlen_user lstrnlen_user
230
#define strlen_user(str) lstrnlen_user(str, 0x7fffffffL)
231
#define clear_user lclear_user
232
#define __clear_user lclear_user
233
234
unsigned
long
copy_to_user
(
void
__user *
dst
,
const
void
*
src
,
unsigned
long
len);
235
#define __copy_to_user copy_to_user
236
unsigned
long
__copy_from_user
(
void
*
dst
,
const
void
__user *
src
,
unsigned
long
len);
237
unsigned
long
copy_in_user
(
void
__user *
dst
,
const
void
__user *
src
,
unsigned
long
len);
238
#define __copy_in_user copy_in_user
239
#define __copy_to_user_inatomic __copy_to_user
240
#define __copy_from_user_inatomic __copy_from_user
241
242
extern
void
copy_from_user_overflow
(
void
)
243
#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
244
__compiletime_error
(
"copy_from_user() buffer size is not provably correct"
)
245
#else
246
__compiletime_warning
(
"copy_from_user() buffer size is not provably correct"
)
247
#endif
248
;
249
250
static
inline
unsigned
long
__must_check
copy_from_user
(
void
*to,
251
const
void
__user *
from
,
252
unsigned
long
n
)
253
{
254
int
sz =
__compiletime_object_size
(to);
255
int
ret
= -
EFAULT
;
256
257
if
(
likely
(sz == -1 || !__builtin_constant_p(n) || sz >= n))
258
ret =
__copy_from_user
(to, from, n);
259
else
260
copy_from_user_overflow
();
261
262
return
ret
;
263
}
264
265
struct
pt_regs
;
266
int
fixup_exception
(
struct
pt_regs
*
regs
);
267
268
#endif
/* __PARISC_UACCESS_H */
Generated on Thu Jan 10 2013 12:50:46 for Linux Kernel by
1.8.2