]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: x86: Honor KVM_GUESTDBG_USE_HW_BP when checking for code breakpoints in emulation
authorHou Wenlong <houwenlong.hwl@antgroup.com>
Fri, 15 May 2026 22:26:33 +0000 (15:26 -0700)
committerSean Christopherson <seanjc@google.com>
Thu, 21 May 2026 21:40:19 +0000 (14:40 -0700)
When KVM_GUESTDBG_USE_HW_BP is enabled, i.e. userspace is usurping the
guest's hardware debug registers, the guest's effective breakpoints are
controlled by userspace rather than by the guest itself.  Honor the
KVM_GUESTDBG_USE_HW_BP behavior when handling code #DBs in the emulator so
that userspace (and the guest) gets consistent behavior for code #DBs
regardless of whether an instruction is executed natively or emulated by
KVM.

To aid in userspace debug, don't treat code breakpoints as inhibited if
KVM_GUESTDBG_USE_HW_BP is enabled as accurately emulating x86 architecture
is obviously a non-goal of guest-debug.

Fixes: 4a1e10d5b5d8 ("KVM: x86: handle hardware breakpoints during emulation")
Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
[sean: massage changelog]
Link: https://patch.msgid.link/20260515222638.1949982-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/x86.c

index 42ab2fd0cb9f6f45a9f6f429c56bf0b286d348d2..f50151d11fa2b69eebd69e331aecb77aec1c8d0f 100644 (file)
@@ -9320,6 +9320,9 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_skip_emulated_instruction);
 
 static bool kvm_is_code_breakpoint_inhibited(struct kvm_vcpu *vcpu)
 {
+       if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
+               return false;
+
        if (kvm_get_rflags(vcpu) & X86_EFLAGS_RF)
                return true;
 
@@ -9336,6 +9339,8 @@ static bool kvm_is_code_breakpoint_inhibited(struct kvm_vcpu *vcpu)
 static bool kvm_vcpu_check_code_breakpoint(struct kvm_vcpu *vcpu,
                                           int emulation_type, int *r)
 {
+       unsigned long dr7 = kvm_get_effective_dr7(vcpu);
+
        WARN_ON_ONCE(emulation_type & EMULTYPE_NO_DECODE);
 
        /*
@@ -9356,34 +9361,14 @@ static bool kvm_vcpu_check_code_breakpoint(struct kvm_vcpu *vcpu,
                              EMULTYPE_TRAP_UD | EMULTYPE_VMWARE_GP | EMULTYPE_PF))
                return false;
 
-       if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) &&
-           (vcpu->arch.guest_debug_dr7 & DR7_BP_EN_MASK)) {
-               struct kvm_run *kvm_run = vcpu->run;
-               unsigned long eip = kvm_get_linear_rip(vcpu);
-               u32 dr6 = kvm_vcpu_check_hw_bp(eip, 0,
-                                          vcpu->arch.guest_debug_dr7,
-                                          vcpu->arch.eff_db);
-
-               if (dr6 != 0) {
-                       kvm_run->debug.arch.dr6 = dr6 | DR6_ACTIVE_LOW;
-                       kvm_run->debug.arch.pc = eip;
-                       kvm_run->debug.arch.exception = DB_VECTOR;
-                       kvm_run->exit_reason = KVM_EXIT_DEBUG;
-                       *r = 0;
-                       return true;
-               }
-       }
-
-       if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK) &&
+       if (unlikely(dr7 & DR7_BP_EN_MASK) &&
            !kvm_is_code_breakpoint_inhibited(vcpu)) {
                unsigned long eip = kvm_get_linear_rip(vcpu);
-               u32 dr6 = kvm_vcpu_check_hw_bp(eip, 0,
-                                          vcpu->arch.dr7,
-                                          vcpu->arch.db);
+               u32 dr6 = kvm_vcpu_check_hw_bp(eip, 0, dr7,
+                                              vcpu->arch.eff_db);
 
-               if (dr6 != 0) {
-                       kvm_queue_exception_p(vcpu, DB_VECTOR, dr6);
-                       *r = 1;
+               if (dr6) {
+                       *r = kvm_inject_emulated_db(vcpu, dr6);
                        return true;
                }
        }