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.17
  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#include <asm/asm-compat.h>
 12
 13#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
 14  __asm__ __volatile ( \
 15	PPC_ATOMIC_ENTRY_BARRIER \
 16"1:	lwarx	%0,0,%2\n" \
 17	insn \
 18	PPC405_ERR77(0, %2) \
 19"2:	stwcx.	%1,0,%2\n" \
 20	"bne-	1b\n" \
 21	PPC_ATOMIC_EXIT_BARRIER \
 22	"li	%1,0\n" \
 23"3:	.section .fixup,\"ax\"\n" \
 24"4:	li	%1,%3\n" \
 25	"b	3b\n" \
 26	".previous\n" \
 27	EX_TABLE(1b, 4b) \
 28	EX_TABLE(2b, 4b) \
 29	: "=&r" (oldval), "=&r" (ret) \
 30	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 31	: "cr0", "memory")
 32
 33static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
 34		u32 __user *uaddr)
 35{
 36	int oldval = 0, ret;
 37
 38	pagefault_disable();
 
 39
 40	switch (op) {
 41	case FUTEX_OP_SET:
 42		__futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
 43		break;
 44	case FUTEX_OP_ADD:
 45		__futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
 46		break;
 47	case FUTEX_OP_OR:
 48		__futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
 49		break;
 50	case FUTEX_OP_ANDN:
 51		__futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
 52		break;
 53	case FUTEX_OP_XOR:
 54		__futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
 55		break;
 56	default:
 57		ret = -ENOSYS;
 58	}
 
 59
 60	pagefault_enable();
 61
 62	if (!ret)
 63		*oval = oldval;
 64
 65	return ret;
 66}
 67
 68static inline int
 69futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 70			      u32 oldval, u32 newval)
 71{
 72	int ret = 0;
 73	u32 prev;
 74
 75	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 76		return -EFAULT;
 77
 78        __asm__ __volatile__ (
 79        PPC_ATOMIC_ENTRY_BARRIER
 80"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
 81        cmpw    0,%1,%4\n\
 82        bne-    3f\n"
 83        PPC405_ERR77(0,%3)
 84"2:     stwcx.  %5,0,%3\n\
 85        bne-    1b\n"
 86        PPC_ATOMIC_EXIT_BARRIER
 87"3:	.section .fixup,\"ax\"\n\
 884:	li	%0,%6\n\
 89	b	3b\n\
 90	.previous\n"
 91	EX_TABLE(1b, 4b)
 92	EX_TABLE(2b, 4b)
 93        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
 94        : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
 95        : "cc", "memory");
 96
 
 
 97	*uval = prev;
 
 98        return ret;
 99}
100
101#endif /* __KERNEL__ */
102#endif /* _ASM_POWERPC_FUTEX_H */