Linux Audio

Check our new training course

Loading...
v3.15
  1#ifndef _ASM_HEXAGON_FUTEX_H
  2#define _ASM_HEXAGON_FUTEX_H
  3
  4#ifdef __KERNEL__
  5
  6#include <linux/futex.h>
  7#include <linux/uaccess.h>
  8#include <asm/errno.h>
  9
 10/* XXX TODO-- need to add sync barriers! */
 11
 12#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
 13	__asm__ __volatile( \
 14	"1: %0 = memw_locked(%3);\n" \
 15	    /* For example: %1 = %4 */ \
 16	    insn \
 17	"2: memw_locked(%3,p2) = %1;\n" \
 18	"   if !p2 jump 1b;\n" \
 19	"   %1 = #0;\n" \
 20	"3:\n" \
 21	".section .fixup,\"ax\"\n" \
 22	"4: %1 = #%5;\n" \
 23	"   jump 3b\n" \
 24	".previous\n" \
 25	".section __ex_table,\"a\"\n" \
 26	".long 1b,4b,2b,4b\n" \
 27	".previous\n" \
 28	: "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
 29	: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
 30	: "p2", "memory")
 31
 32
 33static inline int
 34futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 35{
 36	int op = (encoded_op >> 28) & 7;
 37	int cmp = (encoded_op >> 24) & 15;
 38	int oparg = (encoded_op << 8) >> 20;
 39	int cmparg = (encoded_op << 20) >> 20;
 40	int oldval = 0, ret;
 41	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 42		oparg = 1 << oparg;
 43
 44	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 45		return -EFAULT;
 46
 47	pagefault_disable();
 48
 49	switch (op) {
 50	case FUTEX_OP_SET:
 51		__futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg);
 52		break;
 53	case FUTEX_OP_ADD:
 54		__futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr,
 55				  oparg);
 56		break;
 57	case FUTEX_OP_OR:
 58		__futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr,
 59				  oparg);
 60		break;
 61	case FUTEX_OP_ANDN:
 62		__futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret,
 63				  oldval, uaddr, oparg);
 64		break;
 65	case FUTEX_OP_XOR:
 66		__futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr,
 67				  oparg);
 68		break;
 69	default:
 70		ret = -ENOSYS;
 71	}
 72
 73	pagefault_enable();
 74
 75	if (!ret) {
 76		switch (cmp) {
 77		case FUTEX_OP_CMP_EQ:
 78			ret = (oldval == cmparg);
 79			break;
 80		case FUTEX_OP_CMP_NE:
 81			ret = (oldval != cmparg);
 82			break;
 83		case FUTEX_OP_CMP_LT:
 84			ret = (oldval < cmparg);
 85			break;
 86		case FUTEX_OP_CMP_GE:
 87			ret = (oldval >= cmparg);
 88			break;
 89		case FUTEX_OP_CMP_LE:
 90			ret = (oldval <= cmparg);
 91			break;
 92		case FUTEX_OP_CMP_GT:
 93			ret = (oldval > cmparg);
 94			break;
 95		default:
 96			ret = -ENOSYS;
 97		}
 98	}
 99	return ret;
