@@ -176,6 +176,16 @@ static u32 vmx_possible_passthrough_msrs[MAX_POSSIBLE_PASSTHROUGH_MSRS] = {
MSR_FS_BASE,
MSR_GS_BASE,
MSR_KERNEL_GS_BASE,
+ MSR_IA32_FRED_RSP0,
+ MSR_IA32_FRED_RSP1,
+ MSR_IA32_FRED_RSP2,
+ MSR_IA32_FRED_RSP3,
+ MSR_IA32_FRED_STKLVLS,
+ MSR_IA32_FRED_SSP1,
+ MSR_IA32_FRED_SSP2,
+ MSR_IA32_FRED_SSP3,
+ MSR_IA32_FRED_CONFIG,
+ MSR_IA32_FRED_SSP0, /* Should be added through CET */
MSR_IA32_XFD,
MSR_IA32_XFD_ERR,
#endif
@@ -7935,6 +7945,34 @@ static void update_intel_pt_cfg(struct kvm_vcpu *vcpu)
vmx->pt_desc.ctl_bitmask &= ~(0xfULL << (32 + i * 4));
}
+static void vmx_set_intercept_for_fred_msr(struct kvm_vcpu *vcpu)
+{
+ bool flag = !guest_cpu_cap_has(vcpu, X86_FEATURE_FRED);
+
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP1, MSR_TYPE_RW, flag);
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP2, MSR_TYPE_RW, flag);
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP3, MSR_TYPE_RW, flag);
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_STKLVLS, MSR_TYPE_RW, flag);
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_SSP1, MSR_TYPE_RW, flag);
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_SSP2, MSR_TYPE_RW, flag);
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_SSP3, MSR_TYPE_RW, flag);
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_CONFIG, MSR_TYPE_RW, flag);
+
+ /*
+ * IA32_FRED_RSP0 and IA32_PL0_SSP (a.k.a. IA32_FRED_SSP0) are only used
+ * for delivering events when running userspace, while KVM always runs in
+ * kernel mode (the CPL is always 0 after any VM exit), thus KVM can run
+ * safely with guest IA32_FRED_RSP0 and IA32_PL0_SSP.
+ *
+ * As a result, no need to intercept IA32_FRED_RSP0 and IA32_PL0_SSP.
+ *
+ * Note, save and restore of IA32_PL0_SSP belong to CET supervisor context
+ * management no matter whether FRED is enabled or not. So leave its
+ * state management to CET code.
+ */
+ vmx_set_intercept_for_msr(vcpu, MSR_IA32_FRED_RSP0, MSR_TYPE_RW, flag);
+}
+
void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -8007,6 +8045,8 @@ void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
/* Refresh #PF interception to account for MAXPHYADDR changes. */
vmx_update_exception_bitmap(vcpu);
+
+ vmx_set_intercept_for_fred_msr(vcpu);
}
static __init u64 vmx_get_perf_capabilities(void)
@@ -356,7 +356,7 @@ struct vcpu_vmx {
struct lbr_desc lbr_desc;
/* Save desired MSR intercept (read: pass-through) state */
-#define MAX_POSSIBLE_PASSTHROUGH_MSRS 16
+#define MAX_POSSIBLE_PASSTHROUGH_MSRS 26
struct {
DECLARE_BITMAP(read, MAX_POSSIBLE_PASSTHROUGH_MSRS);
DECLARE_BITMAP(write, MAX_POSSIBLE_PASSTHROUGH_MSRS);