* [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).