1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __KVM_X86_VMENTER_H 3 #define __KVM_X86_VMENTER_H 4 5 #include <asm/kvm_vcpu_regs.h> 6 7 #define KVM_ENTER_VMRESUME BIT(0) 8 #define KVM_ENTER_SAVE_SPEC_CTRL BIT(1) 9 #define KVM_ENTER_CLEAR_CPU_BUFFERS_FOR_MMIO BIT(2) 10 11 #ifdef __ASSEMBLER__ 12 .macro RESTORE_GUEST_SPEC_CTRL_BODY guest_spec_ctrl:req, label:req 13 /* 14 * SPEC_CTRL handling: if the guest's SPEC_CTRL value differs from the 15 * host's, write the MSR. This is kept out-of-line so that the common 16 * case does not have to jump. 17 * 18 * IMPORTANT: To avoid RSB underflow attacks and any other nastiness, 19 * there must not be any returns or indirect branches between this code 20 * and vmentry. 21 */ 22 #ifdef CONFIG_X86_64 23 mov \guest_spec_ctrl, %rdx 24 cmp PER_CPU_VAR(x86_spec_ctrl_current), %rdx 25 je \label 26 movl %edx, %eax 27 shr $32, %rdx 28 #else 29 mov \guest_spec_ctrl, %eax 30 mov PER_CPU_VAR(x86_spec_ctrl_current), %ecx 31 xor %eax, %ecx 32 mov 4 + \guest_spec_ctrl, %edx 33 mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %esi 34 xor %edx, %esi 35 or %esi, %ecx 36 je \label 37 #endif 38 mov $MSR_IA32_SPEC_CTRL, %ecx 39 wrmsr 40 .endm 41 42 .macro RESTORE_HOST_SPEC_CTRL_BODY guest_spec_ctrl:req, enter_flags:req, label:req 43 /* Same for after vmexit. */ 44 mov $MSR_IA32_SPEC_CTRL, %ecx 45 46 /* 47 * Load the value that the guest had written into MSR_IA32_SPEC_CTRL, 48 * if it was not intercepted during guest execution. 49 */ 50 testl $KVM_ENTER_SAVE_SPEC_CTRL, \enter_flags 51 jz 998f 52 rdmsr 53 movl %eax, \guest_spec_ctrl 54 movl %edx, 4 + \guest_spec_ctrl 55 998: 56 /* Now restore the host value of the MSR if different from the guest's. */ 57 #ifdef CONFIG_X86_64 58 mov PER_CPU_VAR(x86_spec_ctrl_current), %rdx 59 cmp \guest_spec_ctrl, %rdx 60 /* 61 * For legacy IBRS, the IBRS bit always needs to be written after 62 * transitioning from a less privileged predictor mode, regardless of 63 * whether the guest/host values differ. 64 */ 65 ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS 66 movl %edx, %eax 67 shr $32, %rdx 68 #else 69 mov PER_CPU_VAR(x86_spec_ctrl_current), %eax 70 mov \guest_spec_ctrl, %esi 71 xor %eax, %esi 72 mov PER_CPU_VAR(x86_spec_ctrl_current + 4), %edx 73 mov 4 + \guest_spec_ctrl, %edi 74 xor %edx, %edi 75 or %edi, %esi 76 ALTERNATIVE __stringify(je \label), "", X86_FEATURE_KERNEL_IBRS 77 #endif 78 wrmsr 79 .endm 80 81 #define WORD_SIZE (BITS_PER_LONG / 8) 82 83 .macro LOAD_REGS src:req, regs_ofs:req, regs:vararg 84 .irp reg, \regs 85 REG_NUM reg_num \reg 86 mov (\regs_ofs + reg_num * WORD_SIZE)(\src), \reg 87 .endr 88 .endm 89 90 .macro STORE_REGS dst:req, regs_ofs:req, regs:vararg 91 .irp reg, \regs 92 REG_NUM reg_num \reg 93 mov \reg, (\regs_ofs + reg_num * WORD_SIZE)(\dst) 94 .endr 95 .endm 96 97 .macro POP_REGS dst:req, regs_ofs:req, regs:vararg 98 .irp reg, \regs 99 REG_NUM reg_num \reg 100 pop (\regs_ofs + reg_num * WORD_SIZE)(\dst) 101 .endr 102 .endm 103 104 .macro CLEAR_REGS regs:vararg 105 .irp reg, \regs 106 xorl \reg, \reg 107 .endr 108 .endm 109 110 #endif /* __ASSEMBLER__ */ 111 #endif /* __KVM_X86_VMENTER_H */ 112