diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-05-06 17:00:08 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-05-06 17:00:08 +0100 |
commit | 5b6e351436e6f94797f0a92a8a478f38644fdaf6 (patch) | |
tree | 84b718f87e6f289adf1fb1cc8419e81d22fe00e5 /xen/common/keyhandler.c | |
parent | 08bbf1f316350aafa28c4c47fa3ed40414d6ad36 (diff) | |
download | xen-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.c | 61 |
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(); } |