1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __PARISC_UACCESS_H 3 #define __PARISC_UACCESS_H 4 5 /* 6 * User space memory access functions 7 */ 8 #include <asm/page.h> 9 #include <asm/cache.h> 10 #include <asm/extable.h> 11 12 #include <linux/bug.h> 13 #include <linux/string.h> 14 15 #define TASK_SIZE_MAX DEFAULT_TASK_SIZE 16 #include <asm/pgtable.h> 17 #include <asm-generic/access_ok.h> 18 19 #define put_user __put_user 20 #define get_user __get_user 21 22 #if !defined(CONFIG_64BIT) 23 #define LDD_USER(sr, val, ptr) __get_user_asm64(sr, val, ptr) 24 #define STD_USER(sr, x, ptr) __put_user_asm64(sr, x, ptr) 25 #else 26 #define LDD_USER(sr, val, ptr) __get_user_asm(sr, val, "ldd", ptr) 27 #define STD_USER(sr, x, ptr) __put_user_asm(sr, "std", x, ptr) 28 #endif 29 30 #define __get_user_internal(sr, val, ptr) \ 31 ({ \ 32 ASM_EXCEPTIONTABLE_VAR(__gu_err); \ 33 \ 34 switch (sizeof(*(ptr))) { \ 35 case 1: __get_user_asm(sr, val, "ldb", ptr); break; \ 36 case 2: __get_user_asm(sr, val, "ldh", ptr); break; \ 37 case 4: __get_user_asm(sr, val, "ldw", ptr); break; \ 38 case 8: LDD_USER(sr, val, ptr); break; \ 39 default: BUILD_BUG(); \ 40 } \ 41 \ 42 __gu_err; \ 43 }) 44 45 #define __get_user(val, ptr) \ 46 ({ \ 47 __get_user_internal(SR_USER, val, ptr); \ 48 }) 49 50 #define __get_user_asm(sr, val, ldx, ptr) \ 51 { \ 52 register long __gu_val; \ 53 \ 54 __asm__("1: " ldx " 0(%%sr%2,%3),%0\n" \ 55 "9:\n" \ 56 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%1") \ 57 : "=r"(__gu_val), "+r"(__gu_err) \ 58 : "i"(sr), "r"(ptr)); \ 59 \ 60 (val) = (__force __typeof__(*(ptr))) __gu_val; \ 61 } 62 63 #define __get_kernel_nofault(dst, src, type, err_label) \ 64 { \ 65 type __z; \ 66 long __err; \ 67 __err = __get_user_internal(SR_KERNEL, __z, (type *)(src)); \ 68 if (unlikely(__err)) \ 69 goto err_label; \ 70 else \ 71 *(type *)(dst) = __z; \ 72 } 73 74 75 #if !defined(CONFIG_64BIT) 76 77 #define __get_user_asm64(sr, val, ptr) \ 78 { \ 79 union { \ 80 unsigned long long l; \ 81 __typeof__(*(ptr)) t; \ 82 } __gu_tmp; \ 83 \ 84 __asm__(" copy %%r0,%R0\n" \ 85 "1: ldw 0(%%sr%2,%3),%0\n" \ 86 "2: ldw 4(%%sr%2,%3),%R0\n" \ 87 "9:\n" \ 88 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%1") \ 89 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b, "%1") \ 90 : "=&r"(__gu_tmp.l), "+r"(__gu_err) \ 91 : "i"(sr), "r"(ptr)); \ 92 \ 93 (val) = __gu_tmp.t; \ 94 } 95 96 #endif /* !defined(CONFIG_64BIT) */ 97 98 99 #define __put_user_internal(sr, x, ptr) \ 100 ({ \ 101 ASM_EXCEPTIONTABLE_VAR(__pu_err); \ 102 \ 103 switch (sizeof(*(ptr))) { \ 104 case 1: __put_user_asm(sr, "stb", x, ptr); break; \ 105 case 2: __put_user_asm(sr, "sth", x, ptr); break; \ 106 case 4: __put_user_asm(sr, "stw", x, ptr); break; \ 107 case 8: STD_USER(sr, x, ptr); break; \ 108 default: BUILD_BUG(); \ 109 } \ 110 \ 111 __pu_err; \ 112 }) 113 114 #define __put_user(x, ptr) \ 115 ({ \ 116 __typeof__(&*(ptr)) __ptr = ptr; \ 117 __typeof__(*(__ptr)) __x = (__typeof__(*(__ptr)))(x); \ 118 __put_user_internal(SR_USER, __x, __ptr); \ 119 }) 120 121 #define __put_kernel_nofault(dst, src, type, err_label) \ 122 { \ 123 type __z = *(type *)(src); \ 124 long __err; \ 125 __err = __put_user_internal(SR_KERNEL, __z, (type *)(dst)); \ 126 if (unlikely(__err)) \ 127 goto err_label; \ 128 } 129 130 131 132 133 /* 134 * The "__put_user/kernel_asm()" macros tell gcc they read from memory 135 * instead of writing. This is because they do not write to any memory 136 * gcc knows about, so there are no aliasing issues. These macros must 137 * also be aware that fixups are executed in the context of the fault, 138 * and any registers used there must be listed as clobbers. 139 * The register holding the possible EFAULT error (ASM_EXCEPTIONTABLE_REG) 140 * is already listed as input and output register. 141 */ 142 143 #define __put_user_asm(sr, stx, x, ptr) \ 144 __asm__ __volatile__ ( \ 145 "1: " stx " %1,0(%%sr%2,%3)\n" \ 146 "9:\n" \ 147 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%0") \ 148 : "+r"(__pu_err) \ 149 : "r"(x), "i"(sr), "r"(ptr)) 150 151 152 #if !defined(CONFIG_64BIT) 153 154 #define __put_user_asm64(sr, __val, ptr) do { \ 155 __asm__ __volatile__ ( \ 156 "1: stw %1,0(%%sr%2,%3)\n" \ 157 "2: stw %R1,4(%%sr%2,%3)\n" \ 158 "9:\n" \ 159 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%0") \ 160 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b, "%0") \ 161 : "+r"(__pu_err) \ 162 : "r"(__val), "i"(sr), "r"(ptr)); \ 163 } while (0) 164 165 #endif /* !defined(CONFIG_64BIT) */ 166 167 /* 168 * Complex access routines -- external declarations 169 */ 170 171 extern long strncpy_from_user(char *, const char __user *, long); 172 extern __must_check unsigned lclear_user(void __user *, unsigned long); 173 extern __must_check long strnlen_user(const char __user *src, long n); 174 /* 175 * Complex access routines -- macros 176 */ 177 178 #define clear_user lclear_user 179 #define __clear_user lclear_user 180 181 unsigned long __must_check raw_copy_to_user(void __user *dst, const void *src, 182 unsigned long len); 183 unsigned long __must_check raw_copy_from_user(void *dst, const void __user *src, 184 unsigned long len); 185 #define INLINE_COPY_TO_USER 186 #define INLINE_COPY_FROM_USER 187 188 #endif /* __PARISC_UACCESS_H */ 189