1 #ifndef __PARISC_UACCESS_H
2 #define __PARISC_UACCESS_H
5 * User space memory access functions
7 #include <linux/sched.h>
9 #include <asm/system.h>
10 #include <asm/cache.h>
11 #include <asm-generic/uaccess.h>
14 #define VERIFY_WRITE 1
16 #define KERNEL_DS ((mm_segment_t){0})
17 #define USER_DS ((mm_segment_t){1})
19 #define segment_eq(a,b) ((a).seg == (b).seg)
21 #define get_ds() (KERNEL_DS)
22 #define get_fs() (current_thread_info()->addr_limit)
23 #define set_fs(x) (current_thread_info()->addr_limit = (x))
26 * Note that since kernel addresses are in a separate address space on
27 * parisc, we don't need to do anything for access_ok() or verify_area().
28 * We just let the page fault handler do the right thing. This also means
29 * that put_user is the same as __put_user, etc.
32 extern int __get_kernel_bad(void);
33 extern int __get_user_bad(void);
34 extern int __put_kernel_bad(void);
35 extern int __put_user_bad(void);
37 #define access_ok(type,addr,size) (1)
38 #define verify_area(type,addr,size) (0)
40 #define put_user __put_user
41 #define get_user __get_user
43 #if BITS_PER_LONG == 32
44 #define LDD_KERNEL(ptr) __get_kernel_bad();
45 #define LDD_USER(ptr) __get_user_bad();
46 #define STD_KERNEL(x, ptr) __put_kernel_asm64(x,ptr)
47 #define STD_USER(x, ptr) __put_user_asm64(x,ptr)
49 #define LDD_KERNEL(ptr) __get_kernel_asm("ldd",ptr)
50 #define LDD_USER(ptr) __get_user_asm("ldd",ptr)
51 #define STD_KERNEL(x, ptr) __put_kernel_asm("std",x,ptr)
52 #define STD_USER(x, ptr) __put_user_asm("std",x,ptr)
56 * The exception table contains two values: the first is an address
57 * for an instruction that is allowed to fault, and the second is
58 * the address to the fixup routine.
61 struct exception_table_entry {
62 unsigned long insn; /* address of insn that is allowed to fault. */
63 long fixup; /* fixup routine */
67 * The page fault handler stores, in a per-cpu area, the following information
68 * if a fixup routine is available.
70 struct exception_data {
71 unsigned long fault_ip;
72 unsigned long fault_space;
73 unsigned long fault_addr;
76 #define __get_user(x,ptr) \
78 register long __gu_err __asm__ ("r8") = 0; \
79 register long __gu_val __asm__ ("r9") = 0; \
81 if (segment_eq(get_fs(),KERNEL_DS)) { \
82 switch (sizeof(*(ptr))) { \
83 case 1: __get_kernel_asm("ldb",ptr); break; \
84 case 2: __get_kernel_asm("ldh",ptr); break; \
85 case 4: __get_kernel_asm("ldw",ptr); break; \
86 case 8: LDD_KERNEL(ptr); break; \
87 default: __get_kernel_bad(); break; \
91 switch (sizeof(*(ptr))) { \
92 case 1: __get_user_asm("ldb",ptr); break; \
93 case 2: __get_user_asm("ldh",ptr); break; \
94 case 4: __get_user_asm("ldw",ptr); break; \
95 case 8: LDD_USER(ptr); break; \
96 default: __get_user_bad(); break; \
100 (x) = (__typeof__(*(ptr))) __gu_val; \
105 #define __get_kernel_asm(ldx,ptr) \
106 __asm__("\n1:\t" ldx "\t0(%2),%0\n" \
107 "\t.section __ex_table,\"aw\"\n" \
108 "\t.dword\t1b,fixup_get_user_skip_1\n" \
110 : "=r"(__gu_val), "=r"(__gu_err) \
111 : "r"(ptr), "1"(__gu_err) \
114 #define __get_user_asm(ldx,ptr) \
115 __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
116 "\t.section __ex_table,\"aw\"\n" \
117 "\t.dword\t1b,fixup_get_user_skip_1\n" \
119 : "=r"(__gu_val), "=r"(__gu_err) \
120 : "r"(ptr), "1"(__gu_err) \
123 #define __get_kernel_asm(ldx,ptr) \
124 __asm__("\n1:\t" ldx "\t0(%2),%0\n" \
125 "\t.section __ex_table,\"aw\"\n" \
126 "\t.word\t1b,fixup_get_user_skip_1\n" \
128 : "=r"(__gu_val), "=r"(__gu_err) \
129 : "r"(ptr), "1"(__gu_err) \
132 #define __get_user_asm(ldx,ptr) \
133 __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
134 "\t.section __ex_table,\"aw\"\n" \
135 "\t.word\t1b,fixup_get_user_skip_1\n" \
137 : "=r"(__gu_val), "=r"(__gu_err) \
138 : "r"(ptr), "1"(__gu_err) \
140 #endif /* !__LP64__ */
142 #define __put_user(x,ptr) \
144 register long __pu_err __asm__ ("r8") = 0; \
146 if (segment_eq(get_fs(),KERNEL_DS)) { \
147 switch (sizeof(*(ptr))) { \
148 case 1: __put_kernel_asm("stb",x,ptr); break; \
149 case 2: __put_kernel_asm("sth",x,ptr); break; \
150 case 4: __put_kernel_asm("stw",x,ptr); break; \
151 case 8: STD_KERNEL(x,ptr); break; \
152 default: __put_kernel_bad(); break; \
156 switch (sizeof(*(ptr))) { \
157 case 1: __put_user_asm("stb",x,ptr); break; \
158 case 2: __put_user_asm("sth",x,ptr); break; \
159 case 4: __put_user_asm("stw",x,ptr); break; \
160 case 8: STD_USER(x,ptr); break; \
161 default: __put_user_bad(); break; \
169 * The "__put_user/kernel_asm()" macros tell gcc they read from memory
170 * instead of writing. This is because they do not write to any memory
171 * gcc knows about, so there are no aliasing issues.
175 #define __put_kernel_asm(stx,x,ptr) \
176 __asm__ __volatile__ ( \
177 "\n1:\t" stx "\t%2,0(%1)\n" \
178 "\t.section __ex_table,\"aw\"\n" \
179 "\t.dword\t1b,fixup_put_user_skip_1\n" \
182 : "r"(ptr), "r"(x), "0"(__pu_err))
184 #define __put_user_asm(stx,x,ptr) \
185 __asm__ __volatile__ ( \
186 "\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
187 "\t.section __ex_table,\"aw\"\n" \
188 "\t.dword\t1b,fixup_put_user_skip_1\n" \
191 : "r"(ptr), "r"(x), "0"(__pu_err) \
194 #define __put_kernel_asm(stx,x,ptr) \
195 __asm__ __volatile__ ( \
196 "\n1:\t" stx "\t%2,0(%1)\n" \
197 "\t.section __ex_table,\"aw\"\n" \
198 "\t.word\t1b,fixup_put_user_skip_1\n" \
201 : "r"(ptr), "r"(x), "0"(__pu_err) \
204 #define __put_user_asm(stx,x,ptr) \
205 __asm__ __volatile__ ( \
206 "\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
207 "\t.section __ex_table,\"aw\"\n" \
208 "\t.word\t1b,fixup_put_user_skip_1\n" \
211 : "r"(ptr), "r"(x), "0"(__pu_err) \
214 #define __put_kernel_asm64(__val,ptr) do { \
215 u64 __val64 = (u64)(__val); \
216 u32 hi = (__val64) >> 32; \
217 u32 lo = (__val64) & 0xffffffff; \
218 __asm__ __volatile__ ( \
219 "\n1:\tstw %2,0(%1)\n" \
220 "\n2:\tstw %3,4(%1)\n" \
221 "\t.section __ex_table,\"aw\"\n" \
222 "\t.word\t1b,fixup_put_user_skip_2\n" \
223 "\t.word\t2b,fixup_put_user_skip_1\n" \
226 : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
230 #define __put_user_asm64(__val,ptr) do { \
231 u64 __val64 = (u64)__val; \
232 u32 hi = (__val64) >> 32; \
233 u32 lo = (__val64) & 0xffffffff; \
234 __asm__ __volatile__ ( \
235 "\n1:\tstw %2,0(%%sr3,%1)\n" \
236 "\n2:\tstw %3,4(%%sr3,%1)\n" \
237 "\t.section __ex_table,\"aw\"\n" \
238 "\t.word\t1b,fixup_get_user_skip_2\n" \
239 "\t.word\t2b,fixup_get_user_skip_1\n" \
242 : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
246 #endif /* !__LP64__ */
250 * Complex access routines -- external declarations
253 extern unsigned long lcopy_to_user(void __user *, const void *, unsigned long);
254 extern unsigned long lcopy_from_user(void *, const void __user *, unsigned long);
255 extern unsigned long lcopy_in_user(void __user *, const void __user *, unsigned long);
256 extern long lstrncpy_from_user(char *, const char __user *, long);
257 extern unsigned lclear_user(void __user *,unsigned long);
258 extern long lstrnlen_user(const char __user *,long);
261 * Complex access routines -- macros
264 #define strncpy_from_user lstrncpy_from_user
265 #define strnlen_user lstrnlen_user
266 #define strlen_user(str) lstrnlen_user(str, 0x7fffffffL)
267 #define clear_user lclear_user
268 #define __clear_user lclear_user
270 unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len);
271 #define __copy_to_user copy_to_user
272 unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len);
273 #define __copy_from_user copy_from_user
274 unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len);
275 #define __copy_in_user copy_in_user
276 #define __copy_to_user_inatomic __copy_to_user
277 #define __copy_from_user_inatomic __copy_from_user
279 #endif /* __PARISC_UACCESS_H */