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        mm_segment_t old_fs;
  30
  31        old_fs = enable_sacf_uaccess();
  32        pagefault_disable();
  33        switch (op) {
  34        case FUTEX_OP_SET:
  35                __futex_atomic_op("lr %2,%5\n",
  36                                  ret, oldval, newval, uaddr, oparg);
  37                break;
  38        case FUTEX_OP_ADD:
  39                __futex_atomic_op("lr %2,%1\nar %2,%5\n",
  40                                  ret, oldval, newval, uaddr, oparg);
  41                break;
  42        case FUTEX_OP_OR:
  43                __futex_atomic_op("lr %2,%1\nor %2,%5\n",
  44                                  ret, oldval, newval, uaddr, oparg);
  45                break;
  46        case FUTEX_OP_ANDN:
  47                __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
  48                                  ret, oldval, newval, uaddr, oparg);
  49                break;
  50        case FUTEX_OP_XOR:
  51                __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
  52                                  ret, oldval, newval, uaddr, oparg);
  53                break;
  54        default:
  55                ret = -ENOSYS;
  56        }
  57        pagefault_enable();
  58        disable_sacf_uaccess(old_fs);
  59
  60        if (!ret)
  61                *oval = oldval;
  62
  63        return ret;
  64}
  65
  66static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  67                                                u32 oldval, u32 newval)
  68{
  69        mm_segment_t old_fs;
  70        int ret;
  71
  72        old_fs = enable_sacf_uaccess();
  73        asm volatile(
  74                "   sacf 256\n"
  75                "0: cs   %1,%4,0(%5)\n"
  76                "1: la   %0,0\n"
  77                "2: sacf 768\n"
  78                EX_TABLE(0b,2b) EX_TABLE(1b,2b)
  79                : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
  80                : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
  81                : "cc", "memory");
  82        disable_sacf_uaccess(old_fs);
  83        *uval = oldval;
  84        return ret;
  85}
  86
  87#endif /* _ASM_S390_FUTEX_H */
  88