.. | .. |
---|
31 | 31 | #define USER_DS (2) |
---|
32 | 32 | #define USER_DS_SACF (3) |
---|
33 | 33 | |
---|
34 | | -#define get_ds() (KERNEL_DS) |
---|
35 | 34 | #define get_fs() (current->thread.mm_segment) |
---|
36 | | -#define segment_eq(a,b) (((a) & 2) == ((b) & 2)) |
---|
| 35 | +#define uaccess_kernel() ((get_fs() & 2) == KERNEL_DS) |
---|
37 | 36 | |
---|
38 | 37 | void set_fs(mm_segment_t fs); |
---|
39 | 38 | |
---|
.. | .. |
---|
48 | 47 | __range_ok((unsigned long)(addr), (size)); \ |
---|
49 | 48 | }) |
---|
50 | 49 | |
---|
51 | | -#define access_ok(type, addr, size) __access_ok(addr, size) |
---|
| 50 | +#define access_ok(addr, size) __access_ok(addr, size) |
---|
52 | 51 | |
---|
53 | 52 | unsigned long __must_check |
---|
54 | 53 | raw_copy_from_user(void *to, const void __user *from, unsigned long n); |
---|
.. | .. |
---|
60 | 59 | #define INLINE_COPY_FROM_USER |
---|
61 | 60 | #define INLINE_COPY_TO_USER |
---|
62 | 61 | #endif |
---|
| 62 | + |
---|
| 63 | +int __put_user_bad(void) __attribute__((noreturn)); |
---|
| 64 | +int __get_user_bad(void) __attribute__((noreturn)); |
---|
63 | 65 | |
---|
64 | 66 | #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES |
---|
65 | 67 | |
---|
.. | .. |
---|
110 | 112 | (unsigned long *)x, |
---|
111 | 113 | size, spec); |
---|
112 | 114 | break; |
---|
| 115 | + default: |
---|
| 116 | + __put_user_bad(); |
---|
| 117 | + break; |
---|
113 | 118 | } |
---|
114 | 119 | return rc; |
---|
115 | 120 | } |
---|
.. | .. |
---|
139 | 144 | rc = __put_get_user_asm((unsigned long *)x, |
---|
140 | 145 | (unsigned long __user *)ptr, |
---|
141 | 146 | size, spec); |
---|
| 147 | + break; |
---|
| 148 | + default: |
---|
| 149 | + __get_user_bad(); |
---|
142 | 150 | break; |
---|
143 | 151 | } |
---|
144 | 152 | return rc; |
---|
.. | .. |
---|
180 | 188 | default: \ |
---|
181 | 189 | __put_user_bad(); \ |
---|
182 | 190 | break; \ |
---|
183 | | - } \ |
---|
| 191 | + } \ |
---|
184 | 192 | __builtin_expect(__pu_err, 0); \ |
---|
185 | 193 | }) |
---|
186 | 194 | |
---|
.. | .. |
---|
190 | 198 | __put_user(x, ptr); \ |
---|
191 | 199 | }) |
---|
192 | 200 | |
---|
193 | | - |
---|
194 | | -int __put_user_bad(void) __attribute__((noreturn)); |
---|
195 | 201 | |
---|
196 | 202 | #define __get_user(x, ptr) \ |
---|
197 | 203 | ({ \ |
---|
.. | .. |
---|
239 | 245 | __get_user(x, ptr); \ |
---|
240 | 246 | }) |
---|
241 | 247 | |
---|
242 | | -int __get_user_bad(void) __attribute__((noreturn)); |
---|
243 | | - |
---|
244 | 248 | unsigned long __must_check |
---|
245 | 249 | raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); |
---|
246 | 250 | |
---|
.. | .. |
---|
277 | 281 | } |
---|
278 | 282 | |
---|
279 | 283 | int copy_to_user_real(void __user *dest, void *src, unsigned long count); |
---|
280 | | -void s390_kernel_write(void *dst, const void *src, size_t size); |
---|
| 284 | +void *s390_kernel_write(void *dst, const void *src, size_t size); |
---|
| 285 | + |
---|
| 286 | +#define HAVE_GET_KERNEL_NOFAULT |
---|
| 287 | + |
---|
| 288 | +int __noreturn __put_kernel_bad(void); |
---|
| 289 | + |
---|
| 290 | +#define __put_kernel_asm(val, to, insn) \ |
---|
| 291 | +({ \ |
---|
| 292 | + int __rc; \ |
---|
| 293 | + \ |
---|
| 294 | + asm volatile( \ |
---|
| 295 | + "0: " insn " %2,%1\n" \ |
---|
| 296 | + "1: xr %0,%0\n" \ |
---|
| 297 | + "2:\n" \ |
---|
| 298 | + ".pushsection .fixup, \"ax\"\n" \ |
---|
| 299 | + "3: lhi %0,%3\n" \ |
---|
| 300 | + " jg 2b\n" \ |
---|
| 301 | + ".popsection\n" \ |
---|
| 302 | + EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ |
---|
| 303 | + : "=d" (__rc), "+Q" (*(to)) \ |
---|
| 304 | + : "d" (val), "K" (-EFAULT) \ |
---|
| 305 | + : "cc"); \ |
---|
| 306 | + __rc; \ |
---|
| 307 | +}) |
---|
| 308 | + |
---|
| 309 | +#define __put_kernel_nofault(dst, src, type, err_label) \ |
---|
| 310 | +do { \ |
---|
| 311 | + u64 __x = (u64)(*((type *)(src))); \ |
---|
| 312 | + int __pk_err; \ |
---|
| 313 | + \ |
---|
| 314 | + switch (sizeof(type)) { \ |
---|
| 315 | + case 1: \ |
---|
| 316 | + __pk_err = __put_kernel_asm(__x, (type *)(dst), "stc"); \ |
---|
| 317 | + break; \ |
---|
| 318 | + case 2: \ |
---|
| 319 | + __pk_err = __put_kernel_asm(__x, (type *)(dst), "sth"); \ |
---|
| 320 | + break; \ |
---|
| 321 | + case 4: \ |
---|
| 322 | + __pk_err = __put_kernel_asm(__x, (type *)(dst), "st"); \ |
---|
| 323 | + break; \ |
---|
| 324 | + case 8: \ |
---|
| 325 | + __pk_err = __put_kernel_asm(__x, (type *)(dst), "stg"); \ |
---|
| 326 | + break; \ |
---|
| 327 | + default: \ |
---|
| 328 | + __pk_err = __put_kernel_bad(); \ |
---|
| 329 | + break; \ |
---|
| 330 | + } \ |
---|
| 331 | + if (unlikely(__pk_err)) \ |
---|
| 332 | + goto err_label; \ |
---|
| 333 | +} while (0) |
---|
| 334 | + |
---|
| 335 | +int __noreturn __get_kernel_bad(void); |
---|
| 336 | + |
---|
| 337 | +#define __get_kernel_asm(val, from, insn) \ |
---|
| 338 | +({ \ |
---|
| 339 | + int __rc; \ |
---|
| 340 | + \ |
---|
| 341 | + asm volatile( \ |
---|
| 342 | + "0: " insn " %1,%2\n" \ |
---|
| 343 | + "1: xr %0,%0\n" \ |
---|
| 344 | + "2:\n" \ |
---|
| 345 | + ".pushsection .fixup, \"ax\"\n" \ |
---|
| 346 | + "3: lhi %0,%3\n" \ |
---|
| 347 | + " jg 2b\n" \ |
---|
| 348 | + ".popsection\n" \ |
---|
| 349 | + EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ |
---|
| 350 | + : "=d" (__rc), "+d" (val) \ |
---|
| 351 | + : "Q" (*(from)), "K" (-EFAULT) \ |
---|
| 352 | + : "cc"); \ |
---|
| 353 | + __rc; \ |
---|
| 354 | +}) |
---|
| 355 | + |
---|
| 356 | +#define __get_kernel_nofault(dst, src, type, err_label) \ |
---|
| 357 | +do { \ |
---|
| 358 | + int __gk_err; \ |
---|
| 359 | + \ |
---|
| 360 | + switch (sizeof(type)) { \ |
---|
| 361 | + case 1: { \ |
---|
| 362 | + u8 __x = 0; \ |
---|
| 363 | + \ |
---|
| 364 | + __gk_err = __get_kernel_asm(__x, (type *)(src), "ic"); \ |
---|
| 365 | + *((type *)(dst)) = (type)__x; \ |
---|
| 366 | + break; \ |
---|
| 367 | + }; \ |
---|
| 368 | + case 2: { \ |
---|
| 369 | + u16 __x = 0; \ |
---|
| 370 | + \ |
---|
| 371 | + __gk_err = __get_kernel_asm(__x, (type *)(src), "lh"); \ |
---|
| 372 | + *((type *)(dst)) = (type)__x; \ |
---|
| 373 | + break; \ |
---|
| 374 | + }; \ |
---|
| 375 | + case 4: { \ |
---|
| 376 | + u32 __x = 0; \ |
---|
| 377 | + \ |
---|
| 378 | + __gk_err = __get_kernel_asm(__x, (type *)(src), "l"); \ |
---|
| 379 | + *((type *)(dst)) = (type)__x; \ |
---|
| 380 | + break; \ |
---|
| 381 | + }; \ |
---|
| 382 | + case 8: { \ |
---|
| 383 | + u64 __x = 0; \ |
---|
| 384 | + \ |
---|
| 385 | + __gk_err = __get_kernel_asm(__x, (type *)(src), "lg"); \ |
---|
| 386 | + *((type *)(dst)) = (type)__x; \ |
---|
| 387 | + break; \ |
---|
| 388 | + }; \ |
---|
| 389 | + default: \ |
---|
| 390 | + __gk_err = __get_kernel_bad(); \ |
---|
| 391 | + break; \ |
---|
| 392 | + } \ |
---|
| 393 | + if (unlikely(__gk_err)) \ |
---|
| 394 | + goto err_label; \ |
---|
| 395 | +} while (0) |
---|
281 | 396 | |
---|
282 | 397 | #endif /* __S390_UACCESS_H */ |
---|