1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (C) 2012 Regents of the University of California 4 * 5 * This file was copied from include/asm-generic/uaccess.h 6 */ 7 8 #ifndef _ASM_RISCV_UACCESS_H 9 #define _ASM_RISCV_UACCESS_H 10 11 #include <asm/asm-extable.h> 12 #include <asm/pgtable.h> /* for TASK_SIZE */ 13 14 /* 15 * User space memory access functions 16 */ 17 #ifdef CONFIG_MMU 18 #include <linux/errno.h> 19 #include <linux/compiler.h> 20 #include <linux/thread_info.h> 21 #include <asm/byteorder.h> 22 #include <asm/extable.h> 23 #include <asm/asm.h> 24 #include <asm-generic/access_ok.h> 25 26 #define __enable_user_access() \ 27 __asm__ __volatile__ ("csrs sstatus, %0" : : "r" (SR_SUM) : "memory") 28 #define __disable_user_access() \ 29 __asm__ __volatile__ ("csrc sstatus, %0" : : "r" (SR_SUM) : "memory") 30 31 /* 32 * The exception table consists of pairs of addresses: the first is the 33 * address of an instruction that is allowed to fault, and the second is 34 * the address at which the program should continue. No registers are 35 * modified, so it is entirely up to the continuation code to figure out 36 * what to do. 37 * 38 * All the routines below use bits of fixup code that are out of line 39 * with the main instruction path. This means when everything is well, 40 * we don't even have to jump over them. Further, they do not intrude 41 * on our cache or tlb entries. 42 */ 43 44 #define __LSW 0 45 #define __MSW 1 46 47 /* 48 * The "__xxx" versions of the user access functions do not verify the address 49 * space - it must have been done previously with a separate "access_ok()" 50 * call. 51 */ 52 53 #define __get_user_asm(insn, x, ptr, err) \ 54 do { \ 55 __typeof__(x) __x; \ 56 __asm__ __volatile__ ( \ 57 "1:\n" \ 58 " " insn " %1, %2\n" \ 59 "2:\n" \ 60 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1) \ 61 : "+r" (err), "=&r" (__x) \ 62 : "m" (*(ptr))); \ 63 (x) = __x; \ 64 } while (0) 65 66 #ifdef CONFIG_64BIT 67 #define __get_user_8(x, ptr, err) \ 68 __get_user_asm("ld", x, ptr, err) 69 #else /* !CONFIG_64BIT */ 70 #define __get_user_8(x, ptr, err) \ 71 do { \ 72 u32 __user *__ptr = (u32 __user *)(ptr); \ 73 u32 __lo, __hi; \ 74 __asm__ __volatile__ ( \ 75 "1:\n" \ 76 " lw %1, %3\n" \ 77 "2:\n" \ 78 " lw %2, %4\n" \ 79 "3:\n" \ 80 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1) \ 81 _ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1) \ 82 : "+r" (err), "=&r" (__lo), "=r" (__hi) \ 83 : "m" (__ptr[__LSW]), "m" (__ptr[__MSW])); \ 84 if (err) \ 85 __hi = 0; \ 86 (x) = (__typeof__(x))((__typeof__((x)-(x)))( \ 87 (((u64)__hi << 32) | __lo))); \ 88 } while (0) 89 #endif /* CONFIG_64BIT */ 90 91 #define __get_user_nocheck(x, __gu_ptr, __gu_err) \ 92 do { \ 93 switch (sizeof(*__gu_ptr)) { \ 94 case 1: \ 95 __get_user_asm("lb", (x), __gu_ptr, __gu_err); \ 96 break; \ 97 case 2: \ 98 __get_user_asm("lh", (x), __gu_ptr, __gu_err); \ 99 break; \ 100 case 4: \ 101 __get_user_asm("lw", (x), __gu_ptr, __gu_err); \ 102 break; \ 103 case 8: \ 104 __get_user_8((x), __gu_ptr, __gu_err); \ 105 break; \ 106 default: \ 107 BUILD_BUG(); \ 108 } \ 109 } while (0) 110 111 /** 112 * __get_user: - Get a simple variable from user space, with less checking. 113 * @x: Variable to store result. 114 * @ptr: Source address, in user space. 115 * 116 * Context: User context only. This function may sleep. 117 * 118 * This macro copies a single simple variable from user space to kernel 119 * space. It supports simple types like char and int, but not larger 120 * data types like structures or arrays. 121 * 122 * @ptr must have pointer-to-simple-variable type, and the result of 123 * dereferencing @ptr must be assignable to @x without a cast. 124 * 125 * Caller must check the pointer with access_ok() before calling this 126 * function. 127 * 128 * Returns zero on success, or -EFAULT on error. 129 * On error, the variable @x is set to zero. 130 */ 131 #define __get_user(x, ptr) \ 132 ({ \ 133 const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 134 long __gu_err = 0; \ 135 \ 136 __chk_user_ptr(__gu_ptr); \ 137 \ 138 __enable_user_access(); \ 139 __get_user_nocheck(x, __gu_ptr, __gu_err); \ 140 __disable_user_access(); \ 141 \ 142 __gu_err; \ 143 }) 144 145 /** 146 * get_user: - Get a simple variable from user space. 147 * @x: Variable to store result. 148 * @ptr: Source address, in user space. 149 * 150 * Context: User context only. This function may sleep. 151 * 152 * This macro copies a single simple variable from user space to kernel 153 * space. It supports simple types like char and int, but not larger 154 * data types like structures or arrays. 155 * 156 * @ptr must have pointer-to-simple-variable type, and the result of 157 * dereferencing @ptr must be assignable to @x without a cast. 158 * 159 * Returns zero on success, or -EFAULT on error. 160 * On error, the variable @x is set to zero. 161 */ 162 #define get_user(x, ptr) \ 163 ({ \ 164 const __typeof__(*(ptr)) __user *__p = (ptr); \ 165 might_fault(); \ 166 access_ok(__p, sizeof(*__p)) ? \ 167 __get_user((x), __p) : \ 168 ((x) = (__force __typeof__(x))0, -EFAULT); \ 169 }) 170 171 #define __put_user_asm(insn, x, ptr, err) \ 172 do { \ 173 __typeof__(*(ptr)) __x = x; \ 174 __asm__ __volatile__ ( \ 175 "1:\n" \ 176 " " insn " %z2, %1\n" \ 177 "2:\n" \ 178 _ASM_EXTABLE_UACCESS_ERR(1b, 2b, %0) \ 179 : "+r" (err), "=m" (*(ptr)) \ 180 : "rJ" (__x)); \ 181 } while (0) 182 183 #ifdef CONFIG_64BIT 184 #define __put_user_8(x, ptr, err) \ 185 __put_user_asm("sd", x, ptr, err) 186 #else /* !CONFIG_64BIT */ 187 #define __put_user_8(x, ptr, err) \ 188 do { \ 189 u32 __user *__ptr = (u32 __user *)(ptr); \ 190 u64 __x = (__typeof__((x)-(x)))(x); \ 191 __asm__ __volatile__ ( \ 192 "1:\n" \ 193 " sw %z3, %1\n" \ 194 "2:\n" \ 195 " sw %z4, %2\n" \ 196 "3:\n" \ 197 _ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0) \ 198 _ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0) \ 199 : "+r" (err), \ 200 "=m" (__ptr[__LSW]), \ 201 "=m" (__ptr[__MSW]) \ 202 : "rJ" (__x), "rJ" (__x >> 32)); \ 203 } while (0) 204 #endif /* CONFIG_64BIT */ 205 206 #define __put_user_nocheck(x, __gu_ptr, __pu_err) \ 207 do { \ 208 switch (sizeof(*__gu_ptr)) { \ 209 case 1: \ 210 __put_user_asm("sb", (x), __gu_ptr, __pu_err); \ 211 break; \ 212 case 2: \ 213 __put_user_asm("sh", (x), __gu_ptr, __pu_err); \ 214 break; \ 215 case 4: \ 216 __put_user_asm("sw", (x), __gu_ptr, __pu_err); \ 217 break; \ 218 case 8: \ 219 __put_user_8((x), __gu_ptr, __pu_err); \ 220 break; \ 221 default: \ 222 BUILD_BUG(); \ 223 } \ 224 } while (0) 225 226 /** 227 * __put_user: - Write a simple value into user space, with less checking. 228 * @x: Value to copy to user space. 229 * @ptr: Destination address, in user space. 230 * 231 * Context: User context only. This function may sleep. 232 * 233 * This macro copies a single simple value from kernel space to user 234 * space. It supports simple types like char and int, but not larger 235 * data types like structures or arrays. 236 * 237 * @ptr must have pointer-to-simple-variable type, and @x must be assignable 238 * to the result of dereferencing @ptr. The value of @x is copied to avoid 239 * re-ordering where @x is evaluated inside the block that enables user-space 240 * access (thus bypassing user space protection if @x is a function). 241 * 242 * Caller must check the pointer with access_ok() before calling this 243 * function. 244 * 245 * Returns zero on success, or -EFAULT on error. 246 */ 247 #define __put_user(x, ptr) \ 248 ({ \ 249 __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 250 __typeof__(*__gu_ptr) __val = (x); \ 251 long __pu_err = 0; \ 252 \ 253 __chk_user_ptr(__gu_ptr); \ 254 \ 255 __enable_user_access(); \ 256 __put_user_nocheck(__val, __gu_ptr, __pu_err); \ 257 __disable_user_access(); \ 258 \ 259 __pu_err; \ 260 }) 261 262 /** 263 * put_user: - Write a simple value into user space. 264 * @x: Value to copy to user space. 265 * @ptr: Destination address, in user space. 266 * 267 * Context: User context only. This function may sleep. 268 * 269 * This macro copies a single simple value from kernel space to user 270 * space. It supports simple types like char and int, but not larger 271 * data types like structures or arrays. 272 * 273 * @ptr must have pointer-to-simple-variable type, and @x must be assignable 274 * to the result of dereferencing @ptr. 275 * 276 * Returns zero on success, or -EFAULT on error. 277 */ 278 #define put_user(x, ptr) \ 279 ({ \ 280 __typeof__(*(ptr)) __user *__p = (ptr); \ 281 might_fault(); \ 282 access_ok(__p, sizeof(*__p)) ? \ 283 __put_user((x), __p) : \ 284 -EFAULT; \ 285 }) 286 287 288 unsigned long __must_check __asm_copy_to_user(void __user *to, 289 const void *from, unsigned long n); 290 unsigned long __must_check __asm_copy_from_user(void *to, 291 const void __user *from, unsigned long n); 292 293 static inline unsigned long 294 raw_copy_from_user(void *to, const void __user *from, unsigned long n) 295 { 296 return __asm_copy_from_user(to, from, n); 297 } 298 299 static inline unsigned long 300 raw_copy_to_user(void __user *to, const void *from, unsigned long n) 301 { 302 return __asm_copy_to_user(to, from, n); 303 } 304 305 extern long strncpy_from_user(char *dest, const char __user *src, long count); 306 307 extern long __must_check strnlen_user(const char __user *str, long n); 308 309 extern 310 unsigned long __must_check __clear_user(void __user *addr, unsigned long n); 311 312 static inline 313 unsigned long __must_check clear_user(void __user *to, unsigned long n) 314 { 315 might_fault(); 316 return access_ok(to, n) ? 317 __clear_user(to, n) : n; 318 } 319 320 #define __get_kernel_nofault(dst, src, type, err_label) \ 321 do { \ 322 long __kr_err = 0; \ 323 \ 324 __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ 325 if (unlikely(__kr_err)) \ 326 goto err_label; \ 327 } while (0) 328 329 #define __put_kernel_nofault(dst, src, type, err_label) \ 330 do { \ 331 long __kr_err = 0; \ 332 \ 333 __put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err); \ 334 if (unlikely(__kr_err)) \ 335 goto err_label; \ 336 } while (0) 337 338 #else /* CONFIG_MMU */ 339 #include <asm-generic/uaccess.h> 340 #endif /* CONFIG_MMU */ 341 #endif /* _ASM_RISCV_UACCESS_H */ 342
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.