/* SPDX-License-Identifier: GPL-2.0-only */1#include <linux/linkage.h>2#include <asm/percpu.h>3#include <asm/processor-flags.h>45.text67/*8* Emulate 'cmpxchg16b %gs:(%rsi)'9*10* Inputs:11* %rsi : memory location to compare12* %rax : low 64 bits of old value13* %rdx : high 64 bits of old value14* %rbx : low 64 bits of new value15* %rcx : high 64 bits of new value16*17* Notably this is not LOCK prefixed and is not safe against NMIs18*/19SYM_FUNC_START(this_cpu_cmpxchg16b_emu)2021pushfq22cli2324/* if (*ptr == old) */25cmpq __percpu (%rsi), %rax26jne .Lnot_same27cmpq __percpu 8(%rsi), %rdx28jne .Lnot_same2930/* *ptr = new */31movq %rbx, __percpu (%rsi)32movq %rcx, __percpu 8(%rsi)3334/* set ZF in EFLAGS to indicate success */35orl $X86_EFLAGS_ZF, (%rsp)3637popfq38RET3940.Lnot_same:41/* *ptr != old */4243/* old = *ptr */44movq __percpu (%rsi), %rax45movq __percpu 8(%rsi), %rdx4647/* clear ZF in EFLAGS to indicate failure */48andl $(~X86_EFLAGS_ZF), (%rsp)4950popfq51RET5253SYM_FUNC_END(this_cpu_cmpxchg16b_emu)545556