linux/arch/xtensa/include/asm/futex.h
<<
>>
Prefs
   1/*
   2 * Atomic futex routines
   3 *
   4 * Based on the PowerPC implementataion
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 * Copyright (C) 2013 TangoTec Ltd.
  11 *
  12 * Baruch Siach <baruch@tkos.co.il>
  13 */
  14
  15#ifndef _ASM_XTENSA_FUTEX_H
  16#define _ASM_XTENSA_FUTEX_H
  17
  18#ifdef __KERNEL__
  19
  20#include <linux/futex.h>
  21#include <linux/uaccess.h>
  22#include <linux/errno.h>
  23
  24#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
  25        __asm__ __volatile(                             \
  26        "1:     l32i    %0, %2, 0\n"                    \
  27                insn "\n"                               \
  28        "       wsr     %0, scompare1\n"                \
  29        "2:     s32c1i  %1, %2, 0\n"                    \
  30        "       bne     %1, %0, 1b\n"                   \
  31        "       movi    %1, 0\n"                        \
  32        "3:\n"                                          \
  33        "       .section .fixup,\"ax\"\n"               \
  34        "       .align 4\n"                             \
  35        "4:     .long   3b\n"                           \
  36        "5:     l32r    %0, 4b\n"                       \
  37        "       movi    %1, %3\n"                       \
  38        "       jx      %0\n"                           \
  39        "       .previous\n"                            \
  40        "       .section __ex_table,\"a\"\n"            \
  41        "       .long 1b,5b,2b,5b\n"                    \
  42        "       .previous\n"                            \
  43        : "=&r" (oldval), "=&r" (ret)                   \
  44        : "r" (uaddr), "I" (-EFAULT), "r" (oparg)       \
  45        : "memory")
  46
  47static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
  48                u32 __user *uaddr)
  49{
  50        int oldval = 0, ret;
  51
  52#if !XCHAL_HAVE_S32C1I
  53        return -ENOSYS;
  54#endif
  55
  56        pagefault_disable();
  57
  58        switch (op) {
  59        case FUTEX_OP_SET:
  60                __futex_atomic_op("mov %1, %4", ret, oldval, uaddr, oparg);
  61                break;
  62        case FUTEX_OP_ADD:
  63                __futex_atomic_op("add %1, %0, %4", ret, oldval, uaddr,
  64                                oparg);
  65                break;
  66        case FUTEX_OP_OR:
  67                __futex_atomic_op("or %1, %0, %4", ret, oldval, uaddr,
  68                                oparg);
  69                break;
  70        case FUTEX_OP_ANDN:
  71                __futex_atomic_op("and %1, %0, %4", ret, oldval, uaddr,
  72                                ~oparg);
  73                break;
  74        case FUTEX_OP_XOR:
  75                __futex_atomic_op("xor %1, %0, %4", ret, oldval, uaddr,
  76                                oparg);
  77                break;
  78        default:
  79                ret = -ENOSYS;
  80        }
  81
  82        pagefault_enable();
  83
  84        if (!ret)
  85                *oval = oldval;
  86
  87        return ret;
  88}
  89
  90static inline int
  91futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  92                              u32 oldval, u32 newval)
  93{
  94        int ret = 0;
  95
  96        if (!access_ok(uaddr, sizeof(u32)))
  97                return -EFAULT;
  98
  99#if !XCHAL_HAVE_S32C1I
 100        return -ENOSYS;
 101#endif
 102
 103        __asm__ __volatile__ (
 104        "       # futex_atomic_cmpxchg_inatomic\n"
 105        "       wsr     %5, scompare1\n"
 106        "1:     s32c1i  %1, %4, 0\n"
 107        "       s32i    %1, %6, 0\n"
 108        "2:\n"
 109        "       .section .fixup,\"ax\"\n"
 110        "       .align 4\n"
 111        "3:     .long   2b\n"
 112        "4:     l32r    %1, 3b\n"
 113        "       movi    %0, %7\n"
 114        "       jx      %1\n"
 115        "       .previous\n"
 116        "       .section __ex_table,\"a\"\n"
 117        "       .long 1b,4b\n"
 118        "       .previous\n"
 119        : "+r" (ret), "+r" (newval), "+m" (*uaddr), "+m" (*uval)
 120        : "r" (uaddr), "r" (oldval), "r" (uval), "I" (-EFAULT)
 121        : "memory");
 122
 123        return ret;
 124}
 125
 126#endif /* __KERNEL__ */
 127#endif /* _ASM_XTENSA_FUTEX_H */
 128