diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-04-21 12:22:57 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-05-01 13:25:39 +1000 |
commit | f9b5a51f4ba81b74b111513a106df5cbd444e1b2 (patch) | |
tree | 3808383094c595ad1bd511987e954be16697611d /hw | |
parent | c205afe6143c017cf88f60d5f5ea038fa928ff01 (diff) | |
download | skiboot-f9b5a51f4ba81b74b111513a106df5cbd444e1b2.zip skiboot-f9b5a51f4ba81b74b111513a106df5cbd444e1b2.tar.gz skiboot-f9b5a51f4ba81b74b111513a106df5cbd444e1b2.tar.bz2 |
xive: Check queues for duplicates in DEBUG builds
There should never be duplicate interrupts in a queue.
This adds code to check that when looking at the queue
content. Since it can be a performance loss, this is only
done for debug builds.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xive.c | 59 |
1 files changed, 58 insertions, 1 deletions
@@ -38,6 +38,13 @@ /* Verbose debug */ #undef XIVE_VERBOSE_DEBUG +/* Check for duplicate interrupts in queues */ +#ifdef DEBUG +#define XIVE_DEBUG_DUPLICATES +#else +#undef XIVE_DEBUG_DUPLICATES +#endif + /* * * VSDs, blocks, set translation etc... @@ -3028,9 +3035,37 @@ static void xive_init_cpu_properties(struct cpu_thread *cpu) dt_add_property_cells(cpu->node, "interrupt-parent", get_ics_phandle()); } +#ifdef XIVE_DEBUG_DUPLICATES +static uint32_t xive_count_irq_copies(struct xive_cpu_state *xs, uint32_t ref) +{ + uint32_t i, irq; + uint32_t cnt = 0; + uint32_t pos = xs->eqptr; + uint32_t gen = xs->eqgen; + + for (i = 0; i < 0x3fff; i++) { + irq = xs->eqbuf[pos]; + if ((irq >> 31) == gen) + break; + if (irq == ref) + cnt++; + pos = (pos + 1) & xs->eqmsk; + if (!pos) + gen ^= 1; + } + return cnt; +} +#else +static inline uint32_t xive_count_irq_copies(struct xive_cpu_state *xs __unused, + uint32_t ref __unused) +{ + return 1; +} +#endif + static uint32_t xive_read_eq(struct xive_cpu_state *xs, bool just_peek) { - uint32_t cur; + uint32_t cur, copies; xive_cpu_vdbg(this_cpu(), " EQ %s... IDX=%x MSK=%x G=%d\n", just_peek ? "peek" : "read", @@ -3042,6 +3077,28 @@ static uint32_t xive_read_eq(struct xive_cpu_state *xs, bool just_peek) xs->eqbuf[(xs->eqptr + 3) & xs->eqmsk]); if ((cur >> 31) == xs->eqgen) return 0; + + /* Debug: check for duplicate interrupts in the queue */ + copies = xive_count_irq_copies(xs, cur); + if (copies > 1) { + struct xive_eq *eq; + + prerror("Wow ! Dups of irq %x, found %d copies !\n", + cur & 0x7fffffff, copies); + prerror("[%08x > %08x %08x %08x %08x ...] eqgen=%x eqptr=%x jp=%d\n", + xs->eqbuf[(xs->eqptr - 1) & xs->eqmsk], + xs->eqbuf[(xs->eqptr + 0) & xs->eqmsk], + xs->eqbuf[(xs->eqptr + 1) & xs->eqmsk], + xs->eqbuf[(xs->eqptr + 2) & xs->eqmsk], + xs->eqbuf[(xs->eqptr + 3) & xs->eqmsk], + xs->eqgen, xs->eqptr, just_peek); + __xive_cache_scrub(xs->xive, xive_cache_eqc, xs->eq_blk, + xs->eq_idx + XIVE_EMULATION_PRIO, + false, false); + eq = xive_get_eq(xs->xive, xs->eq_idx + XIVE_EMULATION_PRIO); + prerror("EQ @%p W0=%08x W1=%08x qbuf @%p\n", + eq, eq->w0, eq->w1, xs->eqbuf); + } if (!just_peek) { xs->eqptr = (xs->eqptr + 1) & xs->eqmsk; if (xs->eqptr == 0) |