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 */
v5.9
  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 (!access_ok(uaddr, sizeof(u32)))
 37		return -EFAULT;
 38	allow_read_write_user(uaddr, uaddr, sizeof(*uaddr));
 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	*oval = oldval;
 61
 62	prevent_read_write_user(uaddr, uaddr, sizeof(*uaddr));
 63	return ret;
 64}
 65
 66static inline int
 67futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 68			      u32 oldval, u32 newval)
 69{
 70	int ret = 0;
 71	u32 prev;
 72
 73	if (!access_ok(uaddr, sizeof(u32)))
 74		return -EFAULT;
 75
 76	allow_read_write_user(uaddr, uaddr, sizeof(*uaddr));
 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"2:     stwcx.  %5,0,%3\n\
 84        bne-    1b\n"
 85        PPC_ATOMIC_EXIT_BARRIER
 86"3:	.section .fixup,\"ax\"\n\
 874:	li	%0,%6\n\
 88	b	3b\n\
 89	.previous\n"
 90	EX_TABLE(1b, 4b)
 91	EX_TABLE(2b, 4b)
 92        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
 93        : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
 94        : "cc", "memory");
 95
 
 
 96	*uval = prev;
 97	prevent_read_write_user(uaddr, uaddr, sizeof(*uaddr));
 98
 99        return ret;
100}
101
102#endif /* __KERNEL__ */
103#endif /* _ASM_POWERPC_FUTEX_H */