Hi Sean, > @@ -4265,6 +4265,16 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, > clgi(); > kvm_load_guest_xsave_state(vcpu); > > + /* > + * Hardware only context switches DEBUGCTL if LBR virtualization is > + * enabled. Manually load DEBUGCTL if necessary (and restore it after > + * VM-Exit), as running with the host's DEBUGCTL can negatively affect > + * guest state and can even be fatal, e.g. due to Bus Lock Detect. > + */ > + if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK) && > + vcpu->arch.host_debugctl != svm->vmcb->save.dbgctl) > + update_debugctlmsr(0); ^^^^^^^^^^^^^^^^^^^^^ You mean: update_debugctlmsr(svm->vmcb->save.dbgctl); ? Somewhat related but independent: CPU automatically clears DEBUGCTL[BTF] on #DB exception. So, when DEBUGCTL is save/restored by KVM (i.e. when LBR virtualization is disabled), it's KVM's responsibility to clear DEBUGCTL[BTF]. --- @@ -2090,6 +2090,14 @@ static int db_interception(struct kvm_vcpu *vcpu) (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) && !svm->nmi_singlestep) { u32 payload = svm->vmcb->save.dr6 ^ DR6_ACTIVE_LOW; + + /* + * CPU automatically clears DEBUGCTL[BTF] on #DB exception. + * Simulate it when DEBUGCTL isn't auto save/restored. + */ + if (!(svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK)) + svm->vmcb->save.dbgctl &= ~0x2; + kvm_queue_exception_p(vcpu, DB_VECTOR, payload); return 1; } --- Thanks, Ravi