parisc: Fix some apparent put_user() failures
After commit4b9d2a731c
("parisc: Switch user access functions to signal errors in r29 instead of r8") bash suddenly started to report those warnings after login: -bash: cannot set terminal process group (-1): Bad file descriptor -bash: no job control in this shell It turned out, that a function call inside a put_user(), e.g.: put_user(vt_do_kdgkbmode(console), (int __user *)arg); clobbered the error register (r29) and thus the put_user() call itself seem to have failed. Rearrange the C-code to pre-calculate the intermediate value and then do the put_user(). Additionally prefer the "+" constraint on pu_err and gu_err registers to tell the compiler that those operands are both read and written by the assembly instruction. Reported-by: John David Anglin <dave.anglin@bell.net> Signed-off-by: Helge Deller <deller@gmx.de> Fixes:4b9d2a731c
("parisc: Switch user access functions to signal errors in r29 instead of r8") Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
parent
b160628e9e
commit
dbd0b42350
@ -89,8 +89,8 @@ struct exception_table_entry {
|
||||
__asm__("1: " ldx " 0(" sr "%2),%0\n" \
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
: "=r"(__gu_val), "=r"(__gu_err) \
|
||||
: "r"(ptr), "1"(__gu_err)); \
|
||||
: "=r"(__gu_val), "+r"(__gu_err) \
|
||||
: "r"(ptr)); \
|
||||
\
|
||||
(val) = (__force __typeof__(*(ptr))) __gu_val; \
|
||||
}
|
||||
@ -123,8 +123,8 @@ struct exception_table_entry {
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
|
||||
: "=&r"(__gu_tmp.l), "=r"(__gu_err) \
|
||||
: "r"(ptr), "1"(__gu_err)); \
|
||||
: "=&r"(__gu_tmp.l), "+r"(__gu_err) \
|
||||
: "r"(ptr)); \
|
||||
\
|
||||
(val) = __gu_tmp.t; \
|
||||
}
|
||||
@ -135,13 +135,12 @@ struct exception_table_entry {
|
||||
#define __put_user_internal(sr, x, ptr) \
|
||||
({ \
|
||||
ASM_EXCEPTIONTABLE_VAR(__pu_err); \
|
||||
__typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
|
||||
\
|
||||
switch (sizeof(*(ptr))) { \
|
||||
case 1: __put_user_asm(sr, "stb", __x, ptr); break; \
|
||||
case 2: __put_user_asm(sr, "sth", __x, ptr); break; \
|
||||
case 4: __put_user_asm(sr, "stw", __x, ptr); break; \
|
||||
case 8: STD_USER(sr, __x, ptr); break; \
|
||||
case 1: __put_user_asm(sr, "stb", x, ptr); break; \
|
||||
case 2: __put_user_asm(sr, "sth", x, ptr); break; \
|
||||
case 4: __put_user_asm(sr, "stw", x, ptr); break; \
|
||||
case 8: STD_USER(sr, x, ptr); break; \
|
||||
default: BUILD_BUG(); \
|
||||
} \
|
||||
\
|
||||
@ -150,7 +149,9 @@ struct exception_table_entry {
|
||||
|
||||
#define __put_user(x, ptr) \
|
||||
({ \
|
||||
__put_user_internal("%%sr3,", x, ptr); \
|
||||
__typeof__(&*(ptr)) __ptr = ptr; \
|
||||
__typeof__(*(__ptr)) __x = (__typeof__(*(__ptr)))(x); \
|
||||
__put_user_internal("%%sr3,", __x, __ptr); \
|
||||
})
|
||||
|
||||
#define __put_kernel_nofault(dst, src, type, err_label) \
|
||||
@ -180,8 +181,8 @@ struct exception_table_entry {
|
||||
"1: " stx " %2,0(" sr "%1)\n" \
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
: "=r"(__pu_err) \
|
||||
: "r"(ptr), "r"(x), "0"(__pu_err))
|
||||
: "+r"(__pu_err) \
|
||||
: "r"(ptr), "r"(x))
|
||||
|
||||
|
||||
#if !defined(CONFIG_64BIT)
|
||||
@ -193,8 +194,8 @@ struct exception_table_entry {
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
|
||||
: "=r"(__pu_err) \
|
||||
: "r"(ptr), "r"(__val), "0"(__pu_err)); \
|
||||
: "+r"(__pu_err) \
|
||||
: "r"(ptr), "r"(__val)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !defined(CONFIG_64BIT) */
|
||||
|
Loading…
Reference in New Issue
Block a user