/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __KVM_X86_VMENTER_H #define __KVM_X86_VMENTER_H #include #define KVM_ENTER_VMRESUME BIT(0) #define KVM_ENTER_SAVE_SPEC_CTRL BIT(1) #define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO BIT(2) #ifdef __ASSEMBLER__ .macro RESTORE_GUEST_SPEC_CTRL_BODY guest_spec_ctrl:req, label:req /* * SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the * host's, write the MSR. This is kept out-of-line so that the common * case does not have to jump. * * IMPORTANT: To avoid RSB underflow attacks and any other nastiness, * there must not be any returns or indirect branches between this code * and vmentry. */ #ifdef CONFIG_X86_64 mov \guest_spec_ctrl, %rdx cmp PER_CPU_VAR(x86_spec_ctrl_current), %rdx je \label movl %edx, %eax shr $32, %rdx #else mov \guest_spec_ctrl, %eax mov PER_CPU_VAR(x86_spec_ctrl_current), %ecx xor %eax, %ecx mov 4 + \guest_spec_ctrl, %edx mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %esi xor %edx, %esi or %esi, %ecx je \label #endif mov $MSR_IA32_SPEC_CTRL, %ecx wrmsr .endm .macro RESTORE_HOST_SPEC_CTRL_BODY guest_spec_ctrl:req, enter_flags:req, label:req /* Same for after vmexit. */ mov $MSR_IA32_SPEC_CTRL, %ecx /* * Load the value that the guest had written into MSR_IA32_SPEC_CTRL, * if it was not intercepted during guest execution. */ testl $KVM_ENTER_SAVE_SPEC_CTRL, \enter_flags jz 998f rdmsr movl %eax, \guest_spec_ctrl movl %edx, 4 + \guest_spec_ctrl 998: /* Now restore the host value of the MSR if different from the guest's. */ #ifdef CONFIG_X86_64 mov PER_CPU_VAR(x86_spec_ctrl_current), %rdx cmp \guest_spec_ctrl, %rdx /* * For legacy IBRS, the IBRS bit always needs to be written after * transitioning from a less privileged predictor mode, regardless of * whether the guest/host values differ. */ ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS movl %edx, %eax shr $32, %rdx #else mov PER_CPU_VAR(x86_spec_ctrl_current), %eax mov \guest_spec_ctrl, %esi xor %eax, %esi mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %edx mov 4 + \guest_spec_ctrl, %edi xor %edx, %edi or %edi, %esi ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS #endif wrmsr .endm #define WORD_SIZE (BITS_PER_LONG / 8) .macro LOAD_REGS src:req, regs_ofs:req, regs:vararg .irp reg, \regs REG_NUM reg_num \reg mov (\regs_ofs + reg_num * WORD_SIZE)(\src), \reg .endr .endm .macro STORE_REGS dst:req, regs_ofs:req, regs:vararg .irp reg, \regs REG_NUM reg_num \reg mov \reg, (\regs_ofs + reg_num * WORD_SIZE)(\dst) .endr .endm .macro POP_REGS dst:req, regs_ofs:req, regs:vararg .irp reg, \regs REG_NUM reg_num \reg pop (\regs_ofs + reg_num * WORD_SIZE)(\dst) .endr .endm .macro CLEAR_REGS regs:vararg .irp reg, \regs xorl \reg, \reg .endr .endm #endif /* __ASSEMBLER__ */ #endif /* __KVM_X86_VMENTER_H */