Skip to content

Commit eaaa119

Browse files
mcarabasBrian Maly
authored andcommitted
KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL - reloaded
This commit is filling out the blanks that were missed in the backport 26a0cd2 ("KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL") due to lack of different interfaces. 26a0cd2 ("KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL") is basically an incomplet cherry-pick from d28b387. Also added the interception of MSR_IA32_SPEC_CTRL and MSR_IA32_PRED_CMD in order for the get/set MSR handling to have a sense. Orabug: 28069548 Signed-off-by: Mihai Carabas <[email protected]> Reviewed-by: Darren Kenny <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent e5455ef commit eaaa119

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

arch/x86/kvm/cpuid.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
358358

359359
/* cpuid 0x80000008.ebx */
360360
const u32 kvm_cpuid_80000008_ebx_x86_features =
361-
KF(IBPB) | KF(VIRT_SSBD);
361+
KF(IBPB) | KF(IBRS) | KF(VIRT_SSBD);
362362

363363
/* all calls to cpuid_count() should be made on the same cpu */
364364
get_cpu();

arch/x86/kvm/cpuid.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,12 @@ static inline bool guest_cpuid_has_ibrs(struct kvm_vcpu *vcpu)
152152
best = kvm_find_cpuid_entry(vcpu, 7, 0);
153153
return best && (best->edx & KF(IBRS));
154154
}
155+
156+
static inline bool guest_cpuid_has_ssbd(struct kvm_vcpu *vcpu)
157+
{
158+
struct kvm_cpuid_entry2 *best;
159+
160+
best = kvm_find_cpuid_entry(vcpu, 7, 0);
161+
return best && (best->edx & KF(SSBD));
162+
}
155163
#endif

arch/x86/kvm/vmx.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2856,6 +2856,11 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
28562856
msr_info->data = guest_read_tsc();
28572857
break;
28582858
case MSR_IA32_SPEC_CTRL:
2859+
if (!msr_info->host_initiated &&
2860+
!guest_cpuid_has_ibrs(vcpu) &&
2861+
!guest_cpuid_has_ssbd(vcpu))
2862+
return 1;
2863+
28592864
msr_info->data = to_vmx(vcpu)->spec_ctrl;
28602865
break;
28612866
case MSR_IA32_ARCH_CAPABILITIES:
@@ -2956,7 +2961,35 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
29562961
kvm_write_tsc(vcpu, msr_info);
29572962
break;
29582963
case MSR_IA32_SPEC_CTRL:
2959-
to_vmx(vcpu)->spec_ctrl = data;
2964+
if (!msr_info->host_initiated &&
2965+
!guest_cpuid_has_ibrs(vcpu) &&
2966+
!guest_cpuid_has_ssbd(vcpu))
2967+
return 1;
2968+
2969+
/* The STIBP bit doesn't fault even if it's not advertised */
2970+
if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP))
2971+
return 1;
2972+
2973+
vmx->spec_ctrl = data;
2974+
2975+
if (!data)
2976+
break;
2977+
2978+
/*
2979+
* For non-nested:
2980+
* When it's written (to non-zero) for the first time, pass
2981+
* it through.
2982+
*
2983+
* For nested:
2984+
* The handling of the MSR bitmap for L2 guests is done in
2985+
* nested_vmx_merge_msr_bitmap. We should not touch the
2986+
* vmcs02.msr_bitmap here since it gets completely overwritten
2987+
* in the merging. We update the vmcs01 here for L1 as well
2988+
* since it will end up touching the MSR anyway now.
2989+
*/
2990+
vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
2991+
MSR_IA32_SPEC_CTRL,
2992+
MSR_TYPE_RW);
29602993
break;
29612994
case MSR_IA32_PRED_CMD:
29622995
if (!msr_info->host_initiated &&
@@ -8718,8 +8751,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
87188751
vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_CS, MSR_TYPE_RW);
87198752
vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_ESP, MSR_TYPE_RW);
87208753
vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_EIP, MSR_TYPE_RW);
8721-
vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SPEC_CTRL, MSR_TYPE_RW);
8722-
vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_PRED_CMD, MSR_TYPE_RW);
87238754
vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_BNDCFGS, MSR_TYPE_RW);
87248755
vmx->msr_bitmap_mode = 0;
87258756

@@ -9118,7 +9149,7 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
91189149
unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap;
91199150

91209151
/*
9121-
* pred_cmd is trying to verify two things:
9152+
* pred_cmd & spec_ctrl are trying to verify two things:
91229153
*
91239154
* 1. L0 gave a permission to L1 to actually passthrough the MSR. This
91249155
* ensures that we do not accidentally generate an L02 MSR bitmap
@@ -9131,9 +9162,10 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
91319162
* the MSR.
91329163
*/
91339164
bool pred_cmd = msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD);
9165+
bool spec_ctrl = msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL);
91349166

91359167
if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
9136-
!pred_cmd)
9168+
!pred_cmd && !spec_ctrl)
91379169
return false;
91389170

91399171
page = nested_get_page(vcpu, vmcs12->msr_bitmap);
@@ -9180,6 +9212,12 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
91809212
MSR_IA32_PRED_CMD,
91819213
MSR_TYPE_W);
91829214

9215+
if (spec_ctrl)
9216+
nested_vmx_disable_intercept_for_msr(
9217+
msr_bitmap_l1, msr_bitmap_l0,
9218+
MSR_IA32_SPEC_CTRL,
9219+
MSR_TYPE_R | MSR_TYPE_W);
9220+
91839221
kunmap(page);
91849222
nested_release_page_clean(page);
91859223

0 commit comments

Comments
 (0)