futex.h revision 8cf662ed3ef190fddc186bb5b1cd75eb3880d5a9
1fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#ifndef _ASM_MICROBLAZE_FUTEX_H 2fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#define _ASM_MICROBLAZE_FUTEX_H 3fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 4fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#ifdef __KERNEL__ 5fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 6fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#include <linux/futex.h> 7fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#include <linux/uaccess.h> 8fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#include <asm/errno.h> 9fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 10fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ 11fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek({ \ 12fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek __asm__ __volatile__ ( \ 13fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek "1: lwx %0, %2, r0; " \ 14fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek insn \ 15fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek "2: swx %1, %2, r0; \ 16fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek addic %1, r0, 0; \ 17fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek bnei %1, 1b; \ 18fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 3: \ 19fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .section .fixup,\"ax\"; \ 20fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 4: brid 3b; \ 21fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek addik %1, r0, %3; \ 22fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .previous; \ 23fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .section __ex_table,\"a\"; \ 24fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .word 1b,4b,2b,4b; \ 25fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .previous;" \ 26fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek : "=&r" (oldval), "=&r" (ret) \ 278cf662ed3ef190fddc186bb5b1cd75eb3880d5a9Michal Simek : "r" (uaddr), "i" (-EFAULT), "r" (oparg) \ 28fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ); \ 29fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek}) 30fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 31fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simekstatic inline int 328d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinassefutex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) 33fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek{ 34fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek int op = (encoded_op >> 28) & 7; 35fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek int cmp = (encoded_op >> 24) & 15; 36fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek int oparg = (encoded_op << 8) >> 20; 37fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek int cmparg = (encoded_op << 20) >> 20; 38fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek int oldval = 0, ret; 39fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 40fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek oparg = 1 << oparg; 41fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 428d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 43fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek return -EFAULT; 44fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 45fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek pagefault_disable(); 46fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 47fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek switch (op) { 48fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_SET: 49fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg); 50fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 51fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_ADD: 52fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg); 53fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 54fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_OR: 55fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg); 56fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 57fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_ANDN: 584bb30baa6d5e7660c06e3b50d8a8a76d402c7170Michal Simek __futex_atomic_op("andn %1,%0,%4;", ret, oldval, uaddr, oparg); 59fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 60fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_XOR: 61fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg); 62fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 63fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek default: 64fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = -ENOSYS; 65fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek } 66fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 67fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek pagefault_enable(); 68fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 69fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek if (!ret) { 70fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek switch (cmp) { 71fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_CMP_EQ: 72fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = (oldval == cmparg); 73fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 74fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_CMP_NE: 75fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = (oldval != cmparg); 76fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 77fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_CMP_LT: 78fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = (oldval < cmparg); 79fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 80fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_CMP_GE: 81fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = (oldval >= cmparg); 82fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 83fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_CMP_LE: 84fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = (oldval <= cmparg); 85fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 86fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek case FUTEX_OP_CMP_GT: 87fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = (oldval > cmparg); 88fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek break; 89fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek default: 90fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek ret = -ENOSYS; 91fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek } 92fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek } 93fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek return ret; 94fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek} 95fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 96fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simekstatic inline int 978d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinassefutex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 988d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse u32 oldval, u32 newval) 99fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek{ 1008d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse int ret = 0, cmp; 1018d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse u32 prev; 102fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 1038d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 104fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek return -EFAULT; 105fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 10637a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse __asm__ __volatile__ ("1: lwx %1, %3, r0; \ 10737a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse cmp %2, %1, %4; \ 10837a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse beqi %2, 3f; \ 10937a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse 2: swx %5, %3, r0; \ 11037a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse addic %2, r0, 0; \ 11137a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse bnei %2, 1b; \ 112fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 3: \ 113fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .section .fixup,\"ax\"; \ 114fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 4: brid 3b; \ 11537a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse addik %0, r0, %6; \ 116fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .previous; \ 117fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .section __ex_table,\"a\"; \ 118fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .word 1b,4b,2b,4b; \ 119fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek .previous;" \ 12037a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse : "+r" (ret), "=&r" (prev), "=&r"(cmp) \ 121fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)); 122fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 12337a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse *uval = prev; 12437a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse return ret; 125fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek} 126fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 127fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#endif /* __KERNEL__ */ 128fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek 129fd3db0a675a35f28b08e47e8ed1a7a7f158467c2Michal Simek#endif 130