Skip to content

Commit 484612f

Browse files
yamahatabonzini
authored andcommitted
KVM: x86: Add a switch_db_regs flag to handle TDX's auto-switched behavior
Add a flag KVM_DEBUGREG_AUTO_SWITCH to skip saving/restoring guest DRs. TDX-SEAM unconditionally saves/restores guest DRs on TD exit/enter, and resets DRs to architectural INIT state on TD exit. Use the new flag KVM_DEBUGREG_AUTO_SWITCH to indicate that KVM doesn't need to save/restore guest DRs. KVM still needs to restore host DRs after TD exit if there are active breakpoints in the host, which is covered by the existing code. MOV-DR exiting is always cleared for TDX guests, so the handler for DR access is never called, and KVM_DEBUGREG_WONT_EXIT is never set. Add a warning if both KVM_DEBUGREG_WONT_EXIT and KVM_DEBUGREG_AUTO_SWITCH are set. Opportunistically convert the KVM_DEBUGREG_* definitions to use BIT(). Reported-by: Xiaoyao Li <xiaoyao.li@intel.com> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Co-developed-by: Chao Gao <chao.gao@intel.com> Signed-off-by: Chao Gao <chao.gao@intel.com> Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> [binbin: rework changelog] Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com> Message-ID: <20241210004946.3718496-2-binbin.wu@linux.intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-ID: <20250129095902.16391-13-adrian.hunter@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 8af0990 commit 484612f

File tree

3 files changed

+13
-3
lines changed

3 files changed

+13
-3
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,8 +606,15 @@ struct kvm_pmu {
606606
struct kvm_pmu_ops;
607607

608608
enum {
609-
KVM_DEBUGREG_BP_ENABLED = 1,
610-
KVM_DEBUGREG_WONT_EXIT = 2,
609+
KVM_DEBUGREG_BP_ENABLED = BIT(0),
610+
KVM_DEBUGREG_WONT_EXIT = BIT(1),
611+
/*
612+
* Guest debug registers (DR0-3, DR6 and DR7) are saved/restored by
613+
* hardware on exit from or enter to guest. KVM needn't switch them.
614+
* DR0-3, DR6 and DR7 are set to their architectural INIT value on VM
615+
* exit, host values need to be restored.
616+
*/
617+
KVM_DEBUGREG_AUTO_SWITCH = BIT(2),
611618
};
612619

613620
struct kvm_mtrr {

arch/x86/kvm/vmx/tdx.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ int tdx_vcpu_create(struct kvm_vcpu *vcpu)
630630

631631
vcpu->arch.efer = EFER_SCE | EFER_LME | EFER_LMA | EFER_NX;
632632

633+
vcpu->arch.switch_db_regs = KVM_DEBUGREG_AUTO_SWITCH;
633634
vcpu->arch.cr0_guest_owned_bits = -1ul;
634635
vcpu->arch.cr4_guest_owned_bits = -1ul;
635636

arch/x86/kvm/x86.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10985,7 +10985,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
1098510985
if (vcpu->arch.guest_fpu.xfd_err)
1098610986
wrmsrl(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
1098710987

10988-
if (unlikely(vcpu->arch.switch_db_regs)) {
10988+
if (unlikely(vcpu->arch.switch_db_regs &&
10989+
!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH))) {
1098910990
set_debugreg(0, 7);
1099010991
set_debugreg(vcpu->arch.eff_db[0], 0);
1099110992
set_debugreg(vcpu->arch.eff_db[1], 1);
@@ -11037,6 +11038,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
1103711038
*/
1103811039
if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
1103911040
WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
11041+
WARN_ON(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH);
1104011042
kvm_x86_call(sync_dirty_debug_regs)(vcpu);
1104111043
kvm_update_dr0123(vcpu);
1104211044
kvm_update_dr7(vcpu);

0 commit comments

Comments
 (0)