linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ARM: futex: preserve oldval in SMP __futex_atomic_op
@ 2011-09-22 18:35 Will Deacon
  2011-09-22 19:09 ` Nicolas Pitre
  0 siblings, 1 reply; 3+ messages in thread
From: Will Deacon @ 2011-09-22 18:35 UTC (permalink / raw)
  To: linux-arm-kernel

The SMP implementation of __futex_atomic_op clobbers oldval with the
status flag from the exclusive store. This causes it to always read as
zero when performing the FUTEX_OP_CMP_* operation.

This patch updates the ARM __futex_atomic_op implementations to take a
tmp argument, allowing us to store the strex status flag without
overwriting the register containing oldval.

Cc: stable at kernel.org
Reported-by: Minho Ben <mhban@samsung.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---

Following up on:

http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/066348.html

it turns out that we don't need to use named arguments after all,
although it might be nice to add that as a later patch. For now, I'm
trying to keep this as small as possible for -stable.

 arch/arm/include/asm/futex.h |   34 +++++++++++++++++-----------------
 1 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 8c73900..253cc86 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -25,17 +25,17 @@
 
 #ifdef CONFIG_SMP
 
-#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
+#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)	\
 	smp_mb();						\
 	__asm__ __volatile__(					\
-	"1:	ldrex	%1, [%2]\n"				\
+	"1:	ldrex	%1, [%3]\n"				\
 	"	" insn "\n"					\
-	"2:	strex	%1, %0, [%2]\n"				\
-	"	teq	%1, #0\n"				\
+	"2:	strex	%2, %0, [%3]\n"				\
+	"	teq	%2, #0\n"				\
 	"	bne	1b\n"					\
 	"	mov	%0, #0\n"				\
-	__futex_atomic_ex_table("%4")				\
-	: "=&r" (ret), "=&r" (oldval)				\
+	__futex_atomic_ex_table("%5")				\
+	: "=&r" (ret), "=&r" (oldval), "=&r" (tmp)		\
 	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
 	: "cc", "memory")
 
@@ -73,14 +73,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 #include <linux/preempt.h>
 #include <asm/domain.h>
 
-#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
+#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)	\
 	__asm__ __volatile__(					\
-	"1:	" T(ldr) "	%1, [%2]\n"			\
+	"1:	" T(ldr) "	%1, [%3]\n"			\
 	"	" insn "\n"					\
-	"2:	" T(str) "	%0, [%2]\n"			\
+	"2:	" T(str) "	%0, [%3]\n"			\
 	"	mov	%0, #0\n"				\
-	__futex_atomic_ex_table("%4")				\
-	: "=&r" (ret), "=&r" (oldval)				\
+	__futex_atomic_ex_table("%5")				\
+	: "=&r" (ret), "=&r" (oldval), "=&r" (tmp)		\
 	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
 	: "cc", "memory")
 
@@ -117,7 +117,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 	int cmp = (encoded_op >> 24) & 15;
 	int oparg = (encoded_op << 8) >> 20;
 	int cmparg = (encoded_op << 20) >> 20;
-	int oldval = 0, ret;
+	int oldval = 0, ret, tmp;
 
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
@@ -129,19 +129,19 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 
 	switch (op) {
 	case FUTEX_OP_SET:
-		__futex_atomic_op("mov	%0, %3", ret, oldval, uaddr, oparg);
+		__futex_atomic_op("mov	%0, %4", ret, oldval, tmp, uaddr, oparg);
 		break;
 	case FUTEX_OP_ADD:
-		__futex_atomic_op("add	%0, %1, %3", ret, oldval, uaddr, oparg);
+		__futex_atomic_op("add	%0, %1, %4", ret, oldval, tmp, uaddr, oparg);
 		break;
 	case FUTEX_OP_OR:
-		__futex_atomic_op("orr	%0, %1, %3", ret, oldval, uaddr, oparg);
+		__futex_atomic_op("orr	%0, %1, %4", ret, oldval, tmp, uaddr, oparg);
 		break;
 	case FUTEX_OP_ANDN:
-		__futex_atomic_op("and	%0, %1, %3", ret, oldval, uaddr, ~oparg);
+		__futex_atomic_op("and	%0, %1, %4", ret, oldval, tmp, uaddr, ~oparg);
 		break;
 	case FUTEX_OP_XOR:
-		__futex_atomic_op("eor	%0, %1, %3", ret, oldval, uaddr, oparg);
+		__futex_atomic_op("eor	%0, %1, %4", ret, oldval, tmp, uaddr, oparg);
 		break;
 	default:
 		ret = -ENOSYS;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH] ARM: futex: preserve oldval in SMP __futex_atomic_op
  2011-09-22 18:35 [PATCH] ARM: futex: preserve oldval in SMP __futex_atomic_op Will Deacon
@ 2011-09-22 19:09 ` Nicolas Pitre
  2011-09-22 20:14   ` Will Deacon
  0 siblings, 1 reply; 3+ messages in thread
From: Nicolas Pitre @ 2011-09-22 19:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 22 Sep 2011, Will Deacon wrote:

> The SMP implementation of __futex_atomic_op clobbers oldval with the
> status flag from the exclusive store. This causes it to always read as
> zero when performing the FUTEX_OP_CMP_* operation.
> 
> This patch updates the ARM __futex_atomic_op implementations to take a
> tmp argument, allowing us to store the strex status flag without
> overwriting the register containing oldval.
> 
> Cc: stable at kernel.org
> Reported-by: Minho Ben <mhban@samsung.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>

Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>

> ---
> 
> Following up on:
> 
> http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/066348.html
> 
> it turns out that we don't need to use named arguments after all,
> although it might be nice to add that as a later patch. For now, I'm
> trying to keep this as small as possible for -stable.

Agreed that named arguments would make this code more obvious, 
especially with the insn argument of __futex_atomic_op() which uses 
numbered registers away from the actual inline asm statement where it is 
used.

I'm a bit worried that the LTP tests still passed though.  In theory it 
shouldn't have worked at all except if you were lucky with test values.

> 
>  arch/arm/include/asm/futex.h |   34 +++++++++++++++++-----------------
>  1 files changed, 17 insertions(+), 17 deletions(-)
> 
> diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
> index 8c73900..253cc86 100644
> --- a/arch/arm/include/asm/futex.h
> +++ b/arch/arm/include/asm/futex.h
> @@ -25,17 +25,17 @@
>  
>  #ifdef CONFIG_SMP
>  
> -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
> +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)	\
>  	smp_mb();						\
>  	__asm__ __volatile__(					\
> -	"1:	ldrex	%1, [%2]\n"				\
> +	"1:	ldrex	%1, [%3]\n"				\
>  	"	" insn "\n"					\
> -	"2:	strex	%1, %0, [%2]\n"				\
> -	"	teq	%1, #0\n"				\
> +	"2:	strex	%2, %0, [%3]\n"				\
> +	"	teq	%2, #0\n"				\
>  	"	bne	1b\n"					\
>  	"	mov	%0, #0\n"				\
> -	__futex_atomic_ex_table("%4")				\
> -	: "=&r" (ret), "=&r" (oldval)				\
> +	__futex_atomic_ex_table("%5")				\
> +	: "=&r" (ret), "=&r" (oldval), "=&r" (tmp)		\
>  	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
>  	: "cc", "memory")
>  
> @@ -73,14 +73,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
>  #include <linux/preempt.h>
>  #include <asm/domain.h>
>  
> -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
> +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)	\
>  	__asm__ __volatile__(					\
> -	"1:	" T(ldr) "	%1, [%2]\n"			\
> +	"1:	" T(ldr) "	%1, [%3]\n"			\
>  	"	" insn "\n"					\
> -	"2:	" T(str) "	%0, [%2]\n"			\
> +	"2:	" T(str) "	%0, [%3]\n"			\
>  	"	mov	%0, #0\n"				\
> -	__futex_atomic_ex_table("%4")				\
> -	: "=&r" (ret), "=&r" (oldval)				\
> +	__futex_atomic_ex_table("%5")				\
> +	: "=&r" (ret), "=&r" (oldval), "=&r" (tmp)		\
>  	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
>  	: "cc", "memory")
>  
> @@ -117,7 +117,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  	int cmp = (encoded_op >> 24) & 15;
>  	int oparg = (encoded_op << 8) >> 20;
>  	int cmparg = (encoded_op << 20) >> 20;
> -	int oldval = 0, ret;
> +	int oldval = 0, ret, tmp;
>  
>  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
>  		oparg = 1 << oparg;
> @@ -129,19 +129,19 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>  
>  	switch (op) {
>  	case FUTEX_OP_SET:
> -		__futex_atomic_op("mov	%0, %3", ret, oldval, uaddr, oparg);
> +		__futex_atomic_op("mov	%0, %4", ret, oldval, tmp, uaddr, oparg);
>  		break;
>  	case FUTEX_OP_ADD:
> -		__futex_atomic_op("add	%0, %1, %3", ret, oldval, uaddr, oparg);
> +		__futex_atomic_op("add	%0, %1, %4", ret, oldval, tmp, uaddr, oparg);
>  		break;
>  	case FUTEX_OP_OR:
> -		__futex_atomic_op("orr	%0, %1, %3", ret, oldval, uaddr, oparg);
> +		__futex_atomic_op("orr	%0, %1, %4", ret, oldval, tmp, uaddr, oparg);
>  		break;
>  	case FUTEX_OP_ANDN:
> -		__futex_atomic_op("and	%0, %1, %3", ret, oldval, uaddr, ~oparg);
> +		__futex_atomic_op("and	%0, %1, %4", ret, oldval, tmp, uaddr, ~oparg);
>  		break;
>  	case FUTEX_OP_XOR:
> -		__futex_atomic_op("eor	%0, %1, %3", ret, oldval, uaddr, oparg);
> +		__futex_atomic_op("eor	%0, %1, %4", ret, oldval, tmp, uaddr, oparg);
>  		break;
>  	default:
>  		ret = -ENOSYS;
> -- 
> 1.7.0.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] ARM: futex: preserve oldval in SMP __futex_atomic_op
  2011-09-22 19:09 ` Nicolas Pitre
