* [PATCH v2 8/9] KVM: selftests: Verify guest debug DR7.GD checking during instruction emulation
2025-12-18 14:00 [PATCH v2 0/9] KVM: x86: Improve the handling of debug exceptions during instruction emulation Hou Wenlong
@ 2025-12-18 14:00 ` Hou Wenlong
2025-12-18 14:00 ` [PATCH v2 9/9] KVM: selftests: Verify 'BS' bit checking in pending debug exception state during VM-Entry Hou Wenlong
2026-05-11 15:45 ` [PATCH v2 0/9] KVM: x86: Improve the handling of debug exceptions during instruction emulation Sean Christopherson
2 siblings, 0 replies; 4+ messages in thread
From: Hou Wenlong @ 2025-12-18 14:00 UTC (permalink / raw)
To: kvm
Cc: Lai Jiangshan, Sean Christopherson, Paolo Bonzini, Shuah Khan,
linux-kselftest, linux-kernel
Similar to the global disable test case in x86's debug_regs test, use
'KVM_FEP' to trigger instruction emulation in order to verify the guest
debug DR7.GD checking during instruction emulation.
Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
---
tools/testing/selftests/kvm/x86/debug_regs.c | 23 +++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/x86/debug_regs.c b/tools/testing/selftests/kvm/x86/debug_regs.c
index 2d814c1d1dc4..bd34cf2a96b7 100644
--- a/tools/testing/selftests/kvm/x86/debug_regs.c
+++ b/tools/testing/selftests/kvm/x86/debug_regs.c
@@ -19,6 +19,7 @@
uint32_t guest_value;
extern unsigned char sw_bp, hw_bp, write_data, ss_start, bd_start;
+extern unsigned char fep_bd_start;
static void guest_code(void)
{
@@ -64,6 +65,10 @@ static void guest_code(void)
/* DR6.BD test */
asm volatile("bd_start: mov %%dr0, %%rax" : : : "rax");
+
+ if (is_forced_emulation_enabled)
+ asm volatile(KVM_FEP "fep_bd_start: mov %%dr0, %%rax" : : : "rax");
+
GUEST_DONE();
}
@@ -185,7 +190,7 @@ int main(void)
target_dr6);
}
- /* Finally test global disable */
+ /* test global disable */
memset(&debug, 0, sizeof(debug));
debug.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
debug.arch.debugreg[7] = 0x400 | DR7_GD;
@@ -202,6 +207,22 @@ int main(void)
run->debug.arch.pc, target_rip, run->debug.arch.dr6,
target_dr6);
+ /* test global disable in emulation */
+ if (is_forced_emulation_enabled) {
+ /* Skip the 3-bytes "mov dr0" */
+ vcpu_skip_insn(vcpu, 3);
+ vcpu_run(vcpu);
+ TEST_ASSERT(run->exit_reason == KVM_EXIT_DEBUG &&
+ run->debug.arch.exception == DB_VECTOR &&
+ run->debug.arch.pc == CAST_TO_RIP(fep_bd_start) &&
+ run->debug.arch.dr6 == target_dr6,
+ "DR7.GD: exit %d exception %d rip 0x%llx "
+ "(should be 0x%llx) dr6 0x%llx (should be 0x%llx)",
+ run->exit_reason, run->debug.arch.exception,
+ run->debug.arch.pc, target_rip, run->debug.arch.dr6,
+ target_dr6);
+ }
+
/* Disable all debug controls, run to the end */
memset(&debug, 0, sizeof(debug));
vcpu_guest_debug_set(vcpu, &debug);
--
2.31.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v2 9/9] KVM: selftests: Verify 'BS' bit checking in pending debug exception state during VM-Entry
2025-12-18 14:00 [PATCH v2 0/9] KVM: x86: Improve the handling of debug exceptions during instruction emulation Hou Wenlong
2025-12-18 14:00 ` [PATCH v2 8/9] KVM: selftests: Verify guest debug DR7.GD checking " Hou Wenlong
@ 2025-12-18 14:00 ` Hou Wenlong
2026-05-11 15:45 ` [PATCH v2 0/9] KVM: x86: Improve the handling of debug exceptions during instruction emulation Sean Christopherson
2 siblings, 0 replies; 4+ messages in thread
From: Hou Wenlong @ 2025-12-18 14:00 UTC (permalink / raw)
To: kvm
Cc: Lai Jiangshan, Sean Christopherson, Paolo Bonzini, Shuah Khan,
linux-kselftest, linux-kernel
In the x86's debug_regs test, add a test case to cover the scenario
where single-step with STI in VMX sets the 'BS' bit in pending debug
exceptions state for #DB interception and instruction emulation in both
cases.
Signed-off-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
---
.../selftests/kvm/include/x86/processor.h | 3 +-
tools/testing/selftests/kvm/x86/debug_regs.c | 53 +++++++++++++++++--
2 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/testing/selftests/kvm/include/x86/processor.h
index 57d62a425109..1992d98016d4 100644
--- a/tools/testing/selftests/kvm/include/x86/processor.h
+++ b/tools/testing/selftests/kvm/include/x86/processor.h
@@ -36,7 +36,8 @@ extern uint64_t guest_tsc_khz;
const char *ex_str(int vector);
-#define X86_EFLAGS_FIXED (1u << 1)
+#define X86_EFLAGS_FIXED (1u << 1)
+#define X86_EFLAGS_TF (1u << 8)
#define X86_CR4_VME (1ul << 0)
#define X86_CR4_PVI (1ul << 1)
diff --git a/tools/testing/selftests/kvm/x86/debug_regs.c b/tools/testing/selftests/kvm/x86/debug_regs.c
index bd34cf2a96b7..84d3103a05fc 100644
--- a/tools/testing/selftests/kvm/x86/debug_regs.c
+++ b/tools/testing/selftests/kvm/x86/debug_regs.c
@@ -15,11 +15,35 @@
#define IRQ_VECTOR 0xAA
+#define CAST_TO_RIP(v) ((unsigned long long)&(v))
+
/* For testing data access debug BP */
uint32_t guest_value;
extern unsigned char sw_bp, hw_bp, write_data, ss_start, bd_start;
-extern unsigned char fep_bd_start;
+extern unsigned char fep_bd_start, fep_sti_start, fep_sti_end;
+
+static void guest_db_handler(struct ex_regs *regs)
+{
+ static int count;
+ unsigned long target_rips[2] = {
+ CAST_TO_RIP(fep_sti_start),
+ CAST_TO_RIP(fep_sti_end),
+ };
+
+ __GUEST_ASSERT(regs->rip == target_rips[count], "STI: unexpected rip 0x%lx (should be 0x%lx)",
+ regs->rip, target_rips[count]);
+ regs->rflags &= ~X86_EFLAGS_TF;
+ count++;
+}
+
+static void guest_irq_handler(struct ex_regs *regs)
+{
+ unsigned long target_rip = CAST_TO_RIP(fep_bd_start);
+
+ __GUEST_ASSERT(regs->rip == target_rip, "IRQ: unexpected rip 0x%lx (should be 0x%lx)",
+ regs->rip, target_rip);
+}
static void guest_code(void)
{
@@ -66,14 +90,27 @@ static void guest_code(void)
/* DR6.BD test */
asm volatile("bd_start: mov %%dr0, %%rax" : : : "rax");
- if (is_forced_emulation_enabled)
+ if (is_forced_emulation_enabled) {
asm volatile(KVM_FEP "fep_bd_start: mov %%dr0, %%rax" : : : "rax");
+ /* pending debug exceptions for emulation */
+ asm volatile("pushf\n\t"
+ "orq $" __stringify(X86_EFLAGS_TF) ", (%rsp)\n\t"
+ "popf\n\t"
+ "sti\n\t"
+ "fep_sti_start:"
+ "cli\n\t"
+ "pushf\n\t"
+ "orq $" __stringify(X86_EFLAGS_TF) ", (%rsp)\n\t"
+ "popf\n\t"
+ KVM_FEP "sti\n\t"
+ "fep_sti_end:"
+ "cli\n\t");
+ }
+
GUEST_DONE();
}
-#define CAST_TO_RIP(v) ((unsigned long long)&(v))
-
static void vcpu_skip_insn(struct kvm_vcpu *vcpu, int insn_len)
{
struct kvm_regs regs;
@@ -227,6 +264,14 @@ int main(void)
memset(&debug, 0, sizeof(debug));
vcpu_guest_debug_set(vcpu, &debug);
+ vm_install_exception_handler(vm, DB_VECTOR, guest_db_handler);
+ /*
+ * Install a dummy IRQ handler, as the single-step #DB delivery after
+ * STI removes the interrupt shadow, so the pending interrupt will be
+ * delivered after #DB handling.
+ */
+ vm_install_exception_handler(vm, IRQ_VECTOR, guest_irq_handler);
+
vcpu_run(vcpu);
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
cmd = get_ucall(vcpu, &uc);
--
2.31.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v2 0/9] KVM: x86: Improve the handling of debug exceptions during instruction emulation
2025-12-18 14:00 [PATCH v2 0/9] KVM: x86: Improve the handling of debug exceptions during instruction emulation Hou Wenlong
2025-12-18 14:00 ` [PATCH v2 8/9] KVM: selftests: Verify guest debug DR7.GD checking " Hou Wenlong
2025-12-18 14:00 ` [PATCH v2 9/9] KVM: selftests: Verify 'BS' bit checking in pending debug exception state during VM-Entry Hou Wenlong
@ 2026-05-11 15:45 ` Sean Christopherson
2 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2026-05-11 15:45 UTC (permalink / raw)
To: Hou Wenlong
Cc: kvm, Lai Jiangshan, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Shuah Khan,
linux-kernel, linux-kselftest
On Thu, Dec 18, 2025, Hou Wenlong wrote:
> Hou Wenlong (9):
> KVM: x86: Capture "struct x86_exception" in
> inject_emulated_exception()
> KVM: x86: Set guest DR6 by kvm_queue_exception_p() in instruction
> emulation
> KVM: x86: Check guest debug in DR access instruction emulation
> KVM: x86: Only check effective code breakpoint in emulation
> KVM: x86: Consolidate KVM_GUESTDBG_SINGLESTEP check into the
> kvm_inject_emulated_db()
> KVM: x86: Move kvm_set_rflags() up before kvm_vcpu_do_singlestep()
> KVM: VMX: Refresh 'PENDING_DBG_EXCEPTIONS.BS' bit during instruction
> emulation
> KVM: selftests: Verify guest debug DR7.GD checking during instruction
> emulation
> KVM: selftests: Verify 'BS' bit checking in pending debug exception
> during VM entry
>
> arch/x86/include/asm/kvm-x86-ops.h | 1 +
> arch/x86/include/asm/kvm_host.h | 1 +
> arch/x86/kvm/emulate.c | 14 +--
> arch/x86/kvm/kvm_emulate.h | 7 +-
> arch/x86/kvm/vmx/main.c | 9 ++
> arch/x86/kvm/vmx/vmx.c | 15 ++-
> arch/x86/kvm/vmx/x86_ops.h | 1 +
> arch/x86/kvm/x86.c | 116 ++++++++++--------
> arch/x86/kvm/x86.h | 7 ++
> .../selftests/kvm/include/x86/processor.h | 3 +-
> tools/testing/selftests/kvm/x86/debug_regs.c | 72 ++++++++++-
> 11 files changed, 178 insertions(+), 68 deletions(-)
One goof and some nits on patch 3, but I'll fix them up when applying, i.e. no
need for a v3. I'll probably also add some comments and elaborate on some of
the changelogs.
^ permalink raw reply [flat|nested] 4+ messages in thread