root/arch/riscv/include/asm/futex.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. arch_futex_atomic_op_inuser
  2. futex_atomic_cmpxchg_inatomic

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /*
   3  * Copyright (c) 2006  Ralf Baechle (ralf@linux-mips.org)
   4  * Copyright (c) 2018  Jim Wilson (jimw@sifive.com)
   5  */
   6 
   7 #ifndef _ASM_FUTEX_H
   8 #define _ASM_FUTEX_H
   9 
  10 #include <linux/futex.h>
  11 #include <linux/uaccess.h>
  12 #include <linux/errno.h>
  13 #include <asm/asm.h>
  14 
  15 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)      \
  16 {                                                               \
  17         uintptr_t tmp;                                          \
  18         __enable_user_access();                                 \
  19         __asm__ __volatile__ (                                  \
  20         "1:     " insn "                                \n"     \
  21         "2:                                             \n"     \
  22         "       .section .fixup,\"ax\"                  \n"     \
  23         "       .balign 4                               \n"     \
  24         "3:     li %[r],%[e]                            \n"     \
  25         "       jump 2b,%[t]                            \n"     \
  26         "       .previous                               \n"     \
  27         "       .section __ex_table,\"a\"               \n"     \
  28         "       .balign " RISCV_SZPTR "                 \n"     \
  29         "       " RISCV_PTR " 1b, 3b                    \n"     \
  30         "       .previous                               \n"     \
  31         : [r] "+r" (ret), [ov] "=&r" (oldval),                  \
  32           [u] "+m" (*uaddr), [t] "=&r" (tmp)                    \
  33         : [op] "Jr" (oparg), [e] "i" (-EFAULT)                  \
  34         : "memory");                                            \
  35         __disable_user_access();                                \
  36 }
  37 
  38 static inline int
  39 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
  40 {
  41         int oldval = 0, ret = 0;
  42 
  43         pagefault_disable();
  44 
  45         switch (op) {
  46         case FUTEX_OP_SET:
  47                 __futex_atomic_op("amoswap.w.aqrl %[ov],%z[op],%[u]",
  48                                   ret, oldval, uaddr, oparg);
  49                 break;
  50         case FUTEX_OP_ADD:
  51                 __futex_atomic_op("amoadd.w.aqrl %[ov],%z[op],%[u]",
  52                                   ret, oldval, uaddr, oparg);
  53                 break;
  54         case FUTEX_OP_OR:
  55                 __futex_atomic_op("amoor.w.aqrl %[ov],%z[op],%[u]",
  56                                   ret, oldval, uaddr, oparg);
  57                 break;
  58         case FUTEX_OP_ANDN:
  59                 __futex_atomic_op("amoand.w.aqrl %[ov],%z[op],%[u]",
  60                                   ret, oldval, uaddr, ~oparg);
  61                 break;
  62         case FUTEX_OP_XOR:
  63                 __futex_atomic_op("amoxor.w.aqrl %[ov],%z[op],%[u]",
  64                                   ret, oldval, uaddr, oparg);
  65                 break;
  66         default:
  67                 ret = -ENOSYS;
  68         }
  69 
  70         pagefault_enable();
  71 
  72         if (!ret)
  73                 *oval = oldval;
  74 
  75         return ret;
  76 }
  77 
  78 static inline int
  79 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  80                               u32 oldval, u32 newval)
  81 {
  82         int ret = 0;
  83         u32 val;
  84         uintptr_t tmp;
  85 
  86         if (!access_ok(uaddr, sizeof(u32)))
  87                 return -EFAULT;
  88 
  89         __enable_user_access();
  90         __asm__ __volatile__ (
  91         "1:     lr.w.aqrl %[v],%[u]                     \n"
  92         "       bne %[v],%z[ov],3f                      \n"
  93         "2:     sc.w.aqrl %[t],%z[nv],%[u]              \n"
  94         "       bnez %[t],1b                            \n"
  95         "3:                                             \n"
  96         "       .section .fixup,\"ax\"                  \n"
  97         "       .balign 4                               \n"
  98         "4:     li %[r],%[e]                            \n"
  99         "       jump 3b,%[t]                            \n"
 100         "       .previous                               \n"
 101         "       .section __ex_table,\"a\"               \n"
 102         "       .balign " RISCV_SZPTR "                 \n"
 103         "       " RISCV_PTR " 1b, 4b                    \n"
 104         "       " RISCV_PTR " 2b, 4b                    \n"
 105         "       .previous                               \n"
 106         : [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr), [t] "=&r" (tmp)
 107         : [ov] "Jr" (oldval), [nv] "Jr" (newval), [e] "i" (-EFAULT)
 108         : "memory");
 109         __disable_user_access();
 110 
 111         *uval = val;
 112         return ret;
 113 }
 114 
 115 #endif /* _ASM_FUTEX_H */

/* [<][>][^][v][top][bottom][index][help] */