linux/arch/nds32/include/asm/futex.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2// Copyright (C) 2005-2017 Andes Technology Corporation
   3
   4#ifndef __NDS32_FUTEX_H__
   5#define __NDS32_FUTEX_H__
   6
   7#include <linux/futex.h>
   8#include <linux/uaccess.h>
   9#include <asm/errno.h>
  10
  11#define __futex_atomic_ex_table(err_reg)                        \
  12        "       .pushsection __ex_table,\"a\"\n"                \
  13        "       .align  3\n"                                    \
  14        "       .long   1b, 4f\n"                               \
  15        "       .long   2b, 4f\n"                               \
  16        "       .popsection\n"                                  \
  17        "       .pushsection .fixup,\"ax\"\n"                   \
  18        "4:     move    %0, " err_reg "\n"                      \
  19        "       b       3b\n"                                   \
  20        "       .popsection"
  21
  22#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
  23        smp_mb();                                               \
  24        asm volatile(                                   \
  25        "       movi    $ta, #0\n"                              \
  26        "1:     llw     %1, [%2+$ta]\n"                         \
  27        "       " insn "\n"                                     \
  28        "2:     scw     %0, [%2+$ta]\n"                         \
  29        "       beqz    %0, 1b\n"                               \
  30        "       movi    %0, #0\n"                               \
  31        "3:\n"                                                  \
  32        __futex_atomic_ex_table("%4")                           \
  33        : "=&r" (ret), "=&r" (oldval)                           \
  34        : "r" (uaddr), "r" (oparg), "i" (-EFAULT)               \
  35        : "cc", "memory")
  36static inline int
  37futex_atomic_cmpxchg_inatomic(u32 * uval, u32 __user * uaddr,
  38                              u32 oldval, u32 newval)
  39{
  40        int ret = 0;
  41        u32 val, tmp, flags;
  42
  43        if (!access_ok(uaddr, sizeof(u32)))
  44                return -EFAULT;
  45
  46        smp_mb();
  47        asm volatile ("       movi    $ta, #0\n"
  48                      "1:     llw     %1, [%6 + $ta]\n"
  49                      "       sub     %3, %1, %4\n"
  50                      "       cmovz   %2, %5, %3\n"
  51                      "       cmovn   %2, %1, %3\n"
  52                      "2:     scw     %2, [%6 + $ta]\n"
  53                      "       beqz    %2, 1b\n"
  54                      "3:\n                   " __futex_atomic_ex_table("%7")
  55                      :"+&r"(ret), "=&r"(val), "=&r"(tmp), "=&r"(flags)
  56                      :"r"(oldval), "r"(newval), "r"(uaddr), "i"(-EFAULT)
  57                      :"$ta", "memory");
  58        smp_mb();
  59
  60        *uval = val;
  61        return ret;
  62}
  63
  64static inline int
  65arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
  66{
  67        int oldval = 0, ret;
  68
  69        if (!access_ok(uaddr, sizeof(u32)))
  70                return -EFAULT;
  71        switch (op) {
  72        case FUTEX_OP_SET:
  73                __futex_atomic_op("move %0, %3", ret, oldval, tmp, uaddr,
  74                                  oparg);
  75                break;
  76        case FUTEX_OP_ADD:
  77                __futex_atomic_op("add  %0, %1, %3", ret, oldval, tmp, uaddr,
  78                                  oparg);
  79                break;
  80        case FUTEX_OP_OR:
  81                __futex_atomic_op("or   %0, %1, %3", ret, oldval, tmp, uaddr,
  82                                  oparg);
  83                break;
  84        case FUTEX_OP_ANDN:
  85                __futex_atomic_op("and  %0, %1, %3", ret, oldval, tmp, uaddr,
  86                                  ~oparg);
  87                break;
  88        case FUTEX_OP_XOR:
  89                __futex_atomic_op("xor  %0, %1, %3", ret, oldval, tmp, uaddr,
  90                                  oparg);
  91                break;
  92        default:
  93                ret = -ENOSYS;
  94        }
  95
  96        if (!ret)
  97                *oval = oldval;
  98
  99        return ret;
 100}
 101#endif /* __NDS32_FUTEX_H__ */
 102