diff options
Diffstat (limited to 'arch/riscv/include/asm/uaccess.h')
-rw-r--r-- | arch/riscv/include/asm/uaccess.h | 177 |
1 files changed, 91 insertions, 86 deletions
diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h index f56c66b3f5fe..c47e6b35c551 100644 --- a/arch/riscv/include/asm/uaccess.h +++ b/arch/riscv/include/asm/uaccess.h @@ -13,24 +13,6 @@ /* * User space memory access functions */ - -extern unsigned long __must_check __asm_copy_to_user(void __user *to, - const void *from, unsigned long n); -extern unsigned long __must_check __asm_copy_from_user(void *to, - const void __user *from, unsigned long n); - -static inline unsigned long -raw_copy_from_user(void *to, const void __user *from, unsigned long n) -{ - return __asm_copy_from_user(to, from, n); -} - -static inline unsigned long -raw_copy_to_user(void __user *to, const void *from, unsigned long n) -{ - return __asm_copy_to_user(to, from, n); -} - #ifdef CONFIG_MMU #include <linux/errno.h> #include <linux/compiler.h> @@ -44,29 +26,6 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n) #define __disable_user_access() \ __asm__ __volatile__ ("csrc sstatus, %0" : : "r" (SR_SUM) : "memory") -/* - * The fs value determines whether argument validity checking should be - * performed or not. If get_fs() == USER_DS, checking is performed, with - * get_fs() == KERNEL_DS, checking is bypassed. - * - * For historical reasons, these macros are grossly misnamed. - */ - -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) - -#define KERNEL_DS MAKE_MM_SEG(~0UL) -#define USER_DS MAKE_MM_SEG(TASK_SIZE) - -#define get_fs() (current_thread_info()->addr_limit) - -static inline void set_fs(mm_segment_t fs) -{ - current_thread_info()->addr_limit = fs; -} - -#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) -#define user_addr_max() (get_fs().seg) - /** * access_ok: - Checks if a user space pointer is valid * @addr: User space pointer to start of block to check @@ -94,9 +53,7 @@ static inline void set_fs(mm_segment_t fs) */ static inline int __access_ok(unsigned long addr, unsigned long size) { - const mm_segment_t fs = get_fs(); - - return size <= fs.seg && addr <= fs.seg - size; + return size <= TASK_SIZE && addr <= TASK_SIZE - size; } /* @@ -125,7 +82,6 @@ static inline int __access_ok(unsigned long addr, unsigned long size) do { \ uintptr_t __tmp; \ __typeof__(x) __x; \ - __enable_user_access(); \ __asm__ __volatile__ ( \ "1:\n" \ " " insn " %1, %3\n" \ @@ -143,7 +99,6 @@ do { \ " .previous" \ : "+r" (err), "=&r" (__x), "=r" (__tmp) \ : "m" (*(ptr)), "i" (-EFAULT)); \ - __disable_user_access(); \ (x) = __x; \ } while (0) @@ -156,7 +111,6 @@ do { \ u32 __user *__ptr = (u32 __user *)(ptr); \ u32 __lo, __hi; \ uintptr_t __tmp; \ - __enable_user_access(); \ __asm__ __volatile__ ( \ "1:\n" \ " lw %1, %4\n" \ @@ -180,12 +134,30 @@ do { \ "=r" (__tmp) \ : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]), \ "i" (-EFAULT)); \ - __disable_user_access(); \ (x) = (__typeof__(x))((__typeof__((x)-(x)))( \ (((u64)__hi << 32) | __lo))); \ } while (0) #endif /* CONFIG_64BIT */ +#define __get_user_nocheck(x, __gu_ptr, __gu_err) \ +do { \ + switch (sizeof(*__gu_ptr)) { \ + case 1: \ + __get_user_asm("lb", (x), __gu_ptr, __gu_err); \ + break; \ + case 2: \ + __get_user_asm("lh", (x), __gu_ptr, __gu_err); \ + break; \ + case 4: \ + __get_user_asm("lw", (x), __gu_ptr, __gu_err); \ + break; \ + case 8: \ + __get_user_8((x), __gu_ptr, __gu_err); \ + break; \ + default: \ + BUILD_BUG(); \ + } \ +} while (0) /** * __get_user: - Get a simple variable from user space, with less checking. @@ -209,25 +181,15 @@ do { \ */ #define __get_user(x, ptr) \ ({ \ - register long __gu_err = 0; \ const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ + long __gu_err = 0; \ + \ __chk_user_ptr(__gu_ptr); \ - switch (sizeof(*__gu_ptr)) { \ - case 1: \ - __get_user_asm("lb", (x), __gu_ptr, __gu_err); \ - break; \ - case 2: \ - __get_user_asm("lh", (x), __gu_ptr, __gu_err); \ - break; \ - case 4: \ - __get_user_asm("lw", (x), __gu_ptr, __gu_err); \ - break; \ - case 8: \ - __get_user_8((x), __gu_ptr, __gu_err); \ - break; \ - default: \ - BUILD_BUG(); \ - } \ + \ + __enable_user_access(); \ + __get_user_nocheck(x, __gu_ptr, __gu_err); \ + __disable_user_access(); \ + \ __gu_err; \ }) @@ -261,7 +223,6 @@ do { \ do { \ uintptr_t __tmp; \ __typeof__(*(ptr)) __x = x; \ - __enable_user_access(); \ __asm__ __volatile__ ( \ "1:\n" \ " " insn " %z3, %2\n" \ @@ -278,7 +239,6 @@ do { \ " .previous" \ : "+r" (err), "=r" (__tmp), "=m" (*(ptr)) \ : "rJ" (__x), "i" (-EFAULT)); \ - __disable_user_access(); \ } while (0) #ifdef CONFIG_64BIT @@ -290,7 +250,6 @@ do { \ u32 __user *__ptr = (u32 __user *)(ptr); \ u64 __x = (__typeof__((x)-(x)))(x); \ uintptr_t __tmp; \ - __enable_user_access(); \ __asm__ __volatile__ ( \ "1:\n" \ " sw %z4, %2\n" \ @@ -312,10 +271,28 @@ do { \ "=m" (__ptr[__LSW]), \ "=m" (__ptr[__MSW]) \ : "rJ" (__x), "rJ" (__x >> 32), "i" (-EFAULT)); \ - __disable_user_access(); \ } while (0) #endif /* CONFIG_64BIT */ +#define __put_user_nocheck(x, __gu_ptr, __pu_err) \ +do { \ + switch (sizeof(*__gu_ptr)) { \ + case 1: \ + __put_user_asm("sb", (x), __gu_ptr, __pu_err); \ + break; \ + case 2: \ + __put_user_asm("sh", (x), __gu_ptr, __pu_err); \ + break; \ + case 4: \ + __put_user_asm("sw", (x), __gu_ptr, __pu_err); \ + break; \ + case 8: \ + __put_user_8((x), __gu_ptr, __pu_err); \ + break; \ + default: \ + BUILD_BUG(); \ + } \ +} while (0) /** * __put_user: - Write a simple value into user space, with less checking. @@ -338,25 +315,15 @@ do { \ */ #define __put_user(x, ptr) \ ({ \ - register long __pu_err = 0; \ __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ + long __pu_err = 0; \ + \ __chk_user_ptr(__gu_ptr); \ - switch (sizeof(*__gu_ptr)) { \ - case 1: \ - __put_user_asm("sb", (x), __gu_ptr, __pu_err); \ - break; \ - case 2: \ - __put_user_asm("sh", (x), __gu_ptr, __pu_err); \ - break; \ - case 4: \ - __put_user_asm("sw", (x), __gu_ptr, __pu_err); \ - break; \ - case 8: \ - __put_user_8((x), __gu_ptr, __pu_err); \ - break; \ - default: \ - BUILD_BUG(); \ - } \ + \ + __enable_user_access(); \ + __put_user_nocheck(x, __gu_ptr, __pu_err); \ + __disable_user_access(); \ + \ __pu_err; \ }) @@ -385,6 +352,24 @@ do { \ -EFAULT; \ }) + +unsigned long __must_check __asm_copy_to_user(void __user *to, + const void *from, unsigned long n); +unsigned long __must_check __asm_copy_from_user(void *to, + const void __user *from, unsigned long n); + +static inline unsigned long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) +{ + return __asm_copy_from_user(to, from, n); +} + +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) +{ + return __asm_copy_to_user(to, from, n); +} + extern long strncpy_from_user(char *dest, const char __user *src, long count); extern long __must_check strlen_user(const char __user *str); @@ -476,6 +461,26 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n) __ret; \ }) +#define HAVE_GET_KERNEL_NOFAULT + +#define __get_kernel_nofault(dst, src, type, err_label) \ +do { \ + long __kr_err; \ + \ + __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ + if (unlikely(__kr_err)) \ + goto err_label; \ +} while (0) + +#define __put_kernel_nofault(dst, src, type, err_label) \ +do { \ + long __kr_err; \ + \ + __put_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ + if (unlikely(__kr_err)) \ + goto err_label; \ +} while (0) + #else /* CONFIG_MMU */ #include <asm-generic/uaccess.h> #endif /* CONFIG_MMU */ |