• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/microblaze/include/asm/
1#ifndef _ASM_MICROBLAZE_FUTEX_H
2#define _ASM_MICROBLAZE_FUTEX_H
3
4#ifdef __KERNEL__
5
6#include <linux/futex.h>
7#include <linux/uaccess.h>
8#include <asm/errno.h>
9
10#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
11({									\
12	__asm__ __volatile__ (						\
13			"1:	lwx	%0, %2, r0; "			\
14				insn					\
15			"2:	swx	%1, %2, r0;			\
16				addic	%1, r0, 0;			\
17				bnei	%1, 1b;				\
18			3:						\
19			.section .fixup,\"ax\";				\
20			4:	brid	3b;				\
21				addik	%1, r0, %3;			\
22			.previous;					\
23			.section __ex_table,\"a\";			\
24			.word	1b,4b,2b,4b;				\
25			.previous;"					\
26	: "=&r" (oldval), "=&r" (ret)					\
27	: "b" (uaddr), "i" (-EFAULT), "r" (oparg)			\
28	);								\
29})
30
31static inline int
32futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
33{
34	int op = (encoded_op >> 28) & 7;
35	int cmp = (encoded_op >> 24) & 15;
36	int oparg = (encoded_op << 8) >> 20;
37	int cmparg = (encoded_op << 20) >> 20;
38	int oldval = 0, ret;
39	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
40		oparg = 1 << oparg;
41
42	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
43		return -EFAULT;
44
45	pagefault_disable();
46
47	switch (op) {
48	case FUTEX_OP_SET:
49		__futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg);
50		break;
51	case FUTEX_OP_ADD:
52		__futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg);
53		break;
54	case FUTEX_OP_OR:
55		__futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg);
56		break;
57	case FUTEX_OP_ANDN:
58		__futex_atomic_op("andn %1,%0,%4;", ret, oldval, uaddr, oparg);
59		break;
60	case FUTEX_OP_XOR:
61		__futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg);
62		break;
63	default:
64		ret = -ENOSYS;
65	}
66
67	pagefault_enable();
68
69	if (!ret) {
70		switch (cmp) {
71		case FUTEX_OP_CMP_EQ:
72			ret = (oldval == cmparg);
73			break;
74		case FUTEX_OP_CMP_NE:
75			ret = (oldval != cmparg);
76			break;
77		case FUTEX_OP_CMP_LT:
78			ret = (oldval < cmparg);
79			break;
80		case FUTEX_OP_CMP_GE:
81			ret = (oldval >= cmparg);
82			break;
83		case FUTEX_OP_CMP_LE:
84			ret = (oldval <= cmparg);
85			break;
86		case FUTEX_OP_CMP_GT:
87			ret = (oldval > cmparg);
88			break;
89		default:
90			ret = -ENOSYS;
91		}
92	}
93	return ret;
94}
95
96static inline int
97futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
98{
99	int prev, cmp;
100
101	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
102		return -EFAULT;
103
104	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
105					cmp	%1, %0, %3;		\
106					beqi	%1, 3f;			\
107				2:	swx	%4, %2, r0;		\
108					addic	%1, r0, 0;		\
109					bnei	%1, 1b;			\
110				3:					\
111				.section .fixup,\"ax\";			\
112				4:	brid	3b;			\
113					addik	%0, r0, %5;		\
114				.previous;				\
115				.section __ex_table,\"a\";		\
116				.word	1b,4b,2b,4b;			\
117				.previous;"				\
118		: "=&r" (prev), "=&r"(cmp)				\
119		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
120
121	return prev;
122}
123
124#endif /* __KERNEL__ */
125
126#endif
127