forked from Minki/linux
s390/uaccess: add HAVE_GET_KERNEL_NOFAULT support
Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
fc3f61e1bc
commit
110a6dbb2e
@ -278,4 +278,115 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo
|
|||||||
int copy_to_user_real(void __user *dest, void *src, unsigned long count);
|
int copy_to_user_real(void __user *dest, void *src, unsigned long count);
|
||||||
void *s390_kernel_write(void *dst, const void *src, size_t size);
|
void *s390_kernel_write(void *dst, const void *src, size_t size);
|
||||||
|
|
||||||
|
#define HAVE_GET_KERNEL_NOFAULT
|
||||||
|
|
||||||
|
int __noreturn __put_kernel_bad(void);
|
||||||
|
|
||||||
|
#define __put_kernel_asm(val, to, insn) \
|
||||||
|
({ \
|
||||||
|
int __rc; \
|
||||||
|
\
|
||||||
|
asm volatile( \
|
||||||
|
"0: " insn " %2,%1\n" \
|
||||||
|
"1: xr %0,%0\n" \
|
||||||
|
"2:\n" \
|
||||||
|
".pushsection .fixup, \"ax\"\n" \
|
||||||
|
"3: lhi %0,%3\n" \
|
||||||
|
" jg 2b\n" \
|
||||||
|
".popsection\n" \
|
||||||
|
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
|
||||||
|
: "=d" (__rc), "+Q" (*(to)) \
|
||||||
|
: "d" (val), "K" (-EFAULT) \
|
||||||
|
: "cc"); \
|
||||||
|
__rc; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define __put_kernel_nofault(dst, src, type, err_label) \
|
||||||
|
do { \
|
||||||
|
u64 __x = (u64)(*((type *)(src))); \
|
||||||
|
int __pk_err; \
|
||||||
|
\
|
||||||
|
switch (sizeof(type)) { \
|
||||||
|
case 1: \
|
||||||
|
__pk_err = __put_kernel_asm(__x, (type *)(dst), "stc"); \
|
||||||
|
break; \
|
||||||
|
case 2: \
|
||||||
|
__pk_err = __put_kernel_asm(__x, (type *)(dst), "sth"); \
|
||||||
|
break; \
|
||||||
|
case 4: \
|
||||||
|
__pk_err = __put_kernel_asm(__x, (type *)(dst), "st"); \
|
||||||
|
break; \
|
||||||
|
case 8: \
|
||||||
|
__pk_err = __put_kernel_asm(__x, (type *)(dst), "stg"); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
__pk_err = __put_kernel_bad(); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if (unlikely(__pk_err)) \
|
||||||
|
goto err_label; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
int __noreturn __get_kernel_bad(void);
|
||||||
|
|
||||||
|
#define __get_kernel_asm(val, from, insn) \
|
||||||
|
({ \
|
||||||
|
int __rc; \
|
||||||
|
\
|
||||||
|
asm volatile( \
|
||||||
|
"0: " insn " %1,%2\n" \
|
||||||
|
"1: xr %0,%0\n" \
|
||||||
|
"2:\n" \
|
||||||
|
".pushsection .fixup, \"ax\"\n" \
|
||||||
|
"3: lhi %0,%3\n" \
|
||||||
|
" jg 2b\n" \
|
||||||
|
".popsection\n" \
|
||||||
|
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
|
||||||
|
: "=d" (__rc), "+d" (val) \
|
||||||
|
: "Q" (*(from)), "K" (-EFAULT) \
|
||||||
|
: "cc"); \
|
||||||
|
__rc; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||||
|
do { \
|
||||||
|
int __gk_err; \
|
||||||
|
\
|
||||||
|
switch (sizeof(type)) { \
|
||||||
|
case 1: { \
|
||||||
|
u8 __x = 0; \
|
||||||
|
\
|
||||||
|
__gk_err = __get_kernel_asm(__x, (type *)(src), "ic"); \
|
||||||
|
*((type *)(dst)) = (type)__x; \
|
||||||
|
break; \
|
||||||
|
}; \
|
||||||
|
case 2: { \
|
||||||
|
u16 __x = 0; \
|
||||||
|
\
|
||||||
|
__gk_err = __get_kernel_asm(__x, (type *)(src), "lh"); \
|
||||||
|
*((type *)(dst)) = (type)__x; \
|
||||||
|
break; \
|
||||||
|
}; \
|
||||||
|
case 4: { \
|
||||||
|
u32 __x = 0; \
|
||||||
|
\
|
||||||
|
__gk_err = __get_kernel_asm(__x, (type *)(src), "l"); \
|
||||||
|
*((type *)(dst)) = (type)__x; \
|
||||||
|
break; \
|
||||||
|
}; \
|
||||||
|
case 8: { \
|
||||||
|
u64 __x = 0; \
|
||||||
|
\
|
||||||
|
__gk_err = __get_kernel_asm(__x, (type *)(src), "lg"); \
|
||||||
|
*((type *)(dst)) = (type)__x; \
|
||||||
|
break; \
|
||||||
|
}; \
|
||||||
|
default: \
|
||||||
|
__gk_err = __get_kernel_bad(); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if (unlikely(__gk_err)) \
|
||||||
|
goto err_label; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif /* __S390_UACCESS_H */
|
#endif /* __S390_UACCESS_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user