From: Hou Wenlong Date: Fri, 15 May 2026 22:26:33 +0000 (-0700) Subject: KVM: x86: Honor KVM_GUESTDBG_USE_HW_BP when checking for code breakpoints in emulation X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00b6520669bc7a1d7df1e138a555e9ef8c314233;p=thirdparty%2Fkernel%2Flinux.git KVM: x86: Honor KVM_GUESTDBG_USE_HW_BP when checking for code breakpoints in emulation 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 [sean: massage changelog] Link: https://patch.msgid.link/20260515222638.1949982-6-seanjc@google.com Signed-off-by: Sean Christopherson --- diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 42ab2fd0cb9f..f50151d11fa2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -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; } }