1 #ifndef _ASM_HEXAGON_FUTEX_H 2 #define _ASM_HEXAGON_FUTEX_H 3 4 #ifdef __KERNEL__ 5 6 #include <linux/futex.h> 7 #include <linux/uaccess.h> 8 #include <asm/errno.h> 9 10 /* XXX TODO-- need to add sync barriers! */ 11 12 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ 13 __asm__ __volatile( \ 14 "1: %0 = memw_locked(%3);\n" \ 15 /* For example: %1 = %4 */ \ 16 insn \ 17 "2: memw_locked(%3,p2) = %1;\n" \ 18 " if !p2 jump 1b;\n" \ 19 " %1 = #0;\n" \ 20 "3:\n" \ 21 ".section .fixup,\"ax\"\n" \ 22 "4: %1 = #%5;\n" \ 23 " jump 3b\n" \ 24 ".previous\n" \ 25 ".section __ex_table,\"a\"\n" \ 26 ".long 1b,4b,2b,4b\n" \ 27 ".previous\n" \ 28 : "=&r" (oldval), "=&r" (ret), "+m" (*uaddr) \ 29 : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ 30 : "p2", "memory") 31 32 33 static inline int 34 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) 35 { 36 int oldval = 0, ret; 37 38 pagefault_disable(); 39 40 switch (op) { 41 case FUTEX_OP_SET: 42 __futex_atomic_op("%1 = %4\n", ret, oldval, uaddr, oparg); 43 break; 44 case FUTEX_OP_ADD: 45 __futex_atomic_op("%1 = add(%0,%4)\n", ret, oldval, uaddr, 46 oparg); 47 break; 48 case FUTEX_OP_OR: 49 __futex_atomic_op("%1 = or(%0,%4)\n", ret, oldval, uaddr, 50 oparg); 51 break; 52 case FUTEX_OP_ANDN: 53 __futex_atomic_op("%1 = not(%4); %1 = and(%0,%1)\n", ret, 54 oldval, uaddr, oparg); 55 break; 56 case FUTEX_OP_XOR: 57 __futex_atomic_op("%1 = xor(%0,%4)\n", ret, oldval, uaddr, 58 oparg); 59 break; 60 default: 61 ret = -ENOSYS; 62 } 63 64 pagefault_enable(); 65 66 if (!ret) 67 *oval = oldval; 68 69 return ret; 70 } 71 72 static inline int 73 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, 74 u32 newval) 75 { 76 int prev; 77 int ret; 78 79 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 80 return -EFAULT; 81 82 __asm__ __volatile__ ( 83 "1: %1 = memw_locked(%3)\n" 84 " {\n" 85 " p2 = cmp.eq(%1,%4)\n" 86 " if !p2.new jump:NT 3f\n" 87 " }\n" 88 "2: memw_locked(%3,p2) = %5\n" 89 " if !p2 jump 1b\n" 90 "3:\n" 91 ".section .fixup,\"ax\"\n" 92 "4: %0 = #%6\n" 93 " jump 3b\n" 94 ".previous\n" 95 ".section __ex_table,\"a\"\n" 96 ".long 1b,4b,2b,4b\n" 97 ".previous\n" 98 : "+r" (ret), "=&r" (prev), "+m" (*uaddr) 99 : "r" (uaddr), "r" (oldval), "r" (newval), "i"(-EFAULT) 100 : "p2", "memory"); 101 102 *uval = prev; 103 return ret; 104 } 105 106 #endif /* __KERNEL__ */ 107 #endif /* _ASM_HEXAGON_FUTEX_H */ 108