Linux Audio

Check our new training course

Loading...
v6.9.4
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _ASM_POWERPC_FUTEX_H
  3#define _ASM_POWERPC_FUTEX_H
  4
  5#ifdef __KERNEL__
  6
  7#include <linux/futex.h>
  8#include <linux/uaccess.h>
  9#include <asm/errno.h>
 10#include <asm/synch.h>
 
 11
 12#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
 13  __asm__ __volatile ( \
 14	PPC_ATOMIC_ENTRY_BARRIER \
 15"1:	lwarx	%0,0,%2\n" \
 16	insn \
 
 17"2:	stwcx.	%1,0,%2\n" \
 18	"bne-	1b\n" \
 19	PPC_ATOMIC_EXIT_BARRIER \
 20	"li	%1,0\n" \
 21"3:	.section .fixup,\"ax\"\n" \
 22"4:	li	%1,%3\n" \
 23	"b	3b\n" \
 24	".previous\n" \
 25	EX_TABLE(1b, 4b) \
 26	EX_TABLE(2b, 4b) \
 27	: "=&r" (oldval), "=&r" (ret) \
 28	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 29	: "cr0", "memory")
 30
 31static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
 32		u32 __user *uaddr)
 33{
 
 
 
 
 34	int oldval = 0, ret;
 
 
 35
 36	if (!user_access_begin(uaddr, sizeof(u32)))
 37		return -EFAULT;
 38
 
 
 39	switch (op) {
 40	case FUTEX_OP_SET:
 41		__futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
 42		break;
 43	case FUTEX_OP_ADD:
 44		__futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
 45		break;
 46	case FUTEX_OP_OR:
 47		__futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
 48		break;
 49	case FUTEX_OP_ANDN:
 50		__futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
 51		break;
 52	case FUTEX_OP_XOR:
 53		__futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
 54		break;
 55	default:
 56		ret = -ENOSYS;
 57	}
 58	user_access_end();
 59
 60	*oval = oldval;
 61
 
 
 
 
 
 
 
 
 
 
 
 62	return ret;
 63}
 64
 65static inline int
 66futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 67			      u32 oldval, u32 newval)
 68{
 69	int ret = 0;
 70	u32 prev;
 71
 72	if (!user_access_begin(uaddr, sizeof(u32)))
 73		return -EFAULT;
 74
 75        __asm__ __volatile__ (
 76        PPC_ATOMIC_ENTRY_BARRIER
 77"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
 78        cmpw    0,%1,%4\n\
 79        bne-    3f\n"
 
 80"2:     stwcx.  %5,0,%3\n\
 81        bne-    1b\n"
 82        PPC_ATOMIC_EXIT_BARRIER
 83"3:	.section .fixup,\"ax\"\n\
 844:	li	%0,%6\n\
 85	b	3b\n\
 86	.previous\n"
 87	EX_TABLE(1b, 4b)
 88	EX_TABLE(2b, 4b)
 89        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
 90        : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
 91        : "cc", "memory");
 92
 93	user_access_end();
 94
 95	*uval = prev;
 96
 97        return ret;
 98}
 99
100#endif /* __KERNEL__ */
101#endif /* _ASM_POWERPC_FUTEX_H */
v4.10.11
 
  1#ifndef _ASM_POWERPC_FUTEX_H
  2#define _ASM_POWERPC_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/synch.h>
 10#include <asm/asm-compat.h>
 11
 12#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
 13  __asm__ __volatile ( \
 14	PPC_ATOMIC_ENTRY_BARRIER \
 15"1:	lwarx	%0,0,%2\n" \
 16	insn \
 17	PPC405_ERR77(0, %2) \
 18"2:	stwcx.	%1,0,%2\n" \
 19	"bne-	1b\n" \
 20	PPC_ATOMIC_EXIT_BARRIER \
 21	"li	%1,0\n" \
 22"3:	.section .fixup,\"ax\"\n" \
 23"4:	li	%1,%3\n" \
 24	"b	3b\n" \
 25	".previous\n" \
 26	EX_TABLE(1b, 4b) \
 27	EX_TABLE(2b, 4b) \
 28	: "=&r" (oldval), "=&r" (ret) \
 29	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 30	: "cr0", "memory")
 31
 32static inline int futex_atomic_op_inuser (int encoded_op, u32 __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(u32)))
 43		return -EFAULT;
 44
 45	pagefault_disable();
 46
 47	switch (op) {
 48	case FUTEX_OP_SET:
 49		__futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
 50		break;
 51	case FUTEX_OP_ADD:
 52		__futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
 53		break;
 54	case FUTEX_OP_OR:
 55		__futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
 56		break;
 57	case FUTEX_OP_ANDN:
 58		__futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
 59		break;
 60	case FUTEX_OP_XOR:
 61		__futex_atomic_op("xor %1,%0,%4\n", 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: ret = (oldval == cmparg); break;
 72		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
 73		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
 74		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
 75		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
 76		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
 77		default: ret = -ENOSYS;
 78		}
 79	}
 80	return ret;
 81}
 82
 83static inline int
 84futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 85			      u32 oldval, u32 newval)
 86{
 87	int ret = 0;
 88	u32 prev;
 89
 90	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 91		return -EFAULT;
 92
 93        __asm__ __volatile__ (
 94        PPC_ATOMIC_ENTRY_BARRIER
 95"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
 96        cmpw    0,%1,%4\n\
 97        bne-    3f\n"
 98        PPC405_ERR77(0,%3)
 99"2:     stwcx.  %5,0,%3\n\
100        bne-    1b\n"
101        PPC_ATOMIC_EXIT_BARRIER
102"3:	.section .fixup,\"ax\"\n\
1034:	li	%0,%6\n\
104	b	3b\n\
105	.previous\n"
106	EX_TABLE(1b, 4b)
107	EX_TABLE(2b, 4b)
108        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
109        : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
110        : "cc", "memory");
111
 
 
112	*uval = prev;
 
113        return ret;
114}
115
116#endif /* __KERNEL__ */
117#endif /* _ASM_POWERPC_FUTEX_H */