[RFC PATCH v3 06/10] KVM: VMX: Cache force_spec_ctrl_value/mask for each vCPU

From: Chao Gao
Date: Wed Apr 10 2024 - 10:37:33 EST


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@xxxxxxxxx>
---
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(-)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 174790b2ffbc..efbc871d0466 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -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);
}
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 93c208f009cf..cdfcc1290d82 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -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);
}
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 97324f6ee01c..a4dfe538e5a8 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -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;

/*
--
2.39.3