On Tue, 2021-05-04 at 10:17 -0700, Sean Christopherson wrote: > Intercept RDTSCP to inject #UD if RDTSC is disabled in the guest. > > Note, SVM does not support intercepting RDPID. Unlike VMX's > ENABLE_RDTSCP control, RDTSCP interception does not apply to RDPID. This > is a benign virtualization hole as the host kernel (incorrectly) sets > MSR_TSC_AUX if RDTSCP is supported, and KVM loads the guest's MSR_TSC_AUX > into hardware if RDTSCP is supported in the host, i.e. KVM will not leak > the host's MSR_TSC_AUX to the guest. > > But, when the kernel bug is fixed, KVM will start leaking the host's > MSR_TSC_AUX if RDPID is supported in hardware, but RDTSCP isn't available > for whatever reason. This leak will be remedied in a future commit. > > Fixes: 46896c73c1a4 ("KVM: svm: add support for RDTSCP") > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- > arch/x86/kvm/svm/svm.c | 17 +++++++++++++---- > 1 file changed, 13 insertions(+), 4 deletions(-) > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c > index a7271f31df47..8f2b184270c0 100644 > --- a/arch/x86/kvm/svm/svm.c > +++ b/arch/x86/kvm/svm/svm.c > @@ -1100,7 +1100,9 @@ static u64 svm_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) > return svm->vmcb->control.tsc_offset; > } > > -static void svm_check_invpcid(struct vcpu_svm *svm) > +/* Evaluate instruction intercepts that depend on guest CPUID features. */ > +static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu, > + struct vcpu_svm *svm) > { > /* > * Intercept INVPCID if shadow paging is enabled to sync/free shadow > @@ -1113,6 +1115,13 @@ static void svm_check_invpcid(struct vcpu_svm *svm) > else > svm_clr_intercept(svm, INTERCEPT_INVPCID); > } > + > + if (kvm_cpu_cap_has(X86_FEATURE_RDTSCP)) { > + if (guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP)) > + svm_clr_intercept(svm, INTERCEPT_RDTSCP); > + else > + svm_set_intercept(svm, INTERCEPT_RDTSCP); > + } > } > > static void init_vmcb(struct kvm_vcpu *vcpu) > @@ -1248,7 +1257,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu) > svm_clr_intercept(svm, INTERCEPT_PAUSE); > } > > - svm_check_invpcid(svm); > + svm_recalc_instruction_intercepts(vcpu, svm); > > /* > * If the host supports V_SPEC_CTRL then disable the interception > @@ -3084,6 +3093,7 @@ static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = { > [SVM_EXIT_STGI] = stgi_interception, > [SVM_EXIT_CLGI] = clgi_interception, > [SVM_EXIT_SKINIT] = skinit_interception, > + [SVM_EXIT_RDTSCP] = kvm_handle_invalid_op, > [SVM_EXIT_WBINVD] = kvm_emulate_wbinvd, > [SVM_EXIT_MONITOR] = kvm_emulate_monitor, > [SVM_EXIT_MWAIT] = kvm_emulate_mwait, > @@ -4007,8 +4017,7 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) > svm->nrips_enabled = kvm_cpu_cap_has(X86_FEATURE_NRIPS) && > guest_cpuid_has(vcpu, X86_FEATURE_NRIPS); > > - /* Check again if INVPCID interception if required */ > - svm_check_invpcid(svm); > + svm_recalc_instruction_intercepts(vcpu, svm); > > /* For sev guests, the memory encryption bit is not reserved in CR3. */ > if (sev_guest(vcpu->kvm)) { Reviewed-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> Best regards, Maxim Levitsky