Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1/* SPDX-License-Identifier: GPL-2.0 */
  2
  3#ifndef __ASM_CSKY_FUTEX_H
  4#define __ASM_CSKY_FUTEX_H
  5
  6#ifndef CONFIG_SMP
  7#include <asm-generic/futex.h>
  8#else
  9#include <linux/atomic.h>
 10#include <linux/futex.h>
 11#include <linux/uaccess.h>
 12#include <linux/errno.h>
 13
 14#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)		\
 15{									\
 16	u32 tmp;							\
 17									\
 18	__atomic_pre_full_fence();					\
 19									\
 20	__asm__ __volatile__ (						\
 21	"1:	ldex.w	%[ov], %[u]			\n"		\
 22	"	"insn"					\n"		\
 23	"2:	stex.w	%[t], %[u]			\n"		\
 24	"	bez	%[t], 1b			\n"		\
 25	"	br	4f				\n"		\
 26	"3:	mov	%[r], %[e]			\n"		\
 27	"4:						\n"		\
 28	"	.section __ex_table,\"a\"		\n"		\
 29	"	.balign 4				\n"		\
 30	"	.long	1b, 3b				\n"		\
 31	"	.long	2b, 3b				\n"		\
 32	"	.previous				\n"		\
 33	: [r] "+r" (ret), [ov] "=&r" (oldval),				\
 34	  [u] "+m" (*uaddr), [t] "=&r" (tmp)				\
 35	: [op] "Jr" (oparg), [e] "jr" (-EFAULT)				\
 36	: "memory");							\
 37									\
 38	__atomic_post_full_fence();					\
 39}
 40
 41static inline int
 42arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
 43{
 44	int oldval = 0, ret = 0;
 45
 46	if (!access_ok(uaddr, sizeof(u32)))
 47		return -EFAULT;
 48
 49	switch (op) {
 50	case FUTEX_OP_SET:
 51		__futex_atomic_op("mov %[t], %[ov]",
 52				  ret, oldval, uaddr, oparg);
 53		break;
 54	case FUTEX_OP_ADD:
 55		__futex_atomic_op("add %[t], %[ov], %[op]",
 56				  ret, oldval, uaddr, oparg);
 57		break;
 58	case FUTEX_OP_OR:
 59		__futex_atomic_op("or %[t], %[ov], %[op]",
 60				  ret, oldval, uaddr, oparg);
 61		break;
 62	case FUTEX_OP_ANDN:
 63		__futex_atomic_op("and %[t], %[ov], %[op]",
 64				  ret, oldval, uaddr, ~oparg);
 65		break;
 66	case FUTEX_OP_XOR:
 67		__futex_atomic_op("xor %[t], %[ov], %[op]",
 68				  ret, oldval, uaddr, oparg);
 69		break;
 70	default:
 71		ret = -ENOSYS;
 72	}
 73
 74	if (!ret)
 75		*oval = oldval;
 76
 77	return ret;
 78}
 79
 80
 81
 82static inline int
 83futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 84			      u32 oldval, u32 newval)
 85{
 86	int ret = 0;
 87	u32 val, tmp;
 88
 89	if (!access_ok(uaddr, sizeof(u32)))
 90		return -EFAULT;
 91
 92	__atomic_pre_full_fence();
 93
 94	__asm__ __volatile__ (
 95	"1:	ldex.w	%[v], %[u]			\n"
 96	"	cmpne	%[v], %[ov]			\n"
 97	"	bt	4f				\n"
 98	"	mov	%[t], %[nv]			\n"
 99	"2:	stex.w	%[t], %[u]			\n"
100	"	bez	%[t], 1b			\n"
101	"	br	4f				\n"
102	"3:	mov	%[r], %[e]			\n"
103	"4:						\n"
104	"	.section __ex_table,\"a\"		\n"
105	"	.balign 4				\n"
106	"	.long	1b, 3b				\n"
107	"	.long	2b, 3b				\n"
108	"	.previous				\n"
109	: [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr),
110	  [t] "=&r" (tmp)
111	: [ov] "Jr" (oldval), [nv] "Jr" (newval), [e] "Jr" (-EFAULT)
112	: "memory");
113
114	__atomic_post_full_fence();
115
116	*uval = val;
117	return ret;
118}
119
120#endif /* CONFIG_SMP */
121#endif /* __ASM_CSKY_FUTEX_H */