summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorHou Wenlong <houwenlong.hwl@antgroup.com>2026-05-15 15:26:33 -0700
committerSean Christopherson <seanjc@google.com>2026-05-21 14:40:19 -0700
commit00b6520669bc7a1d7df1e138a555e9ef8c314233 (patch)
treee892d169908f8c322e06aed8eef4e58e3ecd0a0c /arch
parent51543660c521a30450bcbf74956f14b591c4a58c (diff)
downloadlinux-next-00b6520669bc7a1d7df1e138a555e9ef8c314233.tar.gz
linux-next-00b6520669bc7a1d7df1e138a555e9ef8c314233.zip
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 <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>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/x86.c35
1 files changed, 10 insertions, 25 deletions
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;
}
}