100}
101
102static inline int
103futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
104			      u32 newval)
105{
106	int prev;
107	int ret;
108
109	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
110		return -EFAULT;
111
112	__asm__ __volatile__ (
113	"1: %1 = memw_locked(%3)\n"
114	"   {\n"
115	"      p2 = cmp.eq(%1,%4)\n"
116	"      if !p2.new jump:NT 3f\n"
117	"   }\n"
118	"2: memw_locked(%3,p2) = %5\n"
119	"   if !p2 jump 1b\n"
120	"3:\n"
121	".section .fixup,\"ax\"\n"
122	"4: %0 = #%6\n"
123	"   jump 3b\n"
124	".previous\n"
125	".section __ex_table,\"a\"\n"
126	".long 1b,4b,2b,4b\n"
127	".previous\n"
128	: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
129	: "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT)
130	: "p2", "memory");
131
132	*uval = prev;
133	return ret;
134}
135
136#endif /* __KERNEL__ */
137#endif /* _ASM_HEXAGON_FUTEX_H */
v4.6
  1#ifndef _ASM_HEXAGON_FUTEX_H
  2#define _ASM_HEXAGON_FUTEX_H
  3
  4#ifdef __KERNEL__
  5
  6#include <linux/futex.h>
  7#include <linux/uaccess.h>
  8#include <asm/errno.h>
  9
 10/* XXX TODO-- need to add sync barriers! */
 11
 12#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
 13	__asm__ __volatile( \
 14	"1: %0 = memw_locked(%3);\n" \
 15	    /* For example: %1 = %4 */ \
 16	    insn \
 17	"2: memw_locked(%3,p2) = %1;\n" \
 18	"   if !p2 jump 1b;\n" \
 19	"   %1 = #0;\n" \
 20	"3:\n" \
 21	".section .fixup,\"ax\"\n" \
 22	"4: %1 = #%5;\n" \
 23	"   jump 3b\n" \
 24	".previous\n" \
 25	".section __ex_table,\"a\"\n" \
 26	".long 1b,4b,2b,4b\n" \
 27	".previous\n" \
 28	: "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \
 29	: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
 30	: "p2", "memory")
 31
 32
 33static inline int
 34futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 35{
 36	int op = (encoded_op >> 28) & 7;
 37	int cmp = (encoded_op >> 24) & 15;
 38	int oparg = (encoded_op << 8) >> 20;
 39	int cmparg = (encoded_op << 20) >> 20;
 40	int oldval = 0, ret;
 41	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 42		oparg = 1 << oparg;
 43
 44	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
 45		return -EFAULT;
 46
 47	pagefault_disable();
 48
 49	switch (op) {
 50	case FUTEX_OP_SET:
 51		__futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg);
 52		break;
 53	case FUTEX_OP_ADD:
 54		__futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr,
 55				  oparg);
 56		break;
 57	case FUTEX_OP_OR:
 58		__futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr,
 59				  oparg);
 60		break;
 61	case FUTEX_OP_ANDN:
 62		__futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret,
 63				  oldval, uaddr, oparg);
 64		break;
 65	case FUTEX_OP_XOR:
 66		__futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr,
 67				  oparg);
 68		break;
 69	default:
 70		ret = -ENOSYS;
 71	}
 72
 73	pagefault_enable();
 74
 75	if (!ret) {
 76		switch (cmp) {
 77		case FUTEX_OP_CMP_EQ:
 78			ret = (oldval == cmparg);
 79			break;
 80		case FUTEX_OP_CMP_NE:
 81			ret = (oldval != cmparg);
 82			break;
 83		case FUTEX_OP_CMP_LT:
 84			ret = (oldval < cmparg);
 85			break;
 86		case FUTEX_OP_CMP_GE:
 87			ret = (oldval >= cmparg);
 88			break;
 89		case FUTEX_OP_CMP_LE:
 90			ret = (oldval <= cmparg);
 91			break;
 92		case FUTEX_OP_CMP_GT:
 93			ret = (oldval > cmparg);
 94			break;
 95		default:
 96			ret = -ENOSYS;
 97		}
 98	}
 99	return ret;
100}
101
102static inline int
103futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
104			      u32 newval)
105{
106	int prev;
107	int ret;
108
109	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
110		return -EFAULT;
111
112	__asm__ __volatile__ (
113	"1: %1 = memw_locked(%3)\n"
114	"   {\n"
115	"      p2 = cmp.eq(%1,%4)\n"
116	"      if !p2.new jump:NT 3f\n"
117	"   }\n"
118	"2: memw_locked(%3,p2) = %5\n"
119	"   if !p2 jump 1b\n"
120	"3:\n"
121	".section .fixup,\"ax\"\n"
122	"4: %0 = #%6\n"
123	"   jump 3b\n"
124	".previous\n"
125	".section __ex_table,\"a\"\n"
126	".long 1b,4b,2b,4b\n"
127	".previous\n"
128	: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
129	: "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT)
130	: "p2", "memory");
131
132	*uval = prev;
133	return ret;
134}
135
136#endif /* __KERNEL__ */
137#endif /* _ASM_HEXAGON_FUTEX_H */