aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/apic.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-06 17:00:08 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-06 17:00:08 +0100
commit5b6e351436e6f94797f0a92a8a478f38644fdaf6 (patch)
tree84b718f87e6f289adf1fb1cc8419e81d22fe00e5 /xen/arch/x86/apic.c
parent08bbf1f316350aafa28c4c47fa3ed40414d6ad36 (diff)
downloadxen-5b6e351436e6f94797f0a92a8a478f38644fdaf6.tar.gz
xen-5b6e351436e6f94797f0a92a8a478f38644fdaf6.tar.bz2
xen-5b6e351436e6f94797f0a92a8a478f38644fdaf6.zip
Reduce 'd' debug key's global impact
On large systems, dumping state may cause time management to get stalled for so long a period that it wouldn't recover. Therefore alter the state dumping logic to alternatively block each CPU as it prints rather than one CPU for a very long time (using the alternative key handling toggle introduced with an earlier patch). Further, instead of using on_selected_cpus(), which is unsafe when the dumping happens from a hardware interrupt, introduce and use a dedicated IPI sending function (which each architecture can implement to its liking) Finally, don't print useless data (e.g. the hypervisor context of the interrupt that is used for triggering the printing, but isn't part of the context that's actually interesting). Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/arch/x86/apic.c')
-rw-r--r--xen/arch/x86/apic.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c
index 4c4a3de0d4..56d820ec03 100644
--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -1233,8 +1233,17 @@ fastcall void smp_apic_timer_interrupt(struct cpu_user_regs * regs)
set_irq_regs(old_regs);
}
+static DEFINE_PER_CPU(bool_t, state_dump_pending);
+
+void smp_send_state_dump(unsigned int cpu)
+{
+ /* We overload the spurious interrupt handler to handle the dump. */
+ per_cpu(state_dump_pending, cpu) = 1;
+ send_IPI_mask(cpumask_of(cpu), SPURIOUS_APIC_VECTOR);
+}
+
/*
- * This interrupt should _never_ happen with our APIC/SMP architecture
+ * Spurious interrupts should _never_ happen with our APIC/SMP architecture.
*/
fastcall void smp_spurious_interrupt(struct cpu_user_regs *regs)
{
@@ -1242,18 +1251,27 @@ fastcall void smp_spurious_interrupt(struct cpu_user_regs *regs)
struct cpu_user_regs *old_regs = set_irq_regs(regs);
irq_enter();
+
/*
- * Check if this really is a spurious interrupt and ACK it
- * if it is a vectored one. Just in case...
- * Spurious interrupts should not be ACKed.
+ * Check if this is a vectored interrupt (most likely, as this is probably
+ * a request to dump local CPU state). Vectored interrupts are ACKed;
+ * spurious interrupts are not.
*/
v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
- if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
+ if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) {
ack_APIC_irq();
+ if (this_cpu(state_dump_pending)) {
+ this_cpu(state_dump_pending) = 0;
+ dump_execstate(regs);
+ goto out;
+ }
+ }
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
- printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n",
- smp_processor_id());
+ printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should "
+ "never happen.\n", smp_processor_id());
+
+ out:
irq_exit();
set_irq_regs(old_regs);
}