Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'riscv-for-linus-5.10-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull more RISC-V updates from Palmer Dabbelt:
"Just a single patch set: the remainder of Christoph's work to remove
set_fs, including the RISC-V portion"

* tag 'riscv-for-linus-5.10-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
riscv: remove address space overrides using set_fs()
riscv: implement __get_kernel_nofault and __put_user_nofault
riscv: refactor __get_user and __put_user
riscv: use memcpy based uaccess for nommu again
asm-generic: make the set_fs implementation optional
asm-generic: add nommu implementations of __{get,put}_kernel_nofault
asm-generic: improve the nommu {get,put}_user handling
uaccess: provide a generic TASK_SIZE_MAX definition

+166 -135
+1 -1
arch/riscv/Kconfig
··· 88 88 select SPARSE_IRQ 89 89 select SYSCTL_EXCEPTION_TRACE 90 90 select THREAD_INFO_IN_TASK 91 - select SET_FS 91 + select UACCESS_MEMCPY if !MMU 92 92 93 93 config ARCH_MMAP_RND_BITS_MIN 94 94 default 18 if 64BIT
-6
arch/riscv/include/asm/thread_info.h
··· 24 24 #include <asm/processor.h> 25 25 #include <asm/csr.h> 26 26 27 - typedef struct { 28 - unsigned long seg; 29 - } mm_segment_t; 30 - 31 27 /* 32 28 * low level task data that entry.S needs immediate access to 33 29 * - this struct should fit entirely inside of one cache line ··· 35 39 struct thread_info { 36 40 unsigned long flags; /* low level flags */ 37 41 int preempt_count; /* 0=>preemptible, <0=>BUG */ 38 - mm_segment_t addr_limit; 39 42 /* 40 43 * These stack pointers are overwritten on every system call or 41 44 * exception. SP is also saved to the stack it can be recovered when ··· 54 59 { \ 55 60 .flags = 0, \ 56 61 .preempt_count = INIT_PREEMPT_COUNT, \ 57 - .addr_limit = KERNEL_DS, \ 58 62 } 59 63 60 64 #endif /* !__ASSEMBLY__ */
+91 -86
arch/riscv/include/asm/uaccess.h
··· 13 13 /* 14 14 * User space memory access functions 15 15 */ 16 - 17 - extern unsigned long __must_check __asm_copy_to_user(void __user *to, 18 - const void *from, unsigned long n); 19 - extern unsigned long __must_check __asm_copy_from_user(void *to, 20 - const void __user *from, unsigned long n); 21 - 22 - static inline unsigned long 23 - raw_copy_from_user(void *to, const void __user *from, unsigned long n) 24 - { 25 - return __asm_copy_from_user(to, from, n); 26 - } 27 - 28 - static inline unsigned long 29 - raw_copy_to_user(void __user *to, const void *from, unsigned long n) 30 - { 31 - return __asm_copy_to_user(to, from, n); 32 - } 33 - 34 16 #ifdef CONFIG_MMU 35 17 #include <linux/errno.h> 36 18 #include <linux/compiler.h> ··· 25 43 __asm__ __volatile__ ("csrs sstatus, %0" : : "r" (SR_SUM) : "memory") 26 44 #define __disable_user_access() \ 27 45 __asm__ __volatile__ ("csrc sstatus, %0" : : "r" (SR_SUM) : "memory") 28 - 29 - /* 30 - * The fs value determines whether argument validity checking should be 31 - * performed or not. If get_fs() == USER_DS, checking is performed, with 32 - * get_fs() == KERNEL_DS, checking is bypassed. 33 - * 34 - * For historical reasons, these macros are grossly misnamed. 35 - */ 36 - 37 - #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 38 - 39 - #define KERNEL_DS MAKE_MM_SEG(~0UL) 40 - #define USER_DS MAKE_MM_SEG(TASK_SIZE) 41 - 42 - #define get_fs() (current_thread_info()->addr_limit) 43 - 44 - static inline void set_fs(mm_segment_t fs) 45 - { 46 - current_thread_info()->addr_limit = fs; 47 - } 48 - 49 - #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 50 - #define user_addr_max() (get_fs().seg) 51 46 52 47 /** 53 48 * access_ok: - Checks if a user space pointer is valid ··· 53 94 */ 54 95 static inline int __access_ok(unsigned long addr, unsigned long size) 55 96 { 56 - const mm_segment_t fs = get_fs(); 57 - 58 - return size <= fs.seg && addr <= fs.seg - size; 97 + return size <= TASK_SIZE && addr <= TASK_SIZE - size; 59 98 } 60 99 61 100 /* ··· 82 125 do { \ 83 126 uintptr_t __tmp; \ 84 127 __typeof__(x) __x; \ 85 - __enable_user_access(); \ 86 128 __asm__ __volatile__ ( \ 87 129 "1:\n" \ 88 130 " " insn " %1, %3\n" \ ··· 99 143 " .previous" \ 100 144 : "+r" (err), "=&r" (__x), "=r" (__tmp) \ 101 145 : "m" (*(ptr)), "i" (-EFAULT)); \ 102 - __disable_user_access(); \ 103 146 (x) = __x; \ 104 147 } while (0) 105 148 ··· 111 156 u32 __user *__ptr = (u32 __user *)(ptr); \ 112 157 u32 __lo, __hi; \ 113 158 uintptr_t __tmp; \ 114 - __enable_user_access(); \ 115 159 __asm__ __volatile__ ( \ 116 160 "1:\n" \ 117 161 " lw %1, %4\n" \ ··· 134 180 "=r" (__tmp) \ 135 181 : "m" (__ptr[__LSW]), "m" (__ptr[__MSW]), \ 136 182 "i" (-EFAULT)); \ 137 - __disable_user_access(); \ 138 183 (x) = (__typeof__(x))((__typeof__((x)-(x)))( \ 139 184 (((u64)__hi << 32) | __lo))); \ 140 185 } while (0) 141 186 #endif /* CONFIG_64BIT */ 142 187 188 + #define __get_user_nocheck(x, __gu_ptr, __gu_err) \ 189 + do { \ 190 + switch (sizeof(*__gu_ptr)) { \ 191 + case 1: \ 192 + __get_user_asm("lb", (x), __gu_ptr, __gu_err); \ 193 + break; \ 194 + case 2: \ 195 + __get_user_asm("lh", (x), __gu_ptr, __gu_err); \ 196 + break; \ 197 + case 4: \ 198 + __get_user_asm("lw", (x), __gu_ptr, __gu_err); \ 199 + break; \ 200 + case 8: \ 201 + __get_user_8((x), __gu_ptr, __gu_err); \ 202 + break; \ 203 + default: \ 204 + BUILD_BUG(); \ 205 + } \ 206 + } while (0) 143 207 144 208 /** 145 209 * __get_user: - Get a simple variable from user space, with less checking. ··· 181 209 */ 182 210 #define __get_user(x, ptr) \ 183 211 ({ \ 184 - register long __gu_err = 0; \ 185 212 const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 213 + long __gu_err = 0; \ 214 + \ 186 215 __chk_user_ptr(__gu_ptr); \ 187 - switch (sizeof(*__gu_ptr)) { \ 188 - case 1: \ 189 - __get_user_asm("lb", (x), __gu_ptr, __gu_err); \ 190 - break; \ 191 - case 2: \ 192 - __get_user_asm("lh", (x), __gu_ptr, __gu_err); \ 193 - break; \ 194 - case 4: \ 195 - __get_user_asm("lw", (x), __gu_ptr, __gu_err); \ 196 - break; \ 197 - case 8: \ 198 - __get_user_8((x), __gu_ptr, __gu_err); \ 199 - break; \ 200 - default: \ 201 - BUILD_BUG(); \ 202 - } \ 216 + \ 217 + __enable_user_access(); \ 218 + __get_user_nocheck(x, __gu_ptr, __gu_err); \ 219 + __disable_user_access(); \ 220 + \ 203 221 __gu_err; \ 204 222 }) 205 223 ··· 223 261 do { \ 224 262 uintptr_t __tmp; \ 225 263 __typeof__(*(ptr)) __x = x; \ 226 - __enable_user_access(); \ 227 264 __asm__ __volatile__ ( \ 228 265 "1:\n" \ 229 266 " " insn " %z3, %2\n" \ ··· 239 278 " .previous" \ 240 279 : "+r" (err), "=r" (__tmp), "=m" (*(ptr)) \ 241 280 : "rJ" (__x), "i" (-EFAULT)); \ 242 - __disable_user_access(); \ 243 281 } while (0) 244 282 245 283 #ifdef CONFIG_64BIT ··· 250 290 u32 __user *__ptr = (u32 __user *)(ptr); \ 251 291 u64 __x = (__typeof__((x)-(x)))(x); \ 252 292 uintptr_t __tmp; \ 253 - __enable_user_access(); \ 254 293 __asm__ __volatile__ ( \ 255 294 "1:\n" \ 256 295 " sw %z4, %2\n" \ ··· 271 312 "=m" (__ptr[__LSW]), \ 272 313 "=m" (__ptr[__MSW]) \ 273 314 : "rJ" (__x), "rJ" (__x >> 32), "i" (-EFAULT)); \ 274 - __disable_user_access(); \ 275 315 } while (0) 276 316 #endif /* CONFIG_64BIT */ 277 317 318 + #define __put_user_nocheck(x, __gu_ptr, __pu_err) \ 319 + do { \ 320 + switch (sizeof(*__gu_ptr)) { \ 321 + case 1: \ 322 + __put_user_asm("sb", (x), __gu_ptr, __pu_err); \ 323 + break; \ 324 + case 2: \ 325 + __put_user_asm("sh", (x), __gu_ptr, __pu_err); \ 326 + break; \ 327 + case 4: \ 328 + __put_user_asm("sw", (x), __gu_ptr, __pu_err); \ 329 + break; \ 330 + case 8: \ 331 + __put_user_8((x), __gu_ptr, __pu_err); \ 332 + break; \ 333 + default: \ 334 + BUILD_BUG(); \ 335 + } \ 336 + } while (0) 278 337 279 338 /** 280 339 * __put_user: - Write a simple value into user space, with less checking. ··· 315 338 */ 316 339 #define __put_user(x, ptr) \ 317 340 ({ \ 318 - register long __pu_err = 0; \ 319 341 __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ 342 + long __pu_err = 0; \ 343 + \ 320 344 __chk_user_ptr(__gu_ptr); \ 321 - switch (sizeof(*__gu_ptr)) { \ 322 - case 1: \ 323 - __put_user_asm("sb", (x), __gu_ptr, __pu_err); \ 324 - break; \ 325 - case 2: \ 326 - __put_user_asm("sh", (x), __gu_ptr, __pu_err); \ 327 - break; \ 328 - case 4: \ 329 - __put_user_asm("sw", (x), __gu_ptr, __pu_err); \ 330 - break; \ 331 - case 8: \ 332 - __put_user_8((x), __gu_ptr, __pu_err); \ 333 - break; \ 334 - default: \ 335 - BUILD_BUG(); \ 336 - } \ 345 + \ 346 + __enable_user_access(); \ 347 + __put_user_nocheck(x, __gu_ptr, __pu_err); \ 348 + __disable_user_access(); \ 349 + \ 337 350 __pu_err; \ 338 351 }) 339 352 ··· 351 384 __put_user((x), __p) : \ 352 385 -EFAULT; \ 353 386 }) 387 + 388 + 389 + unsigned long __must_check __asm_copy_to_user(void __user *to, 390 + const void *from, unsigned long n); 391 + unsigned long __must_check __asm_copy_from_user(void *to, 392 + const void __user *from, unsigned long n); 393 + 394 + static inline unsigned long 395 + raw_copy_from_user(void *to, const void __user *from, unsigned long n) 396 + { 397 + return __asm_copy_from_user(to, from, n); 398 + } 399 + 400 + static inline unsigned long 401 + raw_copy_to_user(void __user *to, const void *from, unsigned long n) 402 + { 403 + return __asm_copy_to_user(to, from, n); 404 + } 354 405 355 406 extern long strncpy_from_user(char *dest, const char __user *src, long count); 356 407 ··· 460 475 (err) = __err; \ 461 476 __ret; \ 462 477 }) 478 + 479 + #define HAVE_GET_KERNEL_NOFAULT 480 + 481 + #define __get_kernel_nofault(dst, src, type, err_label) \ 482 + do { \ 483 + long __kr_err; \ 484 + \ 485 + __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ 486 + if (unlikely(__kr_err)) \ 487 + goto err_label; \ 488 + } while (0) 489 + 490 + #define __put_kernel_nofault(dst, src, type, err_label) \ 491 + do { \ 492 + long __kr_err; \ 493 + \ 494 + __put_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ 495 + if (unlikely(__kr_err)) \ 496 + goto err_label; \ 497 + } while (0) 463 498 464 499 #else /* CONFIG_MMU */ 465 500 #include <asm-generic/uaccess.h>
-1
arch/riscv/kernel/process.c
··· 84 84 } 85 85 regs->epc = pc; 86 86 regs->sp = sp; 87 - set_fs(USER_DS); 88 87 } 89 88 90 89 void flush_thread(void)
+1 -1
arch/riscv/lib/Makefile
··· 2 2 lib-y += delay.o 3 3 lib-y += memcpy.o 4 4 lib-y += memset.o 5 - lib-y += uaccess.o 5 + lib-$(CONFIG_MMU) += uaccess.o 6 6 lib-$(CONFIG_64BIT) += tishift.o
+69 -40
include/asm-generic/uaccess.h
··· 10 10 #include <linux/string.h> 11 11 12 12 #ifdef CONFIG_UACCESS_MEMCPY 13 + #include <asm/unaligned.h> 14 + 15 + static inline int __get_user_fn(size_t size, const void __user *from, void *to) 16 + { 17 + BUILD_BUG_ON(!__builtin_constant_p(size)); 18 + 19 + switch (size) { 20 + case 1: 21 + *(u8 *)to = get_unaligned((u8 __force *)from); 22 + return 0; 23 + case 2: 24 + *(u16 *)to = get_unaligned((u16 __force *)from); 25 + return 0; 26 + case 4: 27 + *(u32 *)to = get_unaligned((u32 __force *)from); 28 + return 0; 29 + case 8: 30 + *(u64 *)to = get_unaligned((u64 __force *)from); 31 + return 0; 32 + default: 33 + BUILD_BUG(); 34 + return 0; 35 + } 36 + 37 + } 38 + #define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 39 + 40 + static inline int __put_user_fn(size_t size, void __user *to, void *from) 41 + { 42 + BUILD_BUG_ON(!__builtin_constant_p(size)); 43 + 44 + switch (size) { 45 + case 1: 46 + put_unaligned(*(u8 *)from, (u8 __force *)to); 47 + return 0; 48 + case 2: 49 + put_unaligned(*(u16 *)from, (u16 __force *)to); 50 + return 0; 51 + case 4: 52 + put_unaligned(*(u32 *)from, (u32 __force *)to); 53 + return 0; 54 + case 8: 55 + put_unaligned(*(u64 *)from, (u64 __force *)to); 56 + return 0; 57 + default: 58 + BUILD_BUG(); 59 + return 0; 60 + } 61 + } 62 + #define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 63 + 64 + #define __get_kernel_nofault(dst, src, type, err_label) \ 65 + do { \ 66 + *((type *)dst) = get_unaligned((type *)(src)); \ 67 + if (0) /* make sure the label looks used to the compiler */ \ 68 + goto err_label; \ 69 + } while (0) 70 + 71 + #define __put_kernel_nofault(dst, src, type, err_label) \ 72 + do { \ 73 + put_unaligned(*((type *)src), (type *)(dst)); \ 74 + if (0) /* make sure the label looks used to the compiler */ \ 75 + goto err_label; \ 76 + } while (0) 77 + 78 + #define HAVE_GET_KERNEL_NOFAULT 1 79 + 13 80 static inline __must_check unsigned long 14 81 raw_copy_from_user(void *to, const void __user * from, unsigned long n) 15 82 { 16 - if (__builtin_constant_p(n)) { 17 - switch(n) { 18 - case 1: 19 - *(u8 *)to = *(u8 __force *)from; 20 - return 0; 21 - case 2: 22 - *(u16 *)to = *(u16 __force *)from; 23 - return 0; 24 - case 4: 25 - *(u32 *)to = *(u32 __force *)from; 26 - return 0; 27 - #ifdef CONFIG_64BIT 28 - case 8: 29 - *(u64 *)to = *(u64 __force *)from; 30 - return 0; 31 - #endif 32 - } 33 - } 34 - 35 83 memcpy(to, (const void __force *)from, n); 36 84 return 0; 37 85 } ··· 87 39 static inline __must_check unsigned long 88 40 raw_copy_to_user(void __user *to, const void *from, unsigned long n) 89 41 { 90 - if (__builtin_constant_p(n)) { 91 - switch(n) { 92 - case 1: 93 - *(u8 __force *)to = *(u8 *)from; 94 - return 0; 95 - case 2: 96 - *(u16 __force *)to = *(u16 *)from; 97 - return 0; 98 - case 4: 99 - *(u32 __force *)to = *(u32 *)from; 100 - return 0; 101 - #ifdef CONFIG_64BIT 102 - case 8: 103 - *(u64 __force *)to = *(u64 *)from; 104 - return 0; 105 - #endif 106 - default: 107 - break; 108 - } 109 - } 110 - 111 42 memcpy((void __force *)to, from, n); 112 43 return 0; 113 44 } ··· 94 67 #define INLINE_COPY_TO_USER 95 68 #endif /* CONFIG_UACCESS_MEMCPY */ 96 69 70 + #ifdef CONFIG_SET_FS 97 71 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 98 72 99 73 #ifndef KERNEL_DS ··· 117 89 #ifndef uaccess_kernel 118 90 #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 119 91 #endif 92 + #endif /* CONFIG_SET_FS */ 120 93 121 94 #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size)) 122 95
+4
include/linux/uaccess.h
··· 33 33 /* empty dummy */ 34 34 } mm_segment_t; 35 35 36 + #ifndef TASK_SIZE_MAX 37 + #define TASK_SIZE_MAX TASK_SIZE 38 + #endif 39 + 36 40 #define uaccess_kernel() (false) 37 41 #define user_addr_max() (TASK_SIZE_MAX) 38 42