From 2ff2ae7a0d7bfd813325663dc6353d034db7473d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 2 Nov 2005 13:58:22 +1100 Subject: [PATCH] powerpc: Merge futex.h This patch merges the ppc32 and ppc64 versions of futex.h, essentially by taking the ppc64 version as the powerpc version. The old ppc32 version did not implement the futex_atomic_op_inuser() callback (it always returned -ENOSYS), so FUTEX_WAKE_OP would not work on ppc32. In fact the ppc64 version of this function is almost suitable for ppc32 as well - the only change needed is to extend ppc_asm.h with a macro expanding to to the right pseudo-op to store a pointer (either ".long" or ".llong"). Built and booted on pSeries. Built for 32-bit powermac. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/futex.h | 84 +++++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/ppc_asm.h | 7 ++++ 2 files changed, 91 insertions(+) create mode 100644 include/asm-powerpc/futex.h (limited to 'include/asm-powerpc') diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h new file mode 100644 index 00000000000..37c94e52ab6 --- /dev/null +++ b/include/asm-powerpc/futex.h @@ -0,0 +1,84 @@ +#ifndef _ASM_POWERPC_FUTEX_H +#define _ASM_POWERPC_FUTEX_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ + __asm__ __volatile ( \ + SYNC_ON_SMP \ +"1: lwarx %0,0,%2\n" \ + insn \ +"2: stwcx. %1,0,%2\n" \ + "bne- 1b\n" \ + "li %1,0\n" \ +"3: .section .fixup,\"ax\"\n" \ +"4: li %1,%3\n" \ + "b 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + ".align 3\n" \ + DATAL " 1b,4b,2b,4b\n" \ + ".previous" \ + : "=&r" (oldval), "=&r" (ret) \ + : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ + : "cr0", "memory") + +static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + inc_preempt_count(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + dec_preempt_count(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; + case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; + case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; + case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; + case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; + case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; + default: ret = -ENOSYS; + } + } + return ret; +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_FUTEX_H */ diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h index f99f2af82ca..c534ca41224 100644 --- a/include/asm-powerpc/ppc_asm.h +++ b/include/asm-powerpc/ppc_asm.h @@ -506,6 +506,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) #else #define __ASM_CONST(x) x##UL #define ASM_CONST(x) __ASM_CONST(x) + +#ifdef CONFIG_PPC64 +#define DATAL ".llong" +#else +#define DATAL ".long" +#endif + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_PPC_ASM_H */ -- cgit v1.2.3-70-g09d2