cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

futex.h (2246B)


      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 */