Skip to content

Commit

Permalink
[MIPS] Update/fix futex assembly
Browse files Browse the repository at this point in the history
    
 o Implement futex_atomic_op_inuser() operation
 o Don't use the R10000-ll/sc bug workaround version for every processor.
   branch likely is deprecated and some historic ll/sc processors don't
   implement it.  In any case it's slow.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Ralf Baechle committed May 31, 2006
1 parent 235a9d3 commit 6ee1da9
Showing 1 changed file with 116 additions and 25 deletions.
141 changes: 116 additions & 25 deletions include/asm-mips/futex.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <linux/futex.h>
#include <asm/errno.h>
#include <asm/uaccess.h>
#include <asm/war.h>

#ifdef CONFIG_SMP
#define __FUTEX_SMP_SYNC " sync \n"
Expand All @@ -16,30 +17,58 @@

#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
{ \
__asm__ __volatile__( \
" .set push \n" \
" .set noat \n" \
" .set mips3 \n" \
"1: ll %1, (%3) # __futex_atomic_op1 \n" \
" .set mips0 \n" \
" " insn " \n" \
" .set mips3 \n" \
"2: sc $1, (%3) \n" \
" beqzl $1, 1b \n" \
__FUTEX_SMP_SYNC \
"3: \n" \
" .set pop \n" \
" .set mips0 \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %5 \n" \
" j 2b \n" \
" .previous \n" \
" .section __ex_table,\"a\" \n" \
" "__UA_ADDR "\t1b, 4b \n" \
" "__UA_ADDR "\t2b, 4b \n" \
" .previous \n" \
: "=r" (ret), "=r" (oldval) \
: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \
if (cpu_has_llsc && R10000_LLSC_WAR) { \
__asm__ __volatile__( \
" .set push \n" \
" .set noat \n" \
" .set mips3 \n" \
"1: ll %1, (%3) # __futex_atomic_op \n" \
" .set mips0 \n" \
" " insn " \n" \
" .set mips3 \n" \
"2: sc $1, (%3) \n" \
" beqzl $1, 1b \n" \
__FUTEX_SMP_SYNC \
"3: \n" \
" .set pop \n" \
" .set mips0 \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %5 \n" \
" j 2b \n" \
" .previous \n" \
" .section __ex_table,\"a\" \n" \
" "__UA_ADDR "\t1b, 4b \n" \
" "__UA_ADDR "\t2b, 4b \n" \
" .previous \n" \
: "=r" (ret), "=r" (oldval) \
: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \
} else if (cpu_has_llsc) { \
__asm__ __volatile__( \
" .set push \n" \
" .set noat \n" \
" .set mips3 \n" \
"1: ll %1, (%3) # __futex_atomic_op \n" \
" .set mips0 \n" \
" " insn " \n" \
" .set mips3 \n" \
"2: sc $1, (%3) \n" \
" beqz $1, 1b \n" \
__FUTEX_SMP_SYNC \
"3: \n" \
" .set pop \n" \
" .set mips0 \n" \
" .section .fixup,\"ax\" \n" \
"4: li %0, %5 \n" \
" j 2b \n" \
" .previous \n" \
" .section __ex_table,\"a\" \n" \
" "__UA_ADDR "\t1b, 4b \n" \
" "__UA_ADDR "\t2b, 4b \n" \
" .previous \n" \
: "=r" (ret), "=r" (oldval) \
: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \
} else \
ret = -ENOSYS; \
}

static inline int
Expand Down Expand Up @@ -102,7 +131,69 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
static inline int
futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
{
return -ENOSYS;
int retval;

if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
return -EFAULT;

if (cpu_has_llsc && R10000_LLSC_WAR) {
__asm__ __volatile__(
"# futex_atomic_cmpxchg_inatomic \n"
" .set push \n"
" .set noat \n"
" .set mips3 \n"
"1: ll %0, %2 \n"
" bne %0, %z3, 3f \n"
" .set mips0 \n"
" move $1, %z4 \n"
" .set mips3 \n"
"2: sc $1, %1 \n"
" beqzl $1, 1b \n"
__FUTEX_SMP_SYNC
"3: \n"
" .set pop \n"
" .section .fixup,\"ax\" \n"
"4: li %0, %5 \n"
" j 3b \n"
" .previous \n"
" .section __ex_table,\"a\" \n"
" "__UA_ADDR "\t1b, 4b \n"
" "__UA_ADDR "\t2b, 4b \n"
" .previous \n"
: "=&r" (retval), "=R" (*uaddr)
: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
: "memory");
} else if (cpu_has_llsc) {
__asm__ __volatile__(
"# futex_atomic_cmpxchg_inatomic \n"
" .set push \n"
" .set noat \n"
" .set mips3 \n"
"1: ll %0, %2 \n"
" bne %0, %z3, 3f \n"
" .set mips0 \n"
" move $1, %z4 \n"
" .set mips3 \n"
"2: sc $1, %1 \n"
" beqz $1, 1b \n"
__FUTEX_SMP_SYNC
"3: \n"
" .set pop \n"
" .section .fixup,\"ax\" \n"
"4: li %0, %5 \n"
" j 3b \n"
" .previous \n"
" .section __ex_table,\"a\" \n"
" "__UA_ADDR "\t1b, 4b \n"
" "__UA_ADDR "\t2b, 4b \n"
" .previous \n"
: "=&r" (retval), "=R" (*uaddr)
: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
: "memory");
} else
return -ENOSYS;

return retval;
}

#endif
Expand Down

0 comments on commit 6ee1da9

Please sign in to comment.