1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <linux/linkage.h>
4 #include <asm/export.h>
5 #include <asm/percpu.h>
6 #include <asm/processor-flags.h>
7 
8 .text
9 
10 #ifndef CONFIG_X86_CMPXCHG64
11 
12 /*
13  * Emulate 'cmpxchg8b (%esi)' on UP
14  *
15  * Inputs:
16  * %esi : memory location to compare
17  * %eax : low 32 bits of old value
18  * %edx : high 32 bits of old value
19  * %ebx : low 32 bits of new value
20  * %ecx : high 32 bits of new value
21  */
22 SYM_FUNC_START(cmpxchg8b_emu)
23 
24 	pushfl
25 	cli
26 
27 	cmpl	0(%esi), %eax
28 	jne	.Lnot_same
29 	cmpl	4(%esi), %edx
30 	jne	.Lnot_same
31 
32 	movl	%ebx, 0(%esi)
33 	movl	%ecx, 4(%esi)
34 
35 	orl	$X86_EFLAGS_ZF, (%esp)
36 
37 	popfl
38 	RET
39 
40 .Lnot_same:
41 	movl	0(%esi), %eax
42 	movl	4(%esi), %edx
43 
44 	andl	$(~X86_EFLAGS_ZF), (%esp)
45 
46 	popfl
47 	RET
48 
49 SYM_FUNC_END(cmpxchg8b_emu)
50 EXPORT_SYMBOL(cmpxchg8b_emu)
51 
52 #endif
53 
54 #ifndef CONFIG_UML
55 
56 SYM_FUNC_START(this_cpu_cmpxchg8b_emu)
57 
58 	pushfl
59 	cli
60 
61 	cmpl	PER_CPU_VAR(0(%esi)), %eax
62 	jne	.Lnot_same2
63 	cmpl	PER_CPU_VAR(4(%esi)), %edx
64 	jne	.Lnot_same2
65 
66 	movl	%ebx, PER_CPU_VAR(0(%esi))
67 	movl	%ecx, PER_CPU_VAR(4(%esi))
68 
69 	orl	$X86_EFLAGS_ZF, (%esp)
70 
71 	popfl
72 	RET
73 
74 .Lnot_same2:
75 	movl	PER_CPU_VAR(0(%esi)), %eax
76 	movl	PER_CPU_VAR(4(%esi)), %edx
77 
78 	andl	$(~X86_EFLAGS_ZF), (%esp)
79 
80 	popfl
81 	RET
82 
83 SYM_FUNC_END(this_cpu_cmpxchg8b_emu)
84 
85 #endif
86