FILE
uaccess.h
File preview with syntax highlighting.
linux-6.19.14/arch/loongarch/include/asm/uaccess.h
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 * 5 * Derived from MIPS: 6 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle 7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 2007 Maciej W. Rozycki 9 * Copyright (C) 2014, Imagination Technologies Ltd. 10 */ 11#ifndef _ASM_UACCESS_H 12#define _ASM_UACCESS_H 13 14#include <linux/kernel.h> 15#include <linux/string.h> 16#include <linux/extable.h> 17#include <asm/pgtable.h> 18#include <asm/extable.h> 19#include <asm/asm-extable.h> 20#include <asm-generic/access_ok.h> 21 22#define __LSW 0 23#define __MSW 1 24 25extern u64 __ua_limit; 26 27#ifdef CONFIG_64BIT 28#define __UA_LIMIT __ua_limit 29#else 30#define __UA_LIMIT 0x80000000UL 31#endif 32 33/* 34 * get_user: - Get a simple variable from user space. 35 * @x: Variable to store result. 36 * @ptr: Source address, in user space. 37 * 38 * Context: User context only. This function may sleep if pagefaults are 39 * enabled. 40 * 41 * This macro copies a single simple variable from user space to kernel 42 * space. It supports simple types like char and int, but not larger 43 * data types like structures or arrays. 44 * 45 * @ptr must have pointer-to-simple-variable type, and the result of 46 * dereferencing @ptr must be assignable to @x without a cast. 47 * 48 * Returns zero on success, or -EFAULT on error. 49 * On error, the variable @x is set to zero. 50 */ 51#define get_user(x, ptr) \ 52({ \ 53 const __typeof__(*(ptr)) __user *__p = (ptr); \ 54 \ 55 might_fault(); \ 56 access_ok(__p, sizeof(*__p)) ? __get_user((x), __p) : \ 57 ((x) = 0, -EFAULT); \ 58}) 59 60/* 61 * put_user: - Write a simple value into user space. 62 * @x: Value to copy to user space. 63 * @ptr: Destination address, in user space. 64 * 65 * Context: User context only. This function may sleep if pagefaults are 66 * enabled. 67 * 68 * This macro copies a single simple value from kernel space to user 69 * space. It supports simple types like char and int, but not larger 70 * data types like structures or arrays. 71 * 72 * @ptr must have pointer-to-simple-variable type, and @x must be assignable 73 * to the result of dereferencing @ptr. 74 * 75 * Returns zero on success, or -EFAULT on error. 76 */ 77#define put_user(x, ptr) \ 78({ \ 79 __typeof__(*(ptr)) __user *__p = (ptr); \ 80 \ 81 might_fault(); \ 82 access_ok(__p, sizeof(*__p)) ? __put_user((x), __p) : -EFAULT; \ 83}) 84 85/* 86 * __get_user: - Get a simple variable from user space, with less checking. 87 * @x: Variable to store result. 88 * @ptr: Source address, in user space. 89 * 90 * Context: User context only. This function may sleep if pagefaults are 91 * enabled. 92 * 93 * This macro copies a single simple variable from user space to kernel 94 * space. It supports simple types like char and int, but not larger 95 * data types like structures or arrays. 96 * 97 * @ptr must have pointer-to-simple-variable type, and the result of 98 * dereferencing @ptr must be assignable to @x without a cast. 99 * 100 * Caller must check the pointer with access_ok() before calling this 101 * function. 102 * 103 * Returns zero on success, or -EFAULT on error. 104 * On error, the variable @x is set to zero. 105 */ 106#define __get_user(x, ptr) \ 107({ \ 108 int __gu_err = 0; \ 109 \ 110 __chk_user_ptr(ptr); \ 111 __get_user_common((x), sizeof(*(ptr)), ptr); \ 112 __gu_err; \ 113}) 114 115/* 116 * __put_user: - Write a simple value into user space, with less checking. 117 * @x: Value to copy to user space. 118 * @ptr: Destination address, in user space. 119 * 120 * Context: User context only. This function may sleep if pagefaults are 121 * enabled. 122 * 123 * This macro copies a single simple value from kernel space to user 124 * space. It supports simple types like char and int, but not larger 125 * data types like structures or arrays. 126 * 127 * @ptr must have pointer-to-simple-variable type, and @x must be assignable 128 * to the result of dereferencing @ptr. 129 * 130 * Caller must check the pointer with access_ok() before calling this 131 * function. 132 * 133 * Returns zero on success, or -EFAULT on error. 134 */ 135 136#define __put_user(x, ptr) \ 137({ \ 138 int __pu_err = 0; \ 139 __typeof__(*(ptr)) __pu_val; \ 140 \ 141 __pu_val = (x); \ 142 __chk_user_ptr(ptr); \ 143 __put_user_common(ptr, sizeof(*(ptr))); \ 144 __pu_err; \ 145}) 146 147struct __large_struct { unsigned long buf[100]; }; 148#define __m(x) (*(struct __large_struct __user *)(x)) 149 150#define __get_user_common(val, size, ptr) \ 151do { \ 152 switch (size) { \ 153 case 1: __get_data_asm(val, "ld.b", ptr); break; \ 154 case 2: __get_data_asm(val, "ld.h", ptr); break; \ 155 case 4: __get_data_asm(val, "ld.w", ptr); break; \ 156 case 8: __get_data_asm_8(val, ptr); break; \ 157 default: BUILD_BUG(); break; \ 158 } \ 159} while (0) 160 161#define __get_kernel_common(val, size, ptr) __get_user_common(val, size, ptr) 162 163#define __get_data_asm(val, insn, ptr) \ 164{ \ 165 long __gu_tmp; \ 166 \ 167 __asm__ __volatile__( \ 168 "1: " insn " %1, %2 \n" \ 169 "2: \n" \ 170 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1) \ 171 : "+r" (__gu_err), "=r" (__gu_tmp) \ 172 : "m" (__m(ptr))); \ 173 \ 174 (val) = (__typeof__(*(ptr))) __gu_tmp; \ 175} 176 177#ifdef CONFIG_64BIT 178#define __get_data_asm_8(val, ptr) \ 179 __get_data_asm(val, "ld.d", ptr) 180#else /* !CONFIG_64BIT */ 181#define __get_data_asm_8(val, ptr) \ 182{ \ 183 u32 __lo, __hi; \ 184 u32 __user *__ptr = (u32 __user *)(ptr); \ 185 \ 186 __asm__ __volatile__ ( \ 187 "1:\n" \ 188 " ld.w %1, %3 \n" \ 189 "2:\n" \ 190 " ld.w %2, %4 \n" \ 191 "3:\n" \ 192 _ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1) \ 193 _ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1) \ 194 : "+r" (__gu_err), "=&r" (__lo), "=r" (__hi) \ 195 : "m" (__ptr[__LSW]), "m" (__ptr[__MSW])); \ 196 if (__gu_err) \ 197 __hi = 0; \ 198 (val) = (__typeof__(val))((__typeof__((val)-(val))) \ 199 ((((u64)__hi << 32) | __lo))); \ 200} 201#endif /* CONFIG_64BIT */ 202 203#define __put_user_common(ptr, size) \ 204do { \ 205 switch (size) { \ 206 case 1: __put_data_asm("st.b", ptr); break; \ 207 case 2: __put_data_asm("st.h", ptr); break; \ 208 case 4: __put_data_asm("st.w", ptr); break; \ 209 case 8: __put_data_asm_8(ptr); break; \ 210 default: BUILD_BUG(); break; \ 211 } \ 212} while (0) 213 214#define __put_kernel_common(ptr, size) __put_user_common(ptr, size) 215 216#define __put_data_asm(insn, ptr) \ 217{ \ 218 __asm__ __volatile__( \ 219 "1: " insn " %z2, %1 # __put_user_asm\n" \ 220 "2: \n" \ 221 _ASM_EXTABLE_UACCESS_ERR(1b, 2b, %0) \ 222 : "+r" (__pu_err), "=m" (__m(ptr)) \ 223 : "Jr" (__pu_val)); \ 224} 225 226#ifdef CONFIG_64BIT 227#define __put_data_asm_8(ptr) \ 228 __put_data_asm("st.d", ptr) 229#else /* !CONFIG_64BIT */ 230#define __put_data_asm_8(ptr) \ 231{ \ 232 u32 __user *__ptr = (u32 __user *)(ptr); \ 233 u64 __x = (__typeof__((__pu_val)-(__pu_val)))(__pu_val); \ 234 \ 235 __asm__ __volatile__ ( \ 236 "1:\n" \ 237 " st.w %z3, %1 \n" \ 238 "2:\n" \ 239 " st.w %z4, %2 \n" \ 240 "3:\n" \ 241 _ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0) \ 242 _ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0) \ 243 : "+r" (__pu_err), \ 244 "=m" (__ptr[__LSW]), \ 245 "=m" (__ptr[__MSW]) \ 246 : "rJ" (__x), "rJ" (__x >> 32)); \ 247} 248#endif /* CONFIG_64BIT */ 249 250#define __get_kernel_nofault(dst, src, type, err_label) \ 251do { \ 252 int __gu_err = 0; \ 253 \ 254 __get_kernel_common(*((type *)(dst)), sizeof(type), \ 255 (__force type *)(src)); \ 256 if (unlikely(__gu_err)) { \ 257 pr_info("%s: memory access failed, ecode 0x%x\n", \ 258 __func__, read_csr_excode()); \ 259 pr_info("%s: the caller is %pS\n", \ 260 __func__, __builtin_return_address(0)); \ 261 goto err_label; \ 262 } \ 263} while (0) 264 265#define __put_kernel_nofault(dst, src, type, err_label) \ 266do { \ 267 type __pu_val; \ 268 int __pu_err = 0; \ 269 \ 270 __pu_val = *(__force type *)(src); \ 271 __put_kernel_common(((type *)(dst)), sizeof(type)); \ 272 if (unlikely(__pu_err)) { \ 273 pr_info("%s: memory access failed, ecode 0x%x\n", \ 274 __func__, read_csr_excode()); \ 275 pr_info("%s: the caller is %pS\n", \ 276 __func__, __builtin_return_address(0)); \ 277 goto err_label; \ 278 } \ 279} while (0) 280 281extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n); 282 283static inline unsigned long __must_check 284raw_copy_from_user(void *to, const void __user *from, unsigned long n) 285{ 286 return __copy_user(to, (__force const void *)from, n); 287} 288 289static inline unsigned long __must_check 290raw_copy_to_user(void __user *to, const void *from, unsigned long n) 291{ 292 return __copy_user((__force void *)to, from, n); 293} 294 295#define INLINE_COPY_FROM_USER 296#define INLINE_COPY_TO_USER 297 298/* 299 * __clear_user: - Zero a block of memory in user space, with less checking. 300 * @addr: Destination address, in user space. 301 * @size: Number of bytes to zero. 302 * 303 * Zero a block of memory in user space. Caller must check 304 * the specified block with access_ok() before calling this function. 305 * 306 * Returns number of bytes that could not be cleared. 307 * On success, this will be zero. 308 */ 309extern unsigned long __clear_user(void __user *addr, __kernel_size_t size); 310 311#define clear_user(addr, n) \ 312({ \ 313 void __user *__cl_addr = (addr); \ 314 unsigned long __cl_size = (n); \ 315 if (__cl_size && access_ok(__cl_addr, __cl_size)) \ 316 __cl_size = __clear_user(__cl_addr, __cl_size); \ 317 __cl_size; \ 318}) 319 320extern long strncpy_from_user(char *to, const char __user *from, long n); 321extern long strnlen_user(const char __user *str, long n); 322 323#endif /* _ASM_UACCESS_H */
~/
Read-only file preview.