[PATCH v2] x86: show_hvm_stack() requires enabled interrupts

Jan Beulich posted 1 patch 1 year, 8 months ago
Failed in applying to current master (apply log)
[PATCH v2] x86: show_hvm_stack() requires enabled interrupts
Posted by Jan Beulich 1 year, 8 months ago
show_hvm_stack() requires interrupts to be enabled to avoid triggering
the consistency check in check_lock() for the p2m lock. Add a respective
check. To avoid this check triggering when coming through
spurious_interrupt() requires adding reentrancy protection / handling
there alongside transiently (re-)enabling IRQs.

Fixes: adb715db698b ("x86/HVM: also dump stacks from show_execution_state()")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Check IRQs enabled before calling show_hvm_stack(). Re-base.

--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -1384,22 +1384,40 @@ void smp_send_state_dump(unsigned int cp
  */
 void cf_check 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;
     }
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -660,7 +660,9 @@ void show_execution_state(const struct c
     {
         struct vcpu *curr = current;
 
-        if ( is_hvm_vcpu(curr) )
+        if ( !is_hvm_vcpu(curr) )
+            show_guest_stack(curr, regs);
+        else if ( flags & X86_EFLAGS_IF )
         {
             /*
              * Stop interleaving prevention: The necessary P2M lookups
@@ -671,8 +673,6 @@ void show_execution_state(const struct c
             show_hvm_stack(curr, regs);
             return;
         }
-
-        show_guest_stack(curr, regs);
     }
     else
     {