| /* SPDX-License-Identifier: GPL-2.0 */ | 
 | #ifndef _ASM_X86_FUTEX_H | 
 | #define _ASM_X86_FUTEX_H | 
 |  | 
 | #ifdef __KERNEL__ | 
 |  | 
 | #include <linux/futex.h> | 
 | #include <linux/uaccess.h> | 
 |  | 
 | #include <asm/asm.h> | 
 | #include <asm/errno.h> | 
 | #include <asm/processor.h> | 
 | #include <asm/smap.h> | 
 |  | 
 | #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)	\ | 
 | 	asm volatile("\t" ASM_STAC "\n"				\ | 
 | 		     "1:\t" insn "\n"				\ | 
 | 		     "2:\t" ASM_CLAC "\n"			\ | 
 | 		     "\t.section .fixup,\"ax\"\n"		\ | 
 | 		     "3:\tmov\t%3, %1\n"			\ | 
 | 		     "\tjmp\t2b\n"				\ | 
 | 		     "\t.previous\n"				\ | 
 | 		     _ASM_EXTABLE_UA(1b, 3b)			\ | 
 | 		     : "=r" (oldval), "=r" (ret), "+m" (*uaddr)	\ | 
 | 		     : "i" (-EFAULT), "0" (oparg), "1" (0)) | 
 |  | 
 | #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg)	\ | 
 | 	asm volatile("\t" ASM_STAC "\n"				\ | 
 | 		     "1:\tmovl	%2, %0\n"			\ | 
 | 		     "\tmovl\t%0, %3\n"				\ | 
 | 		     "\t" insn "\n"				\ | 
 | 		     "2:\t" LOCK_PREFIX "cmpxchgl %3, %2\n"	\ | 
 | 		     "\tjnz\t1b\n"				\ | 
 | 		     "3:\t" ASM_CLAC "\n"			\ | 
 | 		     "\t.section .fixup,\"ax\"\n"		\ | 
 | 		     "4:\tmov\t%5, %1\n"			\ | 
 | 		     "\tjmp\t3b\n"				\ | 
 | 		     "\t.previous\n"				\ | 
 | 		     _ASM_EXTABLE_UA(1b, 4b)			\ | 
 | 		     _ASM_EXTABLE_UA(2b, 4b)			\ | 
 | 		     : "=&a" (oldval), "=&r" (ret),		\ | 
 | 		       "+m" (*uaddr), "=&r" (tem)		\ | 
 | 		     : "r" (oparg), "i" (-EFAULT), "1" (0)) | 
 |  | 
 | static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, | 
 | 		u32 __user *uaddr) | 
 | { | 
 | 	int oldval = 0, ret, tem; | 
 |  | 
 | 	pagefault_disable(); | 
 |  | 
 | 	switch (op) { | 
 | 	case FUTEX_OP_SET: | 
 | 		__futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); | 
 | 		break; | 
 | 	case FUTEX_OP_ADD: | 
 | 		__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval, | 
 | 				   uaddr, oparg); | 
 | 		break; | 
 | 	case FUTEX_OP_OR: | 
 | 		__futex_atomic_op2("orl %4, %3", ret, oldval, uaddr, oparg); | 
 | 		break; | 
 | 	case FUTEX_OP_ANDN: | 
 | 		__futex_atomic_op2("andl %4, %3", ret, oldval, uaddr, ~oparg); | 
 | 		break; | 
 | 	case FUTEX_OP_XOR: | 
 | 		__futex_atomic_op2("xorl %4, %3", ret, oldval, uaddr, oparg); | 
 | 		break; | 
 | 	default: | 
 | 		ret = -ENOSYS; | 
 | 	} | 
 |  | 
 | 	pagefault_enable(); | 
 |  | 
 | 	if (!ret) | 
 | 		*oval = oldval; | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | 
 | 						u32 oldval, u32 newval) | 
 | { | 
 | 	return user_atomic_cmpxchg_inatomic(uval, uaddr, oldval, newval); | 
 | } | 
 |  | 
 | #endif | 
 | #endif /* _ASM_X86_FUTEX_H */ |