On 4/16/2025 8:25 AM, Maxim Levitsky wrote: > Pass through the host's DEBUGCTL.DEBUGCTLMSR_FREEZE_IN_SMM to the guest > GUEST_IA32_DEBUGCTL without the guest seeing this value. > > Note that in the future we might allow the guest to set this bit as well, > when we implement PMU freezing on VM own, virtual SMM entry. > > Since the value of the host DEBUGCTL can in theory change between VM runs, > check if has changed, and if yes, then reload the GUEST_IA32_DEBUGCTL with > the new value of the host portion of it (currently only the > DEBUGCTLMSR_FREEZE_IN_SMM bit) > > Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> > --- > arch/x86/kvm/svm/svm.c | 2 ++ > arch/x86/kvm/vmx/vmx.c | 28 +++++++++++++++++++++++++++- > arch/x86/kvm/x86.c | 2 -- > 3 files changed, 29 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c > index cc1c721ba067..fda0660236d8 100644 > --- a/arch/x86/kvm/svm/svm.c > +++ b/arch/x86/kvm/svm/svm.c > @@ -4271,6 +4271,8 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, > svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP]; > svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP]; > > + vcpu->arch.host_debugctl = get_debugctlmsr(); > + > /* > * Disable singlestep if we're injecting an interrupt/exception. > * We don't want our modified rflags to be pushed on the stack where > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index c9208a4acda4..e0bc31598d60 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -2194,6 +2194,17 @@ static u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated > return debugctl; > } > > +static u64 vmx_get_host_preserved_debugctl(struct kvm_vcpu *vcpu) > +{ > + /* > + * Bits of host's DEBUGCTL that we should preserve while the guest is > + * running. > + * > + * Some of those bits might still be emulated for the guest own use. > + */ > + return DEBUGCTLMSR_FREEZE_IN_SMM; > +} Seems unnecessary to define a function here, a macro is enough. #define HOST_DEBUGCTL_PRESERVE_BITS (DEBUGCTLMSR_FREEZE_IN_SMM) > + > u64 vmx_get_guest_debugctl(struct kvm_vcpu *vcpu) > { > return to_vmx(vcpu)->msr_ia32_debugctl; > @@ -2202,9 +2213,11 @@ u64 vmx_get_guest_debugctl(struct kvm_vcpu *vcpu) > static void __vmx_set_guest_debugctl(struct kvm_vcpu *vcpu, u64 data) > { > struct vcpu_vmx *vmx = to_vmx(vcpu); > + u64 host_mask = vmx_get_host_preserved_debugctl(vcpu); > > vmx->msr_ia32_debugctl = data; > - vmcs_write64(GUEST_IA32_DEBUGCTL, data); > + vmcs_write64(GUEST_IA32_DEBUGCTL, > + (vcpu->arch.host_debugctl & host_mask) | (data & ~host_mask)); > } > > bool vmx_set_guest_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated) > @@ -2232,6 +2245,7 @@ bool vmx_set_guest_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated > return true; > } > > + > /* > * Writes msr value into the appropriate "register". > * Returns 0 on success, non-0 otherwise. > @@ -7349,6 +7363,7 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit) > { > struct vcpu_vmx *vmx = to_vmx(vcpu); > unsigned long cr3, cr4; > + u64 old_debugctl; > > /* Record the guest's net vcpu time for enforced NMI injections. */ > if (unlikely(!enable_vnmi && > @@ -7379,6 +7394,17 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit) > vmcs_write32(PLE_WINDOW, vmx->ple_window); > } > > + old_debugctl = vcpu->arch.host_debugctl; > + vcpu->arch.host_debugctl = get_debugctlmsr(); > + > + /* > + * In case the host DEBUGCTL had changed since the last time we > + * read it, update the guest's GUEST_IA32_DEBUGCTL with > + * the host's bits. > + */ > + if (old_debugctl != vcpu->arch.host_debugctl) > + __vmx_set_guest_debugctl(vcpu, vmx->msr_ia32_debugctl); > + > /* > * We did this in prepare_switch_to_guest, because it needs to > * be within srcu_read_lock. > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 844e81ee1d96..05e866ed345d 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -11020,8 +11020,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) > set_debugreg(0, 7); > } > > - vcpu->arch.host_debugctl = get_debugctlmsr(); > - > guest_timing_enter_irqoff(); > > for (;;) {