18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci#include <linux/linkage.h>
38c2ecf20Sopenharmony_ci#include <asm/percpu.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci.text
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci/*
88c2ecf20Sopenharmony_ci * Inputs:
98c2ecf20Sopenharmony_ci * %rsi : memory location to compare
108c2ecf20Sopenharmony_ci * %rax : low 64 bits of old value
118c2ecf20Sopenharmony_ci * %rdx : high 64 bits of old value
128c2ecf20Sopenharmony_ci * %rbx : low 64 bits of new value
138c2ecf20Sopenharmony_ci * %rcx : high 64 bits of new value
148c2ecf20Sopenharmony_ci * %al  : Operation successful
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ciSYM_FUNC_START(this_cpu_cmpxchg16b_emu)
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#
198c2ecf20Sopenharmony_ci# Emulate 'cmpxchg16b %gs:(%rsi)' except we return the result in %al not
208c2ecf20Sopenharmony_ci# via the ZF.  Caller will access %al to get result.
218c2ecf20Sopenharmony_ci#
228c2ecf20Sopenharmony_ci# Note that this is only useful for a cpuops operation.  Meaning that we
238c2ecf20Sopenharmony_ci# do *not* have a fully atomic operation but just an operation that is
248c2ecf20Sopenharmony_ci# *atomic* on a single cpu (as provided by the this_cpu_xx class of
258c2ecf20Sopenharmony_ci# macros).
268c2ecf20Sopenharmony_ci#
278c2ecf20Sopenharmony_ci	pushfq
288c2ecf20Sopenharmony_ci	cli
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	cmpq PER_CPU_VAR((%rsi)), %rax
318c2ecf20Sopenharmony_ci	jne .Lnot_same
328c2ecf20Sopenharmony_ci	cmpq PER_CPU_VAR(8(%rsi)), %rdx
338c2ecf20Sopenharmony_ci	jne .Lnot_same
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	movq %rbx, PER_CPU_VAR((%rsi))
368c2ecf20Sopenharmony_ci	movq %rcx, PER_CPU_VAR(8(%rsi))
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	popfq
398c2ecf20Sopenharmony_ci	mov $1, %al
408c2ecf20Sopenharmony_ci	RET
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci.Lnot_same:
438c2ecf20Sopenharmony_ci	popfq
448c2ecf20Sopenharmony_ci	xor %al,%al
458c2ecf20Sopenharmony_ci	RET
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ciSYM_FUNC_END(this_cpu_cmpxchg16b_emu)
48