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.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#include <asm/asm-405.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	allow_write_to_user(uaddr, sizeof(*uaddr));
 39	pagefault_disable();
 40
 41	switch (op) {
 42	case FUTEX_OP_SET:
 43		__futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
 44		break;
 45	case FUTEX_OP_ADD:
 46		__futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
 47		break;
 48	case FUTEX_OP_OR:
 49		__futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
 50		break;
 51	case FUTEX_OP_ANDN:
 52		__futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
 53		break;
 54	case FUTEX_OP_XOR:
 55		__futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
 56		break;
 57	default:
 58		ret = -ENOSYS;
 59	}
 60
 61	pagefault_enable();
 62
 63	*oval = oldval;
 64
 65	prevent_write_to_user(uaddr, sizeof(*uaddr));
 66	return ret;
 67}
 68
 69static inline int
 70futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 71			      u32 oldval, u32 newval)
 72{
 73	int ret = 0;
 74	u32 prev;
 75
 76	if (!access_ok(uaddr, sizeof(u32)))
 77		return -EFAULT;
 78
 79	allow_write_to_user(uaddr, sizeof(*uaddr));
 80        __asm__ __volatile__ (
 81        PPC_ATOMIC_ENTRY_BARRIER
 82"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
 83        cmpw    0,%1,%4\n\
 84        bne-    3f\n"
 85        PPC405_ERR77(0,%3)
 86"2:     stwcx.  %5,0,%3\n\
 87        bne-    1b\n"
 88        PPC_ATOMIC_EXIT_BARRIER
 89"3:	.section .fixup,\"ax\"\n\
 904:	li	%0,%6\n\
 91	b	3b\n\
 92	.previous\n"
 93	EX_TABLE(1b, 4b)
 94	EX_TABLE(2b, 4b)
 95        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
 96        : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
 97        : "cc", "memory");
 98
 
 
 99	*uval = prev;
100	prevent_write_to_user(uaddr, sizeof(*uaddr));
101        return ret;
102}
103
104#endif /* __KERNEL__ */
105#endif /* _ASM_POWERPC_FUTEX_H */