[MIPS] More uaccess.h fixes with gcc >= 4.0.1.
From Richard Sandiford <richard@codesourcery.com>: This patch caused a miscompilation of the restore_gp_regs() block in restore_sigcontext(). This was in a 32-bit kernel compiled with GCC CVS head. restore_gp_regs() copies 64-bit user fields into 32-bit variables, and in this combination, the new __get_user_asm_ll32() clobbers too many registers. It says: /* * Get a long long 64 using 32 bit registers. */ { \ __asm__ __volatile__( \ "1: lw %1, (%3) \n" \ "2: lw %D1, 4(%3) \n" \ " move %0, $0 \n" \ "3: .section .fixup,\"ax\" \n" \ "4: li %0, %4 \n" \ " move %1, $0 \n" \ " move %D1, $0 \n" \ " j 3b \n" \ " .previous \n" \ " .section __ex_table,\"a\" \n" \ " " __UA_ADDR " 1b, 4b \n" \ " " __UA_ADDR " 2b, 4b \n" \ " .previous \n" \ : "=r" (__gu_err), "=&r" (val) \ : "0" (0), "r" (addr), "i" (-EFAULT)); \ } and this requires val (%1) to be a 64-bit value. In the case I saw, gcc was using $3 for the 32-bit val, and wasn't expecting $4 to be clobbered. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
41700e7399
commit
3218357c94
|
@ -266,6 +266,8 @@ do { \
|
||||||
*/
|
*/
|
||||||
#define __get_user_asm_ll32(val, addr) \
|
#define __get_user_asm_ll32(val, addr) \
|
||||||
{ \
|
{ \
|
||||||
|
unsigned long long __gu_tmp; \
|
||||||
|
\
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
"1: lw %1, (%3) \n" \
|
"1: lw %1, (%3) \n" \
|
||||||
"2: lw %D1, 4(%3) \n" \
|
"2: lw %D1, 4(%3) \n" \
|
||||||
|
@ -280,8 +282,9 @@ do { \
|
||||||
" " __UA_ADDR " 1b, 4b \n" \
|
" " __UA_ADDR " 1b, 4b \n" \
|
||||||
" " __UA_ADDR " 2b, 4b \n" \
|
" " __UA_ADDR " 2b, 4b \n" \
|
||||||
" .previous \n" \
|
" .previous \n" \
|
||||||
: "=r" (__gu_err), "=&r" (val) \
|
: "=r" (__gu_err), "=&r" (__gu_tmp) \
|
||||||
: "0" (0), "r" (addr), "i" (-EFAULT)); \
|
: "0" (0), "r" (addr), "i" (-EFAULT)); \
|
||||||
|
(val) = __gu_tmp; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue