@@ -2390,7 +2390,7 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs0
exec_control &= TERTIARY_EXEC_SPEC_CTRL_SHADOW;
if (exec_control & TERTIARY_EXEC_SPEC_CTRL_SHADOW)
vmcs_write64(IA32_SPEC_CTRL_MASK,
- vmx->vcpu.kvm->arch.force_spec_ctrl_mask);
+ vmx->force_spec_ctrl_mask);
tertiary_exec_controls_set(vmx, exec_control);
}
@@ -2161,7 +2161,7 @@ static void vmx_set_spec_ctrl(struct kvm_vcpu *vcpu, u64 val)
vmx->spec_ctrl_shadow = val;
vmcs_write64(IA32_SPEC_CTRL_SHADOW, val);
- vmx->spec_ctrl |= vcpu->kvm->arch.force_spec_ctrl_value;
+ vmx->spec_ctrl |= vmx->force_spec_ctrl_value;
}
}
@@ -4803,6 +4803,9 @@ static void init_vmcs(struct vcpu_vmx *vmx)
if (cpu_has_vmx_xsaves())
vmcs_write64(XSS_EXIT_BITMAP, VMX_XSS_EXIT_BITMAP);
+ vmx->force_spec_ctrl_mask = kvm->arch.force_spec_ctrl_mask;
+ vmx->force_spec_ctrl_value = kvm->arch.force_spec_ctrl_value;
+
if (cpu_has_spec_ctrl_shadow()) {
vmx->spec_ctrl_shadow = 0;
vmcs_write64(IA32_SPEC_CTRL_SHADOW, 0);
@@ -4816,7 +4819,7 @@ static void init_vmcs(struct vcpu_vmx *vmx)
* guest modify other bits at will, without triggering VM-Exits.
*/
if (kvm->arch.force_spec_ctrl_mask)
- vmcs_write64(IA32_SPEC_CTRL_MASK, kvm->arch.force_spec_ctrl_mask);
+ vmcs_write64(IA32_SPEC_CTRL_MASK, vmx->force_spec_ctrl_mask);
else
vmcs_write64(IA32_SPEC_CTRL_MASK, 0);
}
@@ -7251,8 +7254,8 @@ void noinstr vmx_spec_ctrl_restore_host(struct vcpu_vmx *vmx,
if (cpu_has_spec_ctrl_shadow()) {
vmx->spec_ctrl_shadow = vmcs_read64(IA32_SPEC_CTRL_SHADOW);
vmx->spec_ctrl = (vmx->spec_ctrl_shadow &
- ~vmx->vcpu.kvm->arch.force_spec_ctrl_mask) |
- vmx->vcpu.kvm->arch.force_spec_ctrl_value;
+ ~vmx->force_spec_ctrl_mask) |
+ vmx->force_spec_ctrl_value;
} else {
vmx->spec_ctrl = __rdmsr(MSR_IA32_SPEC_CTRL);
}
@@ -287,6 +287,13 @@ struct vcpu_vmx {
*/
u64 spec_ctrl_shadow;
+ /*
+ * Mask and value of SPEC_CTRL MSR bits which the guest is not allowed to
+ * change.
+ */
+ u64 force_spec_ctrl_mask;
+ u64 force_spec_ctrl_value;
+
u32 msr_ia32_umwait_control;
/*
so that KVM can adjust the mask/value for each vCPU according to the software mitigations the vCPU is using. KVM_CAP_FORCE_SPEC_CTRL allows the userspace VMM to proactively enable hardware mitigations (by setting some bits in IA32_SPEC_CTRL MSRs) to protect the guest from becoming vulnerable to some security issues after live migration. E.g., if a guest using the short BHB-clearing sequence for BHI is migrated from a pre-SPR part to a SPR part will become vulnerable for BHI. Current solution is the userspace VMM deploys BHI_DIS_S for all guests migrated to SPR parts from pre-SPR parts. But KVM_CAP_FORCE_SPEC_CTRL isn't flexible because the userspace VMM may configure KVM to enable BHI_DIS_S for guests which don't care about BHI at all or are using other mitigations (e.g, TSX abort sequence) for BHI. This would cause unnecessary overhead to the guest. To reduce the overhead, the idea is to let the guest communicate which software mitigations are being used to the VMM via Intel-defined virtual MSRs [1]. This information from guests is much more accurate. KVM can adjust hardware mitigations accordingly to reduce the performance impact to the guest as much as possible. The Intel-defined value MSRs are per-thread scope. vCPUs _can_ program different values to them. This means, KVM may need to apply different mask/value to IA32_SPEC_CTRL MSR. So, cache force_spec_ctrl_value/mask for each vCPU in preparation for adding support for intel-defined virtual MSRs. [1]: https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/branch-history-injection.html Signed-off-by: Chao Gao <chao.gao@intel.com> --- arch/x86/kvm/vmx/nested.c | 2 +- arch/x86/kvm/vmx/vmx.c | 11 +++++++---- arch/x86/kvm/vmx/vmx.h | 7 +++++++ 3 files changed, 15 insertions(+), 5 deletions(-)