diff options
| -rw-r--r-- | arch/x86/kvm/svm.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 254eefb3b57f..4e3c79530526 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
| @@ -184,6 +184,8 @@ struct vcpu_svm { | |||
| 184 | u64 gs_base; | 184 | u64 gs_base; |
| 185 | } host; | 185 | } host; |
| 186 | 186 | ||
| 187 | u64 spec_ctrl; | ||
| 188 | |||
| 187 | u32 *msrpm; | 189 | u32 *msrpm; |
| 188 | 190 | ||
| 189 | ulong nmi_iret_rip; | 191 | ulong nmi_iret_rip; |
| @@ -249,6 +251,7 @@ static const struct svm_direct_access_msrs { | |||
| 249 | { .index = MSR_CSTAR, .always = true }, | 251 | { .index = MSR_CSTAR, .always = true }, |
| 250 | { .index = MSR_SYSCALL_MASK, .always = true }, | 252 | { .index = MSR_SYSCALL_MASK, .always = true }, |
| 251 | #endif | 253 | #endif |
| 254 | { .index = MSR_IA32_SPEC_CTRL, .always = false }, | ||
| 252 | { .index = MSR_IA32_PRED_CMD, .always = false }, | 255 | { .index = MSR_IA32_PRED_CMD, .always = false }, |
| 253 | { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false }, | 256 | { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false }, |
| 254 | { .index = MSR_IA32_LASTBRANCHTOIP, .always = false }, | 257 | { .index = MSR_IA32_LASTBRANCHTOIP, .always = false }, |
| @@ -882,6 +885,25 @@ static bool valid_msr_intercept(u32 index) | |||
| 882 | return false; | 885 | return false; |
| 883 | } | 886 | } |
| 884 | 887 | ||
| 888 | static bool msr_write_intercepted(struct kvm_vcpu *vcpu, unsigned msr) | ||
| 889 | { | ||
| 890 | u8 bit_write; | ||
| 891 | unsigned long tmp; | ||
| 892 | u32 offset; | ||
| 893 | u32 *msrpm; | ||
| 894 | |||
| 895 | msrpm = is_guest_mode(vcpu) ? to_svm(vcpu)->nested.msrpm: | ||
| 896 | to_svm(vcpu)->msrpm; | ||
| 897 | |||
| 898 | offset = svm_msrpm_offset(msr); | ||
| 899 | bit_write = 2 * (msr & 0x0f) + 1; | ||
| 900 | tmp = msrpm[offset]; | ||
| 901 | |||
| 902 | BUG_ON(offset == MSR_INVALID); | ||
| 903 | |||
| 904 | return !!test_bit(bit_write, &tmp); | ||
| 905 | } | ||
| 906 | |||
| 885 | static void set_msr_interception(u32 *msrpm, unsigned msr, | 907 | static void set_msr_interception(u32 *msrpm, unsigned msr, |
| 886 | int read, int write) | 908 | int read, int write) |
| 887 | { | 909 | { |
| @@ -1584,6 +1606,8 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) | |||
| 1584 | u32 dummy; | 1606 | u32 dummy; |
| 1585 | u32 eax = 1; | 1607 | u32 eax = 1; |
| 1586 | 1608 | ||
| 1609 | svm->spec_ctrl = 0; | ||
| 1610 | |||
| 1587 | if (!init_event) { | 1611 | if (!init_event) { |
| 1588 | svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE | | 1612 | svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE | |
| 1589 | MSR_IA32_APICBASE_ENABLE; | 1613 | MSR_IA32_APICBASE_ENABLE; |
| @@ -3605,6 +3629,13 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
| 3605 | case MSR_VM_CR: | 3629 | case MSR_VM_CR: |
| 3606 | msr_info->data = svm->nested.vm_cr_msr; | 3630 | msr_info->data = svm->nested.vm_cr_msr; |
| 3607 | break; | 3631 | break; |
| 3632 | case MSR_IA32_SPEC_CTRL: | ||
| 3633 | if (!msr_info->host_initiated && | ||
| 3634 | !guest_cpuid_has(vcpu, X86_FEATURE_IBRS)) | ||
| 3635 | return 1; | ||
| 3636 | |||
| 3637 | msr_info->data = svm->spec_ctrl; | ||
| 3638 | break; | ||
| 3608 | case MSR_IA32_UCODE_REV: | 3639 | case MSR_IA32_UCODE_REV: |
| 3609 | msr_info->data = 0x01000065; | 3640 | msr_info->data = 0x01000065; |
| 3610 | break; | 3641 | break; |
| @@ -3696,6 +3727,33 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) | |||
| 3696 | case MSR_IA32_TSC: | 3727 | case MSR_IA32_TSC: |
| 3697 | kvm_write_tsc(vcpu, msr); | 3728 | kvm_write_tsc(vcpu, msr); |
| 3698 | break; | 3729 | break; |
| 3730 | case MSR_IA32_SPEC_CTRL: | ||
| 3731 | if (!msr->host_initiated && | ||
| 3732 | !guest_cpuid_has(vcpu, X86_FEATURE_IBRS)) | ||
| 3733 | return 1; | ||
| 3734 | |||
| 3735 | /* The STIBP bit doesn't fault even if it's not advertised */ | ||
| 3736 | if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP)) | ||
| 3737 | return 1; | ||
| 3738 | |||
| 3739 | svm->spec_ctrl = data; | ||
| 3740 | |||
| 3741 | if (!data) | ||
| 3742 | break; | ||
| 3743 | |||
| 3744 | /* | ||
| 3745 | * For non-nested: | ||
| 3746 | * When it's written (to non-zero) for the first time, pass | ||
| 3747 | * it through. | ||
| 3748 | * | ||
| 3749 | * For nested: | ||
| 3750 | * The handling of the MSR bitmap for L2 guests is done in | ||
| 3751 | * nested_svm_vmrun_msrpm. | ||
| 3752 | * We update the L1 MSR bit as well since it will end up | ||
| 3753 | * touching the MSR anyway now. | ||
| 3754 | */ | ||
| 3755 | set_msr_interception(svm->msrpm, MSR_IA32_SPEC_CTRL, 1, 1); | ||
| 3756 | break; | ||
| 3699 | case MSR_IA32_PRED_CMD: | 3757 | case MSR_IA32_PRED_CMD: |
| 3700 | if (!msr->host_initiated && | 3758 | if (!msr->host_initiated && |
| 3701 | !guest_cpuid_has(vcpu, X86_FEATURE_IBPB)) | 3759 | !guest_cpuid_has(vcpu, X86_FEATURE_IBPB)) |
| @@ -4964,6 +5022,15 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) | |||
| 4964 | 5022 | ||
| 4965 | local_irq_enable(); | 5023 | local_irq_enable(); |
| 4966 | 5024 | ||
| 5025 | /* | ||
| 5026 | * If this vCPU has touched SPEC_CTRL, restore the guest's value if | ||
| 5027 | * it's non-zero. Since vmentry is serialising on affected CPUs, there | ||
| 5028 | * is no need to worry about the conditional branch over the wrmsr | ||
| 5029 | * being speculatively taken. | ||
| 5030 | */ | ||
| 5031 | if (svm->spec_ctrl) | ||
| 5032 | wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl); | ||
| 5033 | |||
| 4967 | asm volatile ( | 5034 | asm volatile ( |
| 4968 | "push %%" _ASM_BP "; \n\t" | 5035 | "push %%" _ASM_BP "; \n\t" |
| 4969 | "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t" | 5036 | "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t" |
| @@ -5056,6 +5123,27 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) | |||
| 5056 | #endif | 5123 | #endif |
| 5057 | ); | 5124 | ); |
| 5058 | 5125 | ||
| 5126 | /* | ||
| 5127 | * We do not use IBRS in the kernel. If this vCPU has used the | ||
| 5128 | * SPEC_CTRL MSR it may have left it on; save the value and | ||
| 5129 | * turn it off. This is much more efficient than blindly adding | ||
| 5130 | * it to the atomic save/restore list. Especially as the former | ||
| 5131 | * (Saving guest MSRs on vmexit) doesn't even exist in KVM. | ||
| 5132 | * | ||
| 5133 | * For non-nested case: | ||
| 5134 | * If the L01 MSR bitmap does not intercept the MSR, then we need to | ||
| 5135 | * save it. | ||
| 5136 | * | ||
| 5137 | * For nested case: | ||
| 5138 | * If the L02 MSR bitmap does not intercept the MSR, then we need to | ||
| 5139 | * save it. | ||
| 5140 | */ | ||
| 5141 | if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)) | ||
| 5142 | rdmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl); | ||
| 5143 | |||
| 5144 | if (svm->spec_ctrl) | ||
| 5145 | wrmsrl(MSR_IA32_SPEC_CTRL, 0); | ||
| 5146 | |||
| 5059 | /* Eliminate branch target predictions from guest mode */ | 5147 | /* Eliminate branch target predictions from guest mode */ |
| 5060 | vmexit_fill_RSB(); | 5148 | vmexit_fill_RSB(); |
| 5061 | 5149 | ||
