177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#ifndef _ASM_ALPHA_FUTEX_H 277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#define _ASM_ALPHA_FUTEX_H 34732efbeb997189d9f9b04708dc26bf8613ed721Jakub Jelinek 477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#ifdef __KERNEL__ 54732efbeb997189d9f9b04708dc26bf8613ed721Jakub Jelinek 677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <linux/futex.h> 777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <linux/uaccess.h> 877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <asm/errno.h> 977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#include <asm/barrier.h> 1077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 1177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ 1277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __asm__ __volatile__( \ 1377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __ASM_SMP_MB \ 1477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky "1: ldl_l %0,0(%2)\n" \ 1577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky insn \ 1677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky "2: stl_c %1,0(%2)\n" \ 1777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " beq %1,4f\n" \ 1877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " mov $31,%1\n" \ 1977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky "3: .subsection 2\n" \ 2077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky "4: br 1b\n" \ 2177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .previous\n" \ 2277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .section __ex_table,\"a\"\n" \ 2377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .long 1b-.\n" \ 2477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " lda $31,3b-1b(%1)\n" \ 2577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .long 2b-.\n" \ 2677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " lda $31,3b-2b(%1)\n" \ 2777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .previous\n" \ 2877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky : "=&r" (oldval), "=&r"(ret) \ 2977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky : "r" (uaddr), "r"(oparg) \ 3077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky : "memory") 3177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 328d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinassestatic inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) 3377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky{ 3477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky int op = (encoded_op >> 28) & 7; 3577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky int cmp = (encoded_op >> 24) & 15; 3677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky int oparg = (encoded_op << 8) >> 20; 3777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky int cmparg = (encoded_op << 20) >> 20; 3877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky int oldval = 0, ret; 3977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 4077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky oparg = 1 << oparg; 4177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 428d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 4377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky return -EFAULT; 4477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 4577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky pagefault_disable(); 4677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 4777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky switch (op) { 4877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_SET: 4977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg); 5077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky break; 5177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_ADD: 5277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg); 5377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky break; 5477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_OR: 5577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg); 5677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky break; 5777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_ANDN: 5877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg); 5977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky break; 6077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_XOR: 6177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg); 6277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky break; 6377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky default: 6477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky ret = -ENOSYS; 6577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky } 6677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 6777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky pagefault_enable(); 6877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 6977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky if (!ret) { 7077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky switch (cmp) { 7177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; 7277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; 7377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; 7477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; 7577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; 7677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; 7777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky default: ret = -ENOSYS; 7877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky } 7977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky } 8077b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky return ret; 8177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky} 8277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 8377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshayskystatic inline int 848d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinassefutex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, 858d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse u32 oldval, u32 newval) 8677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky{ 878d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse int ret = 0, cmp; 888d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse u32 prev; 8977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 908d7718aa082aaf30a0b4989e1f04858952f941bcMichel Lespinasse if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) 9177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky return -EFAULT; 9277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 9377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __asm__ __volatile__ ( 9477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky __ASM_SMP_MB 9537a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse "1: ldl_l %1,0(%3)\n" 9637a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse " cmpeq %1,%4,%2\n" 9737a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse " beq %2,3f\n" 9837a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse " mov %5,%2\n" 9937a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse "2: stl_c %2,0(%3)\n" 10037a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse " beq %2,4f\n" 10177b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky "3: .subsection 2\n" 10277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky "4: br 1b\n" 10377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .previous\n" 10477b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .section __ex_table,\"a\"\n" 10577b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .long 1b-.\n" 10677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " lda $31,3b-1b(%0)\n" 10777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .long 2b-.\n" 10877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " lda $31,3b-2b(%0)\n" 10977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky " .previous\n" 11037a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse : "+r"(ret), "=&r"(prev), "=&r"(cmp) 11162aca403657fe30e5235c5331e9871e676d9ea0aAndrew Morton : "r"(uaddr), "r"((long)(int)oldval), "r"(newval) 11277b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky : "memory"); 11377b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 11437a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse *uval = prev; 11537a9d912b24f96a0591773e6e6c3642991ae5a70Michel Lespinasse return ret; 11677b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky} 11777b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky 11877b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#endif /* __KERNEL__ */ 11977b4cf5cb0c9d6010a18030a0e0a8d2aaf6b43ecIvan Kokshaysky#endif /* _ASM_ALPHA_FUTEX_H */ 120