1fd3db0a6SMichal Simek #ifndef _ASM_MICROBLAZE_FUTEX_H 2fd3db0a6SMichal Simek #define _ASM_MICROBLAZE_FUTEX_H 3fd3db0a6SMichal Simek 4fd3db0a6SMichal Simek #ifdef __KERNEL__ 5fd3db0a6SMichal Simek 6fd3db0a6SMichal Simek #include <linux/futex.h> 7fd3db0a6SMichal Simek #include <linux/uaccess.h> 8fd3db0a6SMichal Simek #include <asm/errno.h> 9fd3db0a6SMichal Simek 10fd3db0a6SMichal Simek #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ 11fd3db0a6SMichal Simek ({ \ 12fd3db0a6SMichal Simek __asm__ __volatile__ ( \ 13fd3db0a6SMichal Simek "1: lwx %0, %2, r0; " \ 14fd3db0a6SMichal Simek insn \ 15fd3db0a6SMichal Simek "2: swx %1, %2, r0; \ 16fd3db0a6SMichal Simek addic %1, r0, 0; \ 17fd3db0a6SMichal Simek bnei %1, 1b; \ 18fd3db0a6SMichal Simek 3: \ 19fd3db0a6SMichal Simek .section .fixup,\"ax\"; \ 20fd3db0a6SMichal Simek 4: brid 3b; \ 21fd3db0a6SMichal Simek addik %1, r0, %3; \ 22fd3db0a6SMichal Simek .previous; \ 23fd3db0a6SMichal Simek .section __ex_table,\"a\"; \ 24fd3db0a6SMichal Simek .word 1b,4b,2b,4b; \ 25fd3db0a6SMichal Simek .previous;" \ 26fd3db0a6SMichal Simek : "=&r" (oldval), "=&r" (ret) \ 27fd3db0a6SMichal Simek : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ 28fd3db0a6SMichal Simek ); \ 29fd3db0a6SMichal Simek }) 30fd3db0a6SMichal Simek 31fd3db0a6SMichal Simek static inline int 32fd3db0a6SMichal Simek futex_atomic_op_inuser(int encoded_op, int __user *uaddr) 33fd3db0a6SMichal Simek { 34fd3db0a6SMichal Simek int op = (encoded_op >> 28) & 7; 35fd3db0a6SMichal Simek int cmp = (encoded_op >> 24) & 15; 36fd3db0a6SMichal Simek int oparg = (encoded_op << 8) >> 20; 37fd3db0a6SMichal Simek int cmparg = (encoded_op << 20) >> 20; 38fd3db0a6SMichal Simek int oldval = 0, ret; 39fd3db0a6SMichal Simek if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 40fd3db0a6SMichal Simek oparg = 1 << oparg; 41fd3db0a6SMichal Simek 42fd3db0a6SMichal Simek if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 43fd3db0a6SMichal Simek return -EFAULT; 44fd3db0a6SMichal Simek 45fd3db0a6SMichal Simek pagefault_disable(); 46fd3db0a6SMichal Simek 47fd3db0a6SMichal Simek switch (op) { 48fd3db0a6SMichal Simek case FUTEX_OP_SET: 49fd3db0a6SMichal Simek __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg); 50fd3db0a6SMichal Simek break; 51fd3db0a6SMichal Simek case FUTEX_OP_ADD: 52fd3db0a6SMichal Simek __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg); 53fd3db0a6SMichal Simek break; 54fd3db0a6SMichal Simek case FUTEX_OP_OR: 55fd3db0a6SMichal Simek __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg); 56fd3db0a6SMichal Simek break; 57fd3db0a6SMichal Simek case FUTEX_OP_ANDN: 58fd3db0a6SMichal Simek __futex_atomic_op("and %1,%0,%4;", ret, oldval, uaddr, oparg); 59fd3db0a6SMichal Simek break; 60fd3db0a6SMichal Simek case FUTEX_OP_XOR: 61fd3db0a6SMichal Simek __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg); 62fd3db0a6SMichal Simek break; 63fd3db0a6SMichal Simek default: 64fd3db0a6SMichal Simek ret = -ENOSYS; 65fd3db0a6SMichal Simek } 66fd3db0a6SMichal Simek 67fd3db0a6SMichal Simek pagefault_enable(); 68fd3db0a6SMichal Simek 69fd3db0a6SMichal Simek if (!ret) { 70fd3db0a6SMichal Simek switch (cmp) { 71fd3db0a6SMichal Simek case FUTEX_OP_CMP_EQ: 72fd3db0a6SMichal Simek ret = (oldval == cmparg); 73fd3db0a6SMichal Simek break; 74fd3db0a6SMichal Simek case FUTEX_OP_CMP_NE: 75fd3db0a6SMichal Simek ret = (oldval != cmparg); 76fd3db0a6SMichal Simek break; 77fd3db0a6SMichal Simek case FUTEX_OP_CMP_LT: 78fd3db0a6SMichal Simek ret = (oldval < cmparg); 79fd3db0a6SMichal Simek break; 80fd3db0a6SMichal Simek case FUTEX_OP_CMP_GE: 81fd3db0a6SMichal Simek ret = (oldval >= cmparg); 82fd3db0a6SMichal Simek break; 83fd3db0a6SMichal Simek case FUTEX_OP_CMP_LE: 84fd3db0a6SMichal Simek ret = (oldval <= cmparg); 85fd3db0a6SMichal Simek break; 86fd3db0a6SMichal Simek case FUTEX_OP_CMP_GT: 87fd3db0a6SMichal Simek ret = (oldval > cmparg); 88fd3db0a6SMichal Simek break; 89fd3db0a6SMichal Simek default: 90fd3db0a6SMichal Simek ret = -ENOSYS; 91fd3db0a6SMichal Simek } 92fd3db0a6SMichal Simek } 93fd3db0a6SMichal Simek return ret; 94fd3db0a6SMichal Simek } 95fd3db0a6SMichal Simek 96fd3db0a6SMichal Simek static inline int 97fd3db0a6SMichal Simek futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) 98fd3db0a6SMichal Simek { 99fd3db0a6SMichal Simek int prev, cmp; 100fd3db0a6SMichal Simek 101fd3db0a6SMichal Simek if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) 102fd3db0a6SMichal Simek return -EFAULT; 103fd3db0a6SMichal Simek 104fd3db0a6SMichal Simek __asm__ __volatile__ ("1: lwx %0, %2, r0; \ 105fd3db0a6SMichal Simek cmp %1, %0, %3; \ 106fd3db0a6SMichal Simek beqi %1, 3f; \ 107fd3db0a6SMichal Simek 2: swx %4, %2, r0; \ 108fd3db0a6SMichal Simek addic %1, r0, 0; \ 109fd3db0a6SMichal Simek bnei %1, 1b; \ 110fd3db0a6SMichal Simek 3: \ 111fd3db0a6SMichal Simek .section .fixup,\"ax\"; \ 112fd3db0a6SMichal Simek 4: brid 3b; \ 113fd3db0a6SMichal Simek addik %0, r0, %5; \ 114fd3db0a6SMichal Simek .previous; \ 115fd3db0a6SMichal Simek .section __ex_table,\"a\"; \ 116fd3db0a6SMichal Simek .word 1b,4b,2b,4b; \ 117fd3db0a6SMichal Simek .previous;" \ 118fd3db0a6SMichal Simek : "=&r" (prev), "=&r"(cmp) \ 119fd3db0a6SMichal Simek : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)); 120fd3db0a6SMichal Simek 121fd3db0a6SMichal Simek return prev; 122fd3db0a6SMichal Simek } 123fd3db0a6SMichal Simek 124fd3db0a6SMichal Simek #endif /* __KERNEL__ */ 125fd3db0a6SMichal Simek 126fd3db0a6SMichal Simek #endif 127