aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/keyhandler.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/common/keyhandler.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/common/keyhandler.c')
-rw-r--r--xen/common/keyhandler.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index 88ddd88f28..b4ceb627fc 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -71,14 +71,40 @@ static struct keyhandler show_handlers_keyhandler = {
.desc = "show this message"
};
-static void __dump_execstate(void *unused)
+static cpumask_t dump_execstate_mask;
+
+void dump_execstate(struct cpu_user_regs *regs)
{
- dump_execution_state();
- printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id());
- if ( is_idle_vcpu(current) )
- printk("No guest context (CPU is idle).\n");
- else
+ unsigned int cpu = smp_processor_id();
+
+ if ( !guest_mode(regs) )
+ {
+ printk("*** Dumping CPU%u host state: ***\n", cpu);
+ show_execution_state(regs);
+ }
+
+ if ( !is_idle_vcpu(current) )
+ {
+ printk("*** Dumping CPU%u guest state (d%d:v%d): ***\n",
+ smp_processor_id(), current->domain->domain_id,
+ current->vcpu_id);
show_execution_state(guest_cpu_user_regs());
+ printk("\n");
+ }
+
+ cpu_clear(cpu, dump_execstate_mask);
+ if ( !alt_key_handling )
+ return;
+
+ cpu = cycle_cpu(cpu, dump_execstate_mask);
+ if ( cpu < NR_CPUS )
+ {
+ smp_send_state_dump(cpu);
+ return;
+ }
+
+ console_end_sync();
+ watchdog_enable();
}
static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
@@ -89,22 +115,25 @@ static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
watchdog_disable();
console_start_sync();
- printk("'%c' pressed -> dumping registers\n", key);
+ printk("'%c' pressed -> dumping registers\n\n", key);
+
+ dump_execstate_mask = cpu_online_map;
/* Get local execution state out immediately, in case we get stuck. */
- printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id());
- __dump_execstate(NULL);
+ dump_execstate(regs);
- for_each_online_cpu ( cpu )
+ /* Alt. handling: remaining CPUs are dumped asynchronously one-by-one. */
+ if ( alt_key_handling )
+ return;
+
+ /* Normal handling: synchronously dump the remaining CPUs' states. */
+ for_each_cpu_mask ( cpu, dump_execstate_mask )
{
- if ( cpu == smp_processor_id() )
- continue;
- printk("\n*** Dumping CPU%d host state: ***\n", cpu);
- on_selected_cpus(cpumask_of(cpu), __dump_execstate, NULL, 1);
+ smp_send_state_dump(cpu);
+ while ( cpu_isset(cpu, dump_execstate_mask) )
+ cpu_relax();
}
- printk("\n");
-
console_end_sync();
watchdog_enable();
}