linux/arch/s390/include/asm/futex.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _ASM_S390_FUTEX_H
   3#define _ASM_S390_FUTEX_H
   4
   5#include <linux/uaccess.h>
   6#include <linux/futex.h>
   7#include <asm/mmu_context.h>
   8#include <asm/errno.h>
   9
  10#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)      \
  11        asm volatile(                                                   \
  12                "   sacf  256\n"                                        \
  13                "0: l     %1,0(%6)\n"                                   \
  14                "1:"insn                                                \
  15                "2: cs    %1,%2,0(%6)\n"                                \
  16                "3: jl    1b\n"                                         \
  17                "   lhi   %0,0\n"                                       \
  18                "4: sacf  768\n"                                        \
  19                EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b)         \
  20                : "=d" (ret), "=&d" (oldval), "=&d" (newval),           \
  21                  "=m" (*uaddr)                                         \
  22                : "0" (-EFAULT), "d" (oparg), "a" (uaddr),              \
  23                  "m" (*uaddr) : "cc");
  24
  25static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
  26                u32 __user *uaddr)
  27{
  28        int oldval = 0, newval, ret;
  29
  30        switch (op) {
  31        case FUTEX_OP_SET:
  32                __futex_atomic_op("lr %2,%5\n",
  33                                  ret, oldval, newval, uaddr, oparg);
  34                break;
  35        case FUTEX_OP_ADD:
  36                __futex_atomic_op("lr %2,%1\nar %2,%5\n",
  37                                  ret, oldval, newval, uaddr, oparg);
  38                break;
  39        case FUTEX_OP_OR:
  40                __futex_atomic_op("lr %2,%1\nor %2,%5\n",
  41                                  ret, oldval, newval, uaddr, oparg);
  42                break;
  43        case FUTEX_OP_ANDN:
  44                __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
  45                                  ret, oldval, newval, uaddr, oparg);
  46                break;
  47        case FUTEX_OP_XOR:
  48                __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
  49                                  ret, oldval, newval, uaddr, oparg);
  50                break;
  51        default:
  52                ret = -ENOSYS;
  53        }
  54
  55        if (!ret)
  56                *oval = oldval;
  57
  58        return ret;
  59}
  60
  61static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  62                                                u32 oldval, u32 newval)
  63{
  64        int ret;
  65
  66        asm volatile(
  67                "   sacf 256\n"
  68                "0: cs   %1,%4,0(%5)\n"
  69                "1: la   %0,0\n"
  70                "2: sacf 768\n"
  71                EX_TABLE(0b,2b) EX_TABLE(1b,2b)
  72                : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
  73                : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
  74                : "cc", "memory");
  75        *uval = oldval;
  76        return ret;
  77}
  78
  79#endif /* _ASM_S390_FUTEX_H */
  80