@ 2011-09-22 20:14   ` Will Deacon
  0 siblings, 0 replies; 3+ messages in thread
From: Will Deacon @ 2011-09-22 20:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 08:09:41PM +0100, Nicolas Pitre wrote:
> On Thu, 22 Sep 2011, Will Deacon wrote:
> 
> > The SMP implementation of __futex_atomic_op clobbers oldval with the
> > status flag from the exclusive store. This causes it to always read as
> > zero when performing the FUTEX_OP_CMP_* operation.
> > 
> > This patch updates the ARM __futex_atomic_op implementations to take a
> > tmp argument, allowing us to store the strex status flag without
> > overwriting the register containing oldval.
> > 
> > Cc: stable at kernel.org
> > Reported-by: Minho Ben <mhban@samsung.com>
> > Signed-off-by: Will Deacon <will.deacon@arm.com>
> 
> Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>

Thanks Nicolas, I'll put this into the patch system tomorrow.

> > ---
> > 
> > Following up on:
> > 
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/066348.html
> > 
> > it turns out that we don't need to use named arguments after all,
> > although it might be nice to add that as a later patch. For now, I'm
> > trying to keep this as small as possible for -stable.
> 
> Agreed that named arguments would make this code more obvious, 
> especially with the insn argument of __futex_atomic_op() which uses 
> numbered registers away from the actual inline asm statement where it is 
> used.

Yup, I'll post this as a separate patch in the future.

> I'm a bit worried that the LTP tests still passed though.  In theory it 
> shouldn't have worked at all except if you were lucky with test values.

Urgh, I just looked at the implementation of the tests I ran; all they do is
check that the {set,get}_robust_list system calls return -1 when passed
invalid argument combinations. No wonder they passed...

Will

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-09-22 20:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-22 18:35 [PATCH] ARM: futex: preserve oldval in SMP __futex_atomic_op Will Deacon
2011-09-22 19:09 ` Nicolas Pitre
2011-09-22 20:14   ` Will Deacon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).