162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __KVM_X86_SVM_OPS_H
362306a36Sopenharmony_ci#define __KVM_X86_SVM_OPS_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/compiler_types.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "x86.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define svm_asm(insn, clobber...)				\
1062306a36Sopenharmony_cido {								\
1162306a36Sopenharmony_ci	asm goto("1: " __stringify(insn) "\n\t"	\
1262306a36Sopenharmony_ci			  _ASM_EXTABLE(1b, %l[fault])		\
1362306a36Sopenharmony_ci			  ::: clobber : fault);			\
1462306a36Sopenharmony_ci	return;							\
1562306a36Sopenharmony_cifault:								\
1662306a36Sopenharmony_ci	kvm_spurious_fault();					\
1762306a36Sopenharmony_ci} while (0)
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define svm_asm1(insn, op1, clobber...)				\
2062306a36Sopenharmony_cido {								\
2162306a36Sopenharmony_ci	asm goto("1: "  __stringify(insn) " %0\n\t"	\
2262306a36Sopenharmony_ci			  _ASM_EXTABLE(1b, %l[fault])		\
2362306a36Sopenharmony_ci			  :: op1 : clobber : fault);		\
2462306a36Sopenharmony_ci	return;							\
2562306a36Sopenharmony_cifault:								\
2662306a36Sopenharmony_ci	kvm_spurious_fault();					\
2762306a36Sopenharmony_ci} while (0)
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define svm_asm2(insn, op1, op2, clobber...)				\
3062306a36Sopenharmony_cido {									\
3162306a36Sopenharmony_ci	asm goto("1: "  __stringify(insn) " %1, %0\n\t"	\
3262306a36Sopenharmony_ci			  _ASM_EXTABLE(1b, %l[fault])			\
3362306a36Sopenharmony_ci			  :: op1, op2 : clobber : fault);		\
3462306a36Sopenharmony_ci	return;								\
3562306a36Sopenharmony_cifault:									\
3662306a36Sopenharmony_ci	kvm_spurious_fault();						\
3762306a36Sopenharmony_ci} while (0)
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic inline void clgi(void)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	svm_asm(clgi);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic inline void stgi(void)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	svm_asm(stgi);
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic inline void invlpga(unsigned long addr, u32 asid)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	svm_asm2(invlpga, "c"(asid), "a"(addr));
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/*
5562306a36Sopenharmony_ci * Despite being a physical address, the portion of rAX that is consumed by
5662306a36Sopenharmony_ci * VMSAVE, VMLOAD, etc... is still controlled by the effective address size,
5762306a36Sopenharmony_ci * hence 'unsigned long' instead of 'hpa_t'.
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_cistatic __always_inline void vmsave(unsigned long pa)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	svm_asm1(vmsave, "a" (pa), "memory");
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#endif /* __KVM_X86_SVM_OPS_H */
65