linux/arch/microblaze/include/asm/futex.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _ASM_MICROBLAZE_FUTEX_H
   3#define _ASM_MICROBLAZE_FUTEX_H
   4
   5#ifdef __KERNEL__
   6
   7#include <linux/futex.h>
   8#include <linux/uaccess.h>
   9#include <asm/errno.h>
  10
  11#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
  12({                                                                      \
  13        __asm__ __volatile__ (                                          \
  14                        "1:     lwx     %0, %2, r0; "                   \
  15                                insn                                    \
  16                        "2:     swx     %1, %2, r0;                     \
  17                                addic   %1, r0, 0;                      \
  18                                bnei    %1, 1b;                         \
  19                        3:                                              \
  20                        .section .fixup,\"ax\";                         \
  21                        4:      brid    3b;                             \
  22                                addik   %1, r0, %3;                     \
  23                        .previous;                                      \
  24                        .section __ex_table,\"a\";                      \
  25                        .word   1b,4b,2b,4b;                            \
  26                        .previous;"                                     \
  27        : "=&r" (oldval), "=&r" (ret)                                   \
  28        : "r" (uaddr), "i" (-EFAULT), "r" (oparg)                       \
  29        );                                                              \
  30})
  31
  32static inline int
  33arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
  34{
  35        int oldval = 0, ret;
  36
  37        if (!access_ok(uaddr, sizeof(u32)))
  38                return -EFAULT;
  39
  40        switch (op) {
  41        case FUTEX_OP_SET:
  42                __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg);
  43                break;
  44        case FUTEX_OP_ADD:
  45                __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg);
  46                break;
  47        case FUTEX_OP_OR:
  48                __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg);
  49                break;
  50        case FUTEX_OP_ANDN:
  51                __futex_atomic_op("andn %1,%0,%4;", ret, oldval, uaddr, oparg);
  52                break;
  53        case FUTEX_OP_XOR:
  54                __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg);
  55                break;
  56        default:
  57                ret = -ENOSYS;
  58        }
  59
  60        if (!ret)
  61                *oval = oldval;
  62
  63        return ret;
  64}
  65
  66static inline int
  67futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  68                              u32 oldval, u32 newval)
  69{
  70        int ret = 0, cmp;
  71        u32 prev;
  72
  73        if (!access_ok(uaddr, sizeof(u32)))
  74                return -EFAULT;
  75
  76        __asm__ __volatile__ ("1:       lwx     %1, %3, r0;             \
  77                                        cmp     %2, %1, %4;             \
  78                                        bnei    %2, 3f;                 \
  79                                2:      swx     %5, %3, r0;             \
  80                                        addic   %2, r0, 0;              \
  81                                        bnei    %2, 1b;                 \
  82                                3:                                      \
  83                                .section .fixup,\"ax\";                 \
  84                                4:      brid    3b;                     \
  85                                        addik   %0, r0, %6;             \
  86                                .previous;                              \
  87                                .section __ex_table,\"a\";              \
  88                                .word   1b,4b,2b,4b;                    \
  89                                .previous;"                             \
  90                : "+r" (ret), "=&r" (prev), "=&r"(cmp)  \
  91                : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
  92
  93        *uval = prev;
  94        return ret;
  95}
  96
  97#endif /* __KERNEL__ */
  98
  99#endif
 100