• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _ASM_ALPHA_FUTEX_H
2 #define _ASM_ALPHA_FUTEX_H
3 
4 #ifdef __KERNEL__
5 
6 #include <linux/futex.h>
7 #include <linux/uaccess.h>
8 #include <asm/errno.h>
9 #include <asm/barrier.h>
10 
11 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
12 	__asm__ __volatile__(					\
13 		__ASM_SMP_MB					\
14 	"1:	ldl_l	%0,0(%2)\n"				\
15 		insn						\
16 	"2:	stl_c	%1,0(%2)\n"				\
17 	"	beq	%1,4f\n"				\
18 	"	mov	$31,%1\n"				\
19 	"3:	.subsection 2\n"				\
20 	"4:	br	1b\n"					\
21 	"	.previous\n"					\
22 	"	.section __ex_table,\"a\"\n"			\
23 	"	.long	1b-.\n"					\
24 	"	lda	$31,3b-1b(%1)\n"			\
25 	"	.long	2b-.\n"					\
26 	"	lda	$31,3b-2b(%1)\n"			\
27 	"	.previous\n"					\
28 	:	"=&r" (oldval), "=&r"(ret)			\
29 	:	"r" (uaddr), "r"(oparg)				\
30 	:	"memory")
31 
arch_futex_atomic_op_inuser(int op,int oparg,int * oval,u32 __user * uaddr)32 static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
33 		u32 __user *uaddr)
34 {
35 	int oldval = 0, ret;
36 
37 	pagefault_disable();
38 
39 	switch (op) {
40 	case FUTEX_OP_SET:
41 		__futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg);
42 		break;
43 	case FUTEX_OP_ADD:
44 		__futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg);
45 		break;
46 	case FUTEX_OP_OR:
47 		__futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg);
48 		break;
49 	case FUTEX_OP_ANDN:
50 		__futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg);
51 		break;
52 	case FUTEX_OP_XOR:
53 		__futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg);
54 		break;
55 	default:
56 		ret = -ENOSYS;
57 	}
58 
59 	pagefault_enable();
60 
61 	if (!ret)
62 		*oval = oldval;
63 
64 	return ret;
65 }
66 
67 static inline int
futex_atomic_cmpxchg_inatomic(u32 * uval,u32 __user * uaddr,u32 oldval,u32 newval)68 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
69 			      u32 oldval, u32 newval)
70 {
71 	int ret = 0, cmp;
72 	u32 prev;
73 
74 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
75 		return -EFAULT;
76 
77 	__asm__ __volatile__ (
78 		__ASM_SMP_MB
79 	"1:	ldl_l	%1,0(%3)\n"
80 	"	cmpeq	%1,%4,%2\n"
81 	"	beq	%2,3f\n"
82 	"	mov	%5,%2\n"
83 	"2:	stl_c	%2,0(%3)\n"
84 	"	beq	%2,4f\n"
85 	"3:	.subsection 2\n"
86 	"4:	br	1b\n"
87 	"	.previous\n"
88 	"	.section __ex_table,\"a\"\n"
89 	"	.long	1b-.\n"
90 	"	lda	$31,3b-1b(%0)\n"
91 	"	.long	2b-.\n"
92 	"	lda	$31,3b-2b(%0)\n"
93 	"	.previous\n"
94 	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
95 	:	"r"(uaddr), "r"((long)(int)oldval), "r"(newval)
96 	:	"memory");
97 
98 	*uval = prev;
99 	return ret;
100 }
101 
102 #endif /* __KERNEL__ */
103 #endif /* _ASM_ALPHA_FUTEX_H */
104