Re: Fixes for uaccess.h with gcc >= 4.0.1

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ralf Baechle <ralf@xxxxxxxxxxxxxx> writes:
> I'd appreciate if somebody with gcc 4.0.1 could test this kernel patch
> below.

Sorry in advance if this is a dup, but...

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.
 */
#define __get_user_asm_ll32(val, addr)					\
{									\
	__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.

FWIW, the patch below fixes it for me.

Richard


diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 91d813a..1208cae 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -266,6 +266,7 @@ do {									\
  */
 #define __get_user_asm_ll32(val, addr)					\
 {									\
+        unsigned long long __gu_tmp;					\
 	__asm__ __volatile__(						\
 	"1:	lw	%1, (%3)				\n"	\
 	"2:	lw	%D1, 4(%3)				\n"	\
@@ -280,8 +281,9 @@ do {									\
 	"	" __UA_ADDR "	1b, 4b				\n"	\
 	"	" __UA_ADDR "	2b, 4b				\n"	\
 	"	.previous					\n"	\
-	: "=r" (__gu_err), "=&r" (val)					\
+	: "=r" (__gu_err), "=&r" (__gu_tmp)				\
 	: "0" (0), "r" (addr), "i" (-EFAULT));				\
+	(val) = __gu_tmp;						\
 }
 
 /*


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux