Commit 2ff2ae7a authored by David Gibson's avatar David Gibson Committed by Paul Mackerras

[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: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 847aeb6b
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
#ifndef _ASM_POWERPC_FUTEX_H
#define _ASM_POWERPC_FUTEX_H
#ifdef __KERNEL__
......@@ -7,28 +7,29 @@
#include <asm/errno.h>
#include <asm/synch.h>
#include <asm/uaccess.h>
#include <asm/ppc_asm.h>
#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\
.llong 1b,4b,2b,4b\n\
.previous" \
: "=&r" (oldval), "=&r" (ret) \
: "b" (uaddr), "i" (-EFAULT), "1" (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)
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;
......@@ -79,5 +80,5 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
return ret;
}
#endif
#endif
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_FUTEX_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 */
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
#ifdef __KERNEL__
#include <linux/futex.h>
#include <asm/errno.h>
#include <asm/uaccess.h>
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:
case FUTEX_OP_ADD:
case FUTEX_OP_OR:
case FUTEX_OP_ANDN:
case FUTEX_OP_XOR:
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
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment