1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __PARISC_UACCESS_H
3 #define __PARISC_UACCESS_H
6 * User space memory access functions
11 #include <linux/bug.h>
12 #include <linux/string.h>
15 * Note that since kernel addresses are in a separate address space on
16 * parisc, we don't need to do anything for access_ok().
17 * We just let the page fault handler do the right thing. This also means
18 * that put_user is the same as __put_user, etc.
21 #define access_ok(uaddr, size) \
22 ( (uaddr) == (uaddr) )
24 #define put_user __put_user
25 #define get_user __get_user
27 #if !defined(CONFIG_64BIT)
28 #define LDD_USER(sr, val, ptr) __get_user_asm64(sr, val, ptr)
29 #define STD_USER(sr, x, ptr) __put_user_asm64(sr, x, ptr)
31 #define LDD_USER(sr, val, ptr) __get_user_asm(sr, val, "ldd", ptr)
32 #define STD_USER(sr, x, ptr) __put_user_asm(sr, "std", x, ptr)
36 * The exception table contains two values: the first is the relative offset to
37 * the address of the instruction that is allowed to fault, and the second is
38 * the relative offset to the address of the fixup routine. Since relative
39 * addresses are used, 32bit values are sufficient even on 64bit kernel.
42 #define ARCH_HAS_RELATIVE_EXTABLE
43 struct exception_table_entry {
44 int insn; /* relative address of insn that is allowed to fault. */
45 int fixup; /* relative address of fixup routine */
48 #define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
49 ".section __ex_table,\"aw\"\n" \
50 ".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \
54 * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry
55 * (with lowest bit set) for which the fault handler in fixup_exception() will
56 * load -EFAULT into %r8 for a read or write fault, and zeroes the target
57 * register in case of a read fault in get_user().
59 #define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\
60 ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1)
62 #define __get_user_internal(sr, val, ptr) \
64 register long __gu_err __asm__ ("r8") = 0; \
66 switch (sizeof(*(ptr))) { \
67 case 1: __get_user_asm(sr, val, "ldb", ptr); break; \
68 case 2: __get_user_asm(sr, val, "ldh", ptr); break; \
69 case 4: __get_user_asm(sr, val, "ldw", ptr); break; \
70 case 8: LDD_USER(sr, val, ptr); break; \
71 default: BUILD_BUG(); \
77 #define __get_user(val, ptr) \
79 __get_user_internal("%%sr3,", val, ptr); \
82 #define __get_user_asm(sr, val, ldx, ptr) \
84 register long __gu_val; \
86 __asm__("1: " ldx " 0(" sr "%2),%0\n" \
88 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
89 : "=r"(__gu_val), "=r"(__gu_err) \
90 : "r"(ptr), "1"(__gu_err)); \
92 (val) = (__force __typeof__(*(ptr))) __gu_val; \
95 #define HAVE_GET_KERNEL_NOFAULT
96 #define __get_kernel_nofault(dst, src, type, err_label) \
100 __err = __get_user_internal("%%sr0,", __z, (type *)(src)); \
101 if (unlikely(__err)) \
104 *(type *)(dst) = __z; \
108 #if !defined(CONFIG_64BIT)
110 #define __get_user_asm64(sr, val, ptr) \
113 unsigned long long l; \
114 __typeof__(*(ptr)) t; \
117 __asm__(" copy %%r0,%R0\n" \
118 "1: ldw 0(" sr "%2),%0\n" \
119 "2: ldw 4(" sr "%2),%R0\n" \
121 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
122 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
123 : "=&r"(__gu_tmp.l), "=r"(__gu_err) \
124 : "r"(ptr), "1"(__gu_err)); \
126 (val) = __gu_tmp.t; \
129 #endif /* !defined(CONFIG_64BIT) */
132 #define __put_user_internal(sr, x, ptr) \
134 register long __pu_err __asm__ ("r8") = 0; \
135 __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
137 switch (sizeof(*(ptr))) { \
138 case 1: __put_user_asm(sr, "stb", __x, ptr); break; \
139 case 2: __put_user_asm(sr, "sth", __x, ptr); break; \
140 case 4: __put_user_asm(sr, "stw", __x, ptr); break; \
141 case 8: STD_USER(sr, __x, ptr); break; \
142 default: BUILD_BUG(); \
148 #define __put_user(x, ptr) \
150 __put_user_internal("%%sr3,", x, ptr); \
153 #define __put_kernel_nofault(dst, src, type, err_label) \
155 type __z = *(type *)(src); \
157 __err = __put_user_internal("%%sr0,", __z, (type *)(dst)); \
158 if (unlikely(__err)) \
166 * The "__put_user/kernel_asm()" macros tell gcc they read from memory
167 * instead of writing. This is because they do not write to any memory
168 * gcc knows about, so there are no aliasing issues. These macros must
169 * also be aware that fixups are executed in the context of the fault,
170 * and any registers used there must be listed as clobbers.
171 * r8 is already listed as err.
174 #define __put_user_asm(sr, stx, x, ptr) \
175 __asm__ __volatile__ ( \
176 "1: " stx " %2,0(" sr "%1)\n" \
178 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
180 : "r"(ptr), "r"(x), "0"(__pu_err))
183 #if !defined(CONFIG_64BIT)
185 #define __put_user_asm64(sr, __val, ptr) do { \
186 __asm__ __volatile__ ( \
187 "1: stw %2,0(" sr "%1)\n" \
188 "2: stw %R2,4(" sr "%1)\n" \
190 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
191 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
193 : "r"(ptr), "r"(__val), "0"(__pu_err)); \
196 #endif /* !defined(CONFIG_64BIT) */
200 * Complex access routines -- external declarations
203 extern long strncpy_from_user(char *, const char __user *, long);
204 extern __must_check unsigned lclear_user(void __user *, unsigned long);
205 extern __must_check long strnlen_user(const char __user *src, long n);
207 * Complex access routines -- macros
210 #define clear_user lclear_user
211 #define __clear_user lclear_user
213 unsigned long __must_check raw_copy_to_user(void __user *dst, const void *src,
215 unsigned long __must_check raw_copy_from_user(void *dst, const void __user *src,
217 #define INLINE_COPY_TO_USER
218 #define INLINE_COPY_FROM_USER
221 int fixup_exception(struct pt_regs *regs);
223 #endif /* __PARISC_UACCESS_H */