]> xenbits.xensource.com Git - people/andrewcoop/xen.git/commitdiff
PEOI debug peoi-debug
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 30 May 2013 10:18:00 +0000 (11:18 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 10 Oct 2018 11:28:35 +0000 (12:28 +0100)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/acpi/cpu_idle.c
xen/arch/x86/irq.c
xen/include/asm-x86/apic.h
xen/include/asm-x86/irq.h

index 14b02789c54a8038ed4d0c2bf4005725fbc6e5eb..08e3ffd99616cc067289e7da66d6f42f4bcc62ed 100644 (file)
@@ -420,6 +420,8 @@ void mwait_idle_with_hints(unsigned int eax, unsigned int ecx)
     {
         struct cpu_info *info = get_cpu_info();
 
+        peoi_debug_apic(PEOI_IDLE);
+
         cpumask_set_cpu(cpu, &cpuidle_mwait_flags);
 
         spec_ctrl_enter_idle(info);
@@ -427,6 +429,8 @@ void mwait_idle_with_hints(unsigned int eax, unsigned int ecx)
         spec_ctrl_exit_idle(info);
 
         cpumask_clear_cpu(cpu, &cpuidle_mwait_flags);
+
+        peoi_debug_apic(PEOI_WAKE);
     }
 
     if ( expires <= NOW() && expires > 0 )
index 35e7de594fd85749401bbb409fae174a037dec57..2ef6922e70d00aae64cb910175e94bbcc56819a8 100644 (file)
@@ -1148,6 +1148,141 @@ static void irq_guest_eoi_timer_fn(void *data)
     spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+DEFINE_PER_CPU(struct peoi_dbg_record, peoi_dbg[NR_PEOI_RECORDS]);
+DEFINE_PER_CPU(unsigned int, peoi_dbg_idx);
+
+void peoi_debug_stack(enum peoi_dbg_type action, unsigned int sp,
+                      unsigned int irq, unsigned int vector)
+{
+    unsigned int *idx = &this_cpu(peoi_dbg_idx);
+    struct peoi_dbg_record *rec =
+        &this_cpu(peoi_dbg)[*idx & (NR_PEOI_RECORDS - 1)];
+    struct peoi_dbg_stack *stack = &rec->stack;
+
+    rec->seq    = *idx;
+    rec->action = action;
+
+    stack->sp = sp;
+    stack->irq = irq;
+    stack->vector = vector;
+
+    (*idx)++;
+}
+
+void peoi_debug_apic(enum peoi_dbg_type action)
+{
+    unsigned int i, *idx = &this_cpu(peoi_dbg_idx);
+    struct peoi_dbg_record *rec =
+        &this_cpu(peoi_dbg)[*idx & (NR_PEOI_RECORDS - 1)];
+    struct peoi_dbg_apic *apic = &rec->apic;
+    uint32_t *irr = _p(apic->irr);
+    uint32_t *isr = _p(apic->isr);
+
+    rec->seq    = *idx;
+    rec->action = action;
+
+    for ( i = 0; i < APIC_ISR_NR; i++ )
+    {
+        irr[i] = apic_read(APIC_IRR + i * 0x10);
+        isr[i] = apic_read(APIC_ISR + i * 0x10);
+    }
+
+    apic->ppr = apic_read(APIC_PROCPRI);
+
+    (*idx)++;
+}
+
+static void dump_peoi_record(const struct peoi_dbg_record *r)
+{
+    const struct peoi_dbg_stack *s = &r->stack;
+    const struct peoi_dbg_apic  *a = &r->apic;
+
+    switch ( r->action )
+    {
+    case PEOI_PUSH:
+        printk("  [%5u] PUSH     {sp %2d, irq %3d, vec 0x%02x}\n",
+               r->seq, s->sp, s->irq, s->vector);
+        break;
+
+    case PEOI_SETREADY:
+        printk("  [%5u] READY    {sp %2d, irq %3d, vec 0x%02x}\n",
+               r->seq, s->sp, s->irq, s->vector);
+        break;
+
+    case PEOI_FLUSH:
+        printk("  [%5u] FLUSH    %d -> 0\n", r->seq, s->sp);
+        break;
+
+    case PEOI_POP:
+        printk("  [%5u] POP      {sp %2d, irq %3d, vec 0x%02x}\n",
+               r->seq, s->sp, s->irq, s->vector);
+        break;
+
+    case PEOI_IDLE:
+        printk("  [%5u] IDLE     PPR 0x%08x\n", r->seq, a->ppr);
+
+    dump_apic_bitmaps:
+        printk("                   IRR %*phN\n"
+               "                   ISR %*phN\n",
+               (int)sizeof(a->irr), a->irr, (int)sizeof(a->isr), a->isr);
+        break;
+
+    case PEOI_WAKE:
+        printk("  [%5u] WAKE     PPR 0x%08x\n", r->seq, a->ppr);
+        goto dump_apic_bitmaps;
+
+    case PEOI_ACK_PRE:
+        printk("  [%5u] ACK_PRE  PPR 0x%08x\n", r->seq, a->ppr);
+        goto dump_apic_bitmaps;
+
+    case PEOI_ACK_POST:
+        printk("  [%5u] ACK_POST PPR 0x%08x\n", r->seq, a->ppr);
+        goto dump_apic_bitmaps;
+
+    default:
+        printk("  [%5u] ??? %d\n", r->seq, r->action);
+        break;
+    }
+}
+
+static void dump_peoi_records(void)
+{
+    unsigned int i, idx = this_cpu(peoi_dbg_idx);
+    struct peoi_dbg_record *rec = this_cpu(peoi_dbg);
+
+    printk("Peoi stack trace records:\n");
+    for ( i = 0; i < NR_PEOI_RECORDS; ++i )
+        dump_peoi_record(&rec[(idx + i) & (NR_PEOI_RECORDS - 1)]);
+}
+
+static void dump_lapic(void)
+{
+    unsigned int i;
+
+    printk("All LAPIC state:\n");
+    printk("  [vector] %8s %8s %8s\n", "ISR", "TMR", "IRR");
+    for ( i = 0; i < APIC_ISR_NR; ++i )
+        printk("  [%02x:%02x]  %08"PRIx32" %08"PRIx32" %08"PRIx32"\n",
+               (i * 32) + 31, i * 32,
+               apic_read(APIC_ISR + i * 0x10),
+               apic_read(APIC_TMR + i * 0x10),
+               apic_read(APIC_IRR + i * 0x10));
+}
+
+static void dump_peoi_stack(int sp)
+{
+    struct pending_eoi *peoi = this_cpu(pending_eoi);
+    int i;
+
+    printk("Peoi stack: sp %d\n", sp);
+    for ( i = sp - 1; i >= 0; --i )
+        printk("  [%2d] irq %3d, vec 0x%02x, ready %u, ISR %u, TMR %u, IRR %u\n",
+               i, peoi[i].irq, peoi[i].vector, peoi[i].ready,
+               apic_isr_read(peoi[i].vector),
+               apic_tmr_read(peoi[i].vector),
+               apic_irr_read(peoi[i].vector));
+}
+
 static void __do_IRQ_guest(int irq)
 {
     struct irq_desc         *desc = irq_to_desc(irq);
@@ -1170,13 +1305,29 @@ static void __do_IRQ_guest(int irq)
     if ( action->ack_type == ACKTYPE_EOI )
     {
         sp = pending_eoi_sp(peoi);
-        ASSERT((sp == 0) || (peoi[sp-1].vector < vector));
+        if ( !((sp == 0) || (peoi[sp-1].vector < vector)) )
+        {
+            printk("*** Pending EOI error ***\n");
+            printk("  cpu #%u, irq %d, vector 0x%x, sp %d\n",
+                   smp_processor_id(), irq, vector, sp);
+
+            dump_peoi_stack(sp);
+            dump_peoi_records();
+            dump_lapic();
+
+            spin_unlock(&desc->lock);
+
+            assert_failed("(sp == 0) || (peoi[sp-1].vector < vector)");
+        }
+
         ASSERT(sp < (NR_DYNAMIC_VECTORS-1));
         peoi[sp].irq = irq;
         peoi[sp].vector = vector;
         peoi[sp].ready = 0;
         pending_eoi_sp(peoi) = sp+1;
         cpumask_set_cpu(smp_processor_id(), action->cpu_eoi_map);
+
+        peoi_debug_stack(PEOI_PUSH, sp, irq, peoi[sp].vector);
     }
 
     for ( i = 0; i < action->nr_guests; i++ )
@@ -1383,6 +1534,8 @@ static void flush_ready_eoi(void)
         if ( desc->handler->end )
             desc->handler->end(desc, peoi[sp].vector);
         spin_unlock(&desc->lock);
+
+        peoi_debug_stack(PEOI_POP, sp + 1, irq, peoi[sp].vector);
     }
 
     pending_eoi_sp(peoi) = sp+1;
@@ -1409,6 +1562,8 @@ static void __set_eoi_ready(struct irq_desc *desc)
     } while ( peoi[--sp].irq != irq );
     ASSERT(!peoi[sp].ready);
     peoi[sp].ready = 1;
+
+    peoi_debug_stack(PEOI_SETREADY, sp + 1, irq, desc->arch.vector);
 }
 
 /* Mark specified IRQ as ready-for-EOI (if it really is) and attempt to EOI. */
@@ -2448,6 +2603,9 @@ void fixup_eoi(void)
 
     /* Flush the interrupt EOI stack. */
     peoi = this_cpu(pending_eoi);
+
+    peoi_debug_stack(PEOI_FLUSH, pending_eoi_sp(peoi), -1, -1);
+
     for ( sp = 0; sp < pending_eoi_sp(peoi); sp++ )
         peoi[sp].ready = 1;
     flush_ready_eoi();
index 9d7ec93042dbec48a70afe264ea26dfaf52e09c9..77a60f8ac1eb8ef4050eddc10f3e213a45dc7468 100644 (file)
@@ -149,6 +149,16 @@ static __inline bool_t apic_isr_read(u8 vector)
             (vector & 0x1f)) & 1;
 }
 
+static inline bool apic_tmr_read(u8 vector)
+{
+    return apic_read(APIC_TMR + ((vector & ~0x1f) >> 1)) >> (vector & 0x1f);
+}
+
+static inline bool apic_irr_read(u8 vector)
+{
+    return apic_read(APIC_IRR + ((vector & ~0x1f) >> 1)) >> (vector & 0x1f);
+}
+
 static __inline u32 get_apic_id(void) /* Get the physical APIC id */
 {
     u32 id = apic_read(APIC_ID);
@@ -161,8 +171,12 @@ int get_physical_broadcast(void);
 
 static inline void ack_APIC_irq(void)
 {
+    peoi_debug_apic(PEOI_ACK_PRE);
+
        /* Docs say use 0 for future compatibility */
        apic_write(APIC_EOI, 0);
+
+    peoi_debug_apic(PEOI_ACK_POST);
 }
 
 extern int get_maxlvt(void);
index 4b39997f09ea63a21338322d033bbc0d0cdcc66e..d781412528c873f3eb5c53279e7b6bb1708b80a5 100644 (file)
@@ -27,6 +27,43 @@ typedef struct {
     DECLARE_BITMAP(_bits,NR_VECTORS);
 } vmask_t;
 
+struct peoi_dbg_record
+{
+    unsigned int seq;
+
+    enum peoi_dbg_type {
+        PEOI_PUSH,
+        PEOI_SETREADY,
+        PEOI_FLUSH,
+        PEOI_POP,
+
+        PEOI_IDLE,
+        PEOI_WAKE,
+        PEOI_ACK_PRE,
+        PEOI_ACK_POST,
+    } action;
+
+    union {
+        struct peoi_dbg_stack {
+            unsigned int sp, irq, vector;
+        } stack;
+
+        struct peoi_dbg_apic {
+            DECLARE_BITMAP(irr, NR_VECTORS);
+            DECLARE_BITMAP(isr, NR_VECTORS);
+            unsigned int ppr;
+        } apic;
+    };
+};
+
+#define NR_PEOI_RECORDS 32
+DECLARE_PER_CPU(struct peoi_dbg_record, peoi_dbg[NR_PEOI_RECORDS]);
+DECLARE_PER_CPU(unsigned int, peoi_dbg_idx);
+
+void peoi_debug_stack(enum peoi_dbg_type action, unsigned int sp,
+                      unsigned int irq, unsigned int vector);
+void peoi_debug_apic(enum peoi_dbg_type action);
+
 struct irq_desc;
 
 struct arch_irq_desc {