It seems current get_user() incorrectly sign-extend an unsigned int
value on 64bit kernel. I think this is because '(__typeof__(val))'
cast in final assignment. I suppose the cast should be
'(__typeof__(*(addr))'.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
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>
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!