linux/arch/powerpc/include/asm/futex.h
<<
>>
Prefs
   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(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 */
 103