1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #include <linux/linkage.h>
3 #include <asm/percpu.h>
4 #include <asm/processor-flags.h>
9 * Emulate 'cmpxchg16b %gs:(%rsi)'
12 * %rsi : memory location to compare
13 * %rax : low 64 bits of old value
14 * %rdx : high 64 bits of old value
15 * %rbx : low 64 bits of new value
16 * %rcx : high 64 bits of new value
18 * Notably this is not LOCK prefixed and is not safe against NMIs
20 SYM_FUNC_START(this_cpu_cmpxchg16b_emu)
25 /* if (*ptr == old) */
26 cmpq __percpu (%rsi), %rax
28 cmpq __percpu 8(%rsi), %rdx
32 movq %rbx, __percpu (%rsi)
33 movq %rcx, __percpu 8(%rsi)
35 /* set ZF in EFLAGS to indicate success */
36 orl $X86_EFLAGS_ZF, (%rsp)
45 movq __percpu (%rsi), %rax
46 movq __percpu 8(%rsi), %rdx
48 /* clear ZF in EFLAGS to indicate failure */
49 andl $(~X86_EFLAGS_ZF), (%rsp)
54 SYM_FUNC_END(this_cpu_cmpxchg16b_emu)