1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | |
3 | #include <linux/export.h> |
4 | #include <linux/linkage.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 (%esi), %eax |
28 | jne .Lnot_same |
29 | cmpl 4(%esi), %edx |
30 | jne .Lnot_same |
31 | |
32 | movl %ebx, (%esi) |
33 | movl %ecx, 4(%esi) |
34 | |
35 | orl $X86_EFLAGS_ZF, (%esp) |
36 | |
37 | popfl |
38 | RET |
39 | |
40 | .Lnot_same: |
41 | movl (%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 | /* |
57 | * Emulate 'cmpxchg8b %fs:(%rsi)' |
58 | * |
59 | * Inputs: |
60 | * %esi : memory location to compare |
61 | * %eax : low 32 bits of old value |
62 | * %edx : high 32 bits of old value |
63 | * %ebx : low 32 bits of new value |
64 | * %ecx : high 32 bits of new value |
65 | * |
66 | * Notably this is not LOCK prefixed and is not safe against NMIs |
67 | */ |
68 | SYM_FUNC_START(this_cpu_cmpxchg8b_emu) |
69 | |
70 | pushfl |
71 | cli |
72 | |
73 | cmpl __percpu (%esi), %eax |
74 | jne .Lnot_same2 |
75 | cmpl __percpu 4(%esi), %edx |
76 | jne .Lnot_same2 |
77 | |
78 | movl %ebx, __percpu (%esi) |
79 | movl %ecx, __percpu 4(%esi) |
80 | |
81 | orl $X86_EFLAGS_ZF, (%esp) |
82 | |
83 | popfl |
84 | RET |
85 | |
86 | .Lnot_same2: |
87 | movl __percpu (%esi), %eax |
88 | movl __percpu 4(%esi), %edx |
89 | |
90 | andl $(~X86_EFLAGS_ZF), (%esp) |
91 | |
92 | popfl |
93 | RET |
94 | |
95 | SYM_FUNC_END(this_cpu_cmpxchg8b_emu) |
96 | |
97 | #endif |
98 | |