Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/openrisc/include/asm/uaccess.h
26481 views
1
/* SPDX-License-Identifier: GPL-2.0-or-later */
2
/*
3
* OpenRISC Linux
4
*
5
* Linux architectural port borrowing liberally from similar works of
6
* others. All original copyrights apply as per the original source
7
* declaration.
8
*
9
* OpenRISC implementation:
10
* Copyright (C) 2003 Matjaz Breskvar <[email protected]>
11
* Copyright (C) 2010-2011 Jonas Bonn <[email protected]>
12
* et al.
13
*/
14
15
#ifndef __ASM_OPENRISC_UACCESS_H
16
#define __ASM_OPENRISC_UACCESS_H
17
18
/*
19
* User space memory access functions
20
*/
21
#include <linux/prefetch.h>
22
#include <linux/string.h>
23
#include <asm/page.h>
24
#include <asm/extable.h>
25
#include <asm-generic/access_ok.h>
26
27
/*
28
* These are the main single-value transfer routines. They automatically
29
* use the right size if we just have the right pointer type.
30
*
31
* This gets kind of ugly. We want to return _two_ values in "get_user()"
32
* and yet we don't want to do any pointers, because that is too much
33
* of a performance impact. Thus we have a few rather ugly macros here,
34
* and hide all the uglyness from the user.
35
*
36
* The "__xxx" versions of the user access functions are versions that
37
* do not verify the address space, that must have been done previously
38
* with a separate "access_ok()" call (this is used when we do multiple
39
* accesses to the same area of user memory).
40
*
41
* As we use the same address space for kernel and user data on the
42
* PowerPC, we can just do these as direct assignments. (Of course, the
43
* exception handling means that it's no longer "just"...)
44
*/
45
#define get_user(x, ptr) \
46
__get_user_check((x), (ptr), sizeof(*(ptr)))
47
#define put_user(x, ptr) \
48
__put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
49
50
#define __get_user(x, ptr) \
51
__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
52
#define __put_user(x, ptr) \
53
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
54
55
extern long __put_user_bad(void);
56
57
#define __put_user_nocheck(x, ptr, size) \
58
({ \
59
long __pu_err; \
60
__put_user_size((x), (ptr), (size), __pu_err); \
61
__pu_err; \
62
})
63
64
#define __put_user_check(x, ptr, size) \
65
({ \
66
long __pu_err = -EFAULT; \
67
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
68
if (access_ok(__pu_addr, size)) \
69
__put_user_size((x), __pu_addr, (size), __pu_err); \
70
__pu_err; \
71
})
72
73
#define __put_user_size(x, ptr, size, retval) \
74
do { \
75
retval = 0; \
76
switch (size) { \
77
case 1: __put_user_asm(x, ptr, retval, "l.sb"); break; \
78
case 2: __put_user_asm(x, ptr, retval, "l.sh"); break; \
79
case 4: __put_user_asm(x, ptr, retval, "l.sw"); break; \
80
case 8: __put_user_asm2(x, ptr, retval); break; \
81
default: __put_user_bad(); \
82
} \
83
} while (0)
84
85
struct __large_struct {
86
unsigned long buf[100];
87
};
88
#define __m(x) (*(struct __large_struct *)(x))
89
90
/*
91
* We don't tell gcc that we are accessing memory, but this is OK
92
* because we do not write to any memory gcc knows about, so there
93
* are no aliasing issues.
94
*/
95
#define __put_user_asm(x, addr, err, op) \
96
__asm__ __volatile__( \
97
"1: "op" 0(%2),%1\n" \
98
"2:\n" \
99
".section .fixup,\"ax\"\n" \
100
"3: l.addi %0,r0,%3\n" \
101
" l.j 2b\n" \
102
" l.nop\n" \
103
".previous\n" \
104
".section __ex_table,\"a\"\n" \
105
" .align 2\n" \
106
" .long 1b,3b\n" \
107
".previous" \
108
: "=r"(err) \
109
: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
110
111
#define __put_user_asm2(x, addr, err) \
112
__asm__ __volatile__( \
113
"1: l.sw 0(%2),%1\n" \
114
"2: l.sw 4(%2),%H1\n" \
115
"3:\n" \
116
".section .fixup,\"ax\"\n" \
117
"4: l.addi %0,r0,%3\n" \
118
" l.j 3b\n" \
119
" l.nop\n" \
120
".previous\n" \
121
".section __ex_table,\"a\"\n" \
122
" .align 2\n" \
123
" .long 1b,4b\n" \
124
" .long 2b,4b\n" \
125
".previous" \
126
: "=r"(err) \
127
: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
128
129
#define __get_user_nocheck(x, ptr, size) \
130
({ \
131
long __gu_err; \
132
__get_user_size((x), (ptr), (size), __gu_err); \
133
__gu_err; \
134
})
135
136
#define __get_user_check(x, ptr, size) \
137
({ \
138
long __gu_err = -EFAULT; \
139
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
140
if (access_ok(__gu_addr, size)) \
141
__get_user_size((x), __gu_addr, (size), __gu_err); \
142
else \
143
(x) = (__typeof__(*(ptr))) 0; \
144
__gu_err; \
145
})
146
147
extern long __get_user_bad(void);
148
149
#define __get_user_size(x, ptr, size, retval) \
150
do { \
151
retval = 0; \
152
switch (size) { \
153
case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break; \
154
case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \
155
case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \
156
case 8: __get_user_asm2(x, ptr, retval); break; \
157
default: (x) = (__typeof__(*(ptr)))__get_user_bad(); \
158
} \
159
} while (0)
160
161
#define __get_user_asm(x, addr, err, op) \
162
{ \
163
unsigned long __gu_tmp; \
164
__asm__ __volatile__( \
165
"1: "op" %1,0(%2)\n" \
166
"2:\n" \
167
".section .fixup,\"ax\"\n" \
168
"3: l.addi %0,r0,%3\n" \
169
" l.addi %1,r0,0\n" \
170
" l.j 2b\n" \
171
" l.nop\n" \
172
".previous\n" \
173
".section __ex_table,\"a\"\n" \
174
" .align 2\n" \
175
" .long 1b,3b\n" \
176
".previous" \
177
: "=r"(err), "=r"(__gu_tmp) \
178
: "r"(addr), "i"(-EFAULT), "0"(err)); \
179
(x) = (__typeof__(*(addr)))__gu_tmp; \
180
}
181
182
#define __get_user_asm2(x, addr, err) \
183
{ \
184
unsigned long long __gu_tmp; \
185
__asm__ __volatile__( \
186
"1: l.lwz %1,0(%2)\n" \
187
"2: l.lwz %H1,4(%2)\n" \
188
"3:\n" \
189
".section .fixup,\"ax\"\n" \
190
"4: l.addi %0,r0,%3\n" \
191
" l.addi %1,r0,0\n" \
192
" l.addi %H1,r0,0\n" \
193
" l.j 3b\n" \
194
" l.nop\n" \
195
".previous\n" \
196
".section __ex_table,\"a\"\n" \
197
" .align 2\n" \
198
" .long 1b,4b\n" \
199
" .long 2b,4b\n" \
200
".previous" \
201
: "=r"(err), "=&r"(__gu_tmp) \
202
: "r"(addr), "i"(-EFAULT), "0"(err)); \
203
(x) = (__typeof__(*(addr)))( \
204
(__typeof__((x)-(x)))__gu_tmp); \
205
}
206
207
/* more complex routines */
208
209
extern unsigned long __must_check
210
__copy_tofrom_user(void *to, const void *from, unsigned long size);
211
static inline unsigned long
212
raw_copy_from_user(void *to, const void __user *from, unsigned long size)
213
{
214
return __copy_tofrom_user(to, (__force const void *)from, size);
215
}
216
static inline unsigned long
217
raw_copy_to_user(void __user *to, const void *from, unsigned long size)
218
{
219
return __copy_tofrom_user((__force void *)to, from, size);
220
}
221
#define INLINE_COPY_FROM_USER
222
#define INLINE_COPY_TO_USER
223
224
extern unsigned long __clear_user(void __user *addr, unsigned long size);
225
226
static inline __must_check unsigned long
227
clear_user(void __user *addr, unsigned long size)
228
{
229
if (likely(access_ok(addr, size)))
230
size = __clear_user(addr, size);
231
return size;
232
}
233
234
extern long strncpy_from_user(char *dest, const char __user *src, long count);
235
236
extern __must_check long strnlen_user(const char __user *str, long n);
237
238
#endif /* __ASM_OPENRISC_UACCESS_H */
239
240