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 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 | |