Patch "KVM/SVM: Allow direct access to MSR_IA32_SPEC_CTRL" has been added to the 4.9-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
KVM/SVM: Allow direct access to MSR_IA32_SPEC_CTRL
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
kvm-svm-allow-direct-access-to-msr_ia32_spec_ctrl.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
b2ac58f90540e39324e7a29a7ad471407ae0bf48Mon Sep 17 00:00:00 2001
From: KarimAllah Ahmed <[email protected]>
Date: Sat, 3 Feb 2018 15:56:23 +0100
Subject: KVM/SVM: Allow direct access to MSR_IA32_SPEC_CTRL
From: KarimAllah Ahmed <[email protected]>
commit b2ac58f90540e39324e7a29a7ad471407ae0bf48 upstream.
[ Based on a patch from Paolo Bonzini <[email protected]> ]
... basically doing exactly what we do for VMX:
- Passthrough SPEC_CTRL to guests (if enabled in guest CPUID)
- Save and restore SPEC_CTRL around VMExit and VMEntry only if the guest actually used it.
--- arch/x86/kvm/svm.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
arch/x86/kvm/svm.c +88 -0
@@ -183,6 +183,8 @@ struct vcpu_svm {u64 gs_base; } host; +u64 spec_ctrl; +u32 *msrpm;ulong nmi_iret_rip;
@@ -248,6 +250,7 @@ static const struct svm_direct_access_ms { .index = MSR_CSTAR, .always = true }, { .index = MSR_SYSCALL_MASK, .always = true }, #endif + { .index = MSR_IA32_SPEC_CTRL, .always = false }, { .index = MSR_IA32_PRED_CMD, .always = false }, { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false }, { .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
@@ -863,6 +866,25 @@ static bool valid_msr_intercept(u32 indereturn false; } +static bool msr_write_intercepted (struct kvm_vcpu *vcpu,unsigned msr) +{ +u8 bit_write; +unsigned long tmp; +u32 offset; +u32 *msrpm; + + msrpm =is_guest_mode (vcpu) ?to_svm (vcpu)->nested.msrpm: +to_svm (vcpu)->msrpm; + + offset =svm_msrpm_offset (msr); + bit_write =2 * (msr &0x0f ) +1 ; + tmp = msrpm[offset]; + +BUG_ON (offset ==MSR_INVALID ); + +return !!test_bit (bit_write, &tmp); +} +static void set_msr_interception (u32 *msrpm,unsigned msr,int read,int write) {
@@ -1537,6 +1559,8 @@ static void svm_vcpu_reset(struct kvm_vcu32 dummy;u32 eax =1 ; + svm->spec_ctrl =0 ; +if (!init_event) { svm->vcpu.arch.apic_base =APIC_DEFAULT_PHYS_BASE |MSR_IA32_APICBASE_ENABLE ;
@@ -3520,6 +3544,13 @@ static int svm_get_msr(struct kvm_vcpu *case MSR_VM_CR : msr_info->data = svm->nested.vm_cr_msr;break ; +case MSR_IA32_SPEC_CTRL : +if (!msr_info->host_initiated && + !guest_cpuid_has_ibrs (vcpu)) +return 1 ; + + msr_info->data = svm->spec_ctrl; +break ;case MSR_IA32_UCODE_REV : msr_info->data =0x01000065 ;break ;
@@ -3611,6 +3642,33 @@ static int svm_set_msr(struct kvm_vcpu *case MSR_IA32_TSC :kvm_write_tsc (vcpu, msr);break ; +case MSR_IA32_SPEC_CTRL : +if (!msr->host_initiated && + !guest_cpuid_has_ibrs (vcpu)) +return 1 ; + +/* The STIBP bit doesn't fault even if it's not advertised */ +if (data & ~(SPEC_CTRL_IBRS |SPEC_CTRL_STIBP )) +return 1 ; + + svm->spec_ctrl = data; + +if (!data) +break ; + +/* +* For non-nested: +* When it's written (to non-zero) for the first time, pass +* it through. +* +* For nested: +* The handling of the MSR bitmap for L2 guests is done in +* nested_svm_vmrun_msrpm. +* We update the L1 MSR bit as well since it will end up +* touching the MSR anyway now. +*/ +set_msr_interception (svm->msrpm,MSR_IA32_SPEC_CTRL ,1 ,1 ); +break ;case MSR_IA32_PRED_CMD :if (!msr->host_initiated && !guest_cpuid_has_ibpb (vcpu))
@@ -4854,6 +4912,15 @@ static void svm_vcpu_run(struct kvm_vcpulocal_irq_enable (); +/* +* If this vCPU has touched SPEC_CTRL, restore the guest's value if +* it's non-zero. Since vmentry is serialising on affected CPUs, there +* is no need to worry about the conditional branch over the wrmsr +* being speculatively taken. +*/ +if (svm->spec_ctrl) +wrmsrl (MSR_IA32_SPEC_CTRL , svm->spec_ctrl); + asmvolatile ("push %%" _ASM_BP"; \n\t" "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
@@ -4946,6 +5013,27 @@ static void svm_vcpu_run(struct kvm_vcpu#endif ); +/* +* We do not use IBRS in the kernel. If this vCPU has used the +* SPEC_CTRL MSR it may have left it on; save the value and +* turn it off. This is much more efficient than blindly adding +* it to the atomic save/restore list. Especially as the former +* (Saving guest MSRs on vmexit) doesn't even exist in KVM. +* +* For non-nested case: +* If the L01 MSR bitmap does not intercept the MSR, then we need to +* save it. +* +* For nested case: +* If the L02 MSR bitmap does not intercept the MSR, then we need to +* save it. +*/ +if (!msr_write_intercepted (vcpu,MSR_IA32_SPEC_CTRL )) +rdmsrl (MSR_IA32_SPEC_CTRL , svm->spec_ctrl); + +if (svm->spec_ctrl) +wrmsrl (MSR_IA32_SPEC_CTRL ,0 ); +/* Eliminate branch target predictions from guest mode */ vmexit_fill_RSB ();
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/kvm-vmx-allow-direct-access-to-msr_ia32_spec_ctrl.patch queue-4.9/kvm-x86-add-ibpb-support.patch queue-4.9/kvm-svm-allow-direct-access-to-msr_ia32_spec_ctrl.patch queue-4.9/kvm-vmx-emulate-msr_ia32_arch_capabilities.patch