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