On Wed, May 13, 2026 at 04:14:14PM -0700, Sean Christopherson wrote:
> On Thu, Dec 18, 2025, Hou Wenlong wrote:
> > 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.
> 
> ...
> 
> > +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);
> 
> This is wrong, and the test fails with your series applied verbatim.  The IRQ
> will arrive at fep_sti_start, because RFLAGS.IF=0 from the CLI at the end of 
> the
> ss_start block, and remains that way across fep_bd_start.   And to make things
> even more confusing, the IRQ arrives on the CLI even though it's in an STI 
> shadow
> due to #DBs not being subjected to _STI_ shadows on Intel, only to 
> MOV-SS/POP-SS
> shadows.  I.e. the #DB lands on CLI, pushes RFLAGS.IF=1 on the stack, and then
> the subsequent IRET from guest_db_handler() fully unmasks IRQs, and voila.

Yes, the RIP here should be 'fep_sti_start'. This was a stupid mistake,
and I’m very sorry about that. In my reply to v1[0] I explained why an IRQ
handler is needed, so in v2 I added comments and an additional check,
and I tested it before sending. However, it looks like the patch differs
from what I had locally—my code management was a bit messy.

As you pointed out, this pending interrupt can make the test somewhat
confusing. So it might be better to consume the IRQ before running the
test, e.g.:

```
diff --git a/tools/testing/selftests/kvm/x86/debug_regs.c
b/tools/testing/selftests/kvm/x86/debug_regs.c
index 3ec2724697de..030d5cb58cc2 100644
--- a/tools/testing/selftests/kvm/x86/debug_regs.c
+++ b/tools/testing/selftests/kvm/x86/debug_regs.c
@@ -21,7 +21,7 @@
 u32 guest_value;

 extern unsigned char sw_bp, hw_bp, write_data, ss_start, bd_start;
-extern unsigned char fep_bd_start, fep_sti_start, fep_sti_end;
+extern unsigned char fep_irq, fep_bd_start, fep_sti_start, fep_sti_end;

 static void guest_db_handler(struct ex_regs *regs)
 {
@@ -39,7 +39,7 @@ static void guest_db_handler(struct ex_regs *regs)

 static void guest_irq_handler(struct ex_regs *regs)
 {
-       unsigned long target_rip = CAST_TO_RIP(fep_bd_start);
+       unsigned long target_rip = CAST_TO_RIP(fep_irq);

        __GUEST_ASSERT(regs->rip == target_rip, "IRQ: unexpected rip
0x%lx (should be 0x%lx)",
                       regs->rip, target_rip);
@@ -93,6 +93,14 @@ static void guest_code(void)
        if (is_forced_emulation_enabled) {
                asm volatile(KVM_FEP "fep_bd_start: mov %%dr0, %%rax" :
: : "rax");

+               /*
+                * Consume the pending interrupt, as the single-step #DB
delivery after
+                * STI removes the interrupt shadow, so the pending
interrupt will be
+                * delivered after guest #DB handling.
+                */
+               asm volatile("sti; nop\n\t"
+                            "fep_irq:");
+
                /* pending debug exceptions for emulation */
                asm volatile("pushf\n\t"
                             "orq $" __stringify(X86_EFLAGS_TF) ",
(%rsp)\n\t"
@@ -264,13 +272,10 @@ 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);
+       if (is_forced_emulation_enabled) {
+               vm_install_exception_handler(vm, DB_VECTOR,
guest_db_handler);
+               vm_install_exception_handler(vm, IRQ_VECTOR,
guest_irq_handler);
+       }

        vcpu_run(vcpu);
        TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
```

I have tested it on both Intel and AMD. Please let me know if I should
resend a v3 of this patch.

[0]: https://lore.kernel.org/kvm/[email protected]/

Thanks!


Reply via email to