show_hvm_stack() requires interrupts to be enabled to avoids triggering
the consistency check in check_lock() for the p2m lock. To do so in
spurious_interrupt() requires adding reentrancy protection / handling
there.

Fixes: adb715db698b ("x86/HVM: also dump stacks from show_execution_state()")
Signed-off-by: Jan Beulich <jbeul...@suse.com>
---
The obvious (but imo undesirable) alternative is to suppress the call to
show_hvm_stack() when interrupts are disabled.

--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -1386,22 +1386,40 @@ void smp_send_state_dump(unsigned int cp
  */
 void spurious_interrupt(struct cpu_user_regs *regs)
 {
+    static DEFINE_PER_CPU(unsigned int, recursed);
+    unsigned int cpu = smp_processor_id();
+
     /*
      * Check if this is a vectored interrupt (most likely, as this is probably
      * a request to dump local CPU state or to continue NMI handling).
      * Vectored interrupts are ACKed; spurious interrupts are not.
      */
-    if (apic_isr_read(SPURIOUS_APIC_VECTOR)) {
+    while ( apic_isr_read(SPURIOUS_APIC_VECTOR) )
+    {
         bool is_spurious;
 
+        if ( per_cpu(recursed, cpu)++ )
+            return;
+
         ack_APIC_irq();
         is_spurious = !nmi_check_continuation();
-        if (this_cpu(state_dump_pending)) {
-            this_cpu(state_dump_pending) = false;
+
+        if ( per_cpu(state_dump_pending, cpu) )
+        {
+            per_cpu(state_dump_pending, cpu) = false;
+
+            local_irq_enable();
+
             dump_execstate(regs);
-            is_spurious = false;
+
+            local_irq_disable();
+
+            /* (Ab)use is_spurious to arrange for loop continuation. */
+            is_spurious = per_cpu(recursed, cpu) > 1;
         }
 
+        per_cpu(recursed, cpu) = 0;
+
         if ( !is_spurious )
             return;
     }


Reply via email to