177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#ifndef _ASM_ALPHA_FUTEX_H
277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#define _ASM_ALPHA_FUTEX_H
34732efbeb997189d9f9b04708dc26bf8613ed721Jakub Jelinek
477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#ifdef __KERNEL__
54732efbeb997189d9f9b04708dc26bf8613ed721Jakub Jelinek
677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <linux/futex.h>
777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <linux/uaccess.h>
877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <asm/errno.h>
977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <asm/barrier.h>
1077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
1177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
1277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	__asm__ __volatile__(					\
1377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		__ASM_SMP_MB					\
1477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"1:	ldl_l	%0,0(%2)\n"				\
1577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		insn						\
1677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"2:	stl_c	%1,0(%2)\n"				\
1777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	beq	%1,4f\n"				\
1877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	mov	$31,%1\n"				\
1977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"3:	.subsection 2\n"				\
2077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"4:	br	1b\n"					\
2177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.previous\n"					\
2277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.section __ex_table,\"a\"\n"			\
2377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.long	1b-.\n"					\
2477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	lda	$31,3b-1b(%1)\n"			\
2577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.long	2b-.\n"					\
2677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	lda	$31,3b-2b(%1)\n"			\
2777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.previous\n"					\
2877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	:	"=&r" (oldval), "=&r"(ret)			\
2977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	:	"r" (uaddr), "r"(oparg)				\
3077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	:	"memory")
3177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
328d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinassestatic inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
3377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky{
3477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	int op = (encoded_op >> 28) & 7;
3577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	int cmp = (encoded_op >> 24) & 15;
3677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	int oparg = (encoded_op << 8) >> 20;
3777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	int cmparg = (encoded_op << 20) >> 20;
3877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	int oldval = 0, ret;
3977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
4077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		oparg = 1 << oparg;
4177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
428d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
4377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		return -EFAULT;
4477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
4577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	pagefault_disable();
4677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
4777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	switch (op) {
4877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	case FUTEX_OP_SET:
4977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		__futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg);
5077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		break;
5177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	case FUTEX_OP_ADD:
5277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		__futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg);
5377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		break;
5477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	case FUTEX_OP_OR:
5577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		__futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg);
5677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		break;
5777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	case FUTEX_OP_ANDN:
5877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		__futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg);
5977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		break;
6077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	case FUTEX_OP_XOR:
6177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		__futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg);
6277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		break;
6377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	default:
6477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		ret = -ENOSYS;
6577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	}
6677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
6777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	pagefault_enable();
6877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
6977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	if (!ret) {
7077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		switch (cmp) {
7177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
7277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
7377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
7477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
7577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
7677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
7777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		default: ret = -ENOSYS;
7877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		}
7977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	}
8077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	return ret;
8177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky}
8277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
8377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshayskystatic inline int
848d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinassefutex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
858d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse			      u32 oldval, u32 newval)
8677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky{
878d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse	int ret = 0, cmp;
888d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse	u32 prev;
8977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
908d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
9177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		return -EFAULT;
9277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
9377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	__asm__ __volatile__ (
9477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky		__ASM_SMP_MB
9537a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	"1:	ldl_l	%1,0(%3)\n"
9637a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	"	cmpeq	%1,%4,%2\n"
9737a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	"	beq	%2,3f\n"
9837a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	"	mov	%5,%2\n"
9937a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	"2:	stl_c	%2,0(%3)\n"
10037a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	"	beq	%2,4f\n"
10177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"3:	.subsection 2\n"
10277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"4:	br	1b\n"
10377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.previous\n"
10477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.section __ex_table,\"a\"\n"
10577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.long	1b-.\n"
10677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	lda	$31,3b-1b(%0)\n"
10777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.long	2b-.\n"
10877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	lda	$31,3b-2b(%0)\n"
10977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	"	.previous\n"
11037a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
11162aca403657fe30e5235c5331e9871e676d9ea0aAndrew Morton	:	"r"(uaddr), "r"((long)(int)oldval), "r"(newval)
11277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky	:	"memory");
11377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
11437a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	*uval = prev;
11537a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse	return ret;
11677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky}
11777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky
11877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#endif /* __KERNEL__ */
11977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#endif /* _ASM_ALPHA_FUTEX_H */
120