1/* SPDX-License-Identifier: GPL-2.0-only */ 2#include <linux/linkage.h> 3#include <asm/percpu.h> 4#include <asm/processor-flags.h> 5 6.text 7 8/* 9 * Emulate 'cmpxchg16b %gs:(%rsi)' 10 * 11 * Inputs: 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 17 * 18 * Notably this is not LOCK prefixed and is not safe against NMIs 19 */ 20SYM_FUNC_START(this_cpu_cmpxchg16b_emu) 21 22 pushfq 23 cli 24 25 /* if (*ptr == old) */ 26 cmpq PER_CPU_VAR(0(%rsi)), %rax 27 jne .Lnot_same 28 cmpq PER_CPU_VAR(8(%rsi)), %rdx 29 jne .Lnot_same 30 31 /* *ptr = new */ 32 movq %rbx, PER_CPU_VAR(0(%rsi)) 33 movq %rcx, PER_CPU_VAR(8(%rsi)) 34 35 /* set ZF in EFLAGS to indicate success */ 36 orl $X86_EFLAGS_ZF, (%rsp) 37 38 popfq 39 RET 40 41.Lnot_same: 42 /* *ptr != old */ 43 44 /* old = *ptr */ 45 movq PER_CPU_VAR(0(%rsi)), %rax 46 movq PER_CPU_VAR(8(%rsi)), %rdx 47 48 /* clear ZF in EFLAGS to indicate failure */ 49 andl $(~X86_EFLAGS_ZF), (%rsp) 50 51 popfq 52 RET 53 54SYM_FUNC_END(this_cpu_cmpxchg16b_emu) 55