[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH, v3] 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@xxxxxxxxxx> --- 2010-05-04.orig/xen/arch/ia64/linux-xen/smp.c 2010-05-06 14:52:45.000000000 +0200 +++ 2010-05-04/xen/arch/ia64/linux-xen/smp.c 2010-05-06 11:20:40.000000000 +0200 @@ -94,6 +94,7 @@ static volatile struct call_data_struct #define IPI_CALL_FUNC 0 #define IPI_CPU_STOP 1 +#define IPI_STATE_DUMP 2 /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; @@ -202,6 +203,10 @@ handle_IPI (int irq, void *dev_id, struc stop_this_cpu(); break; + case IPI_STATE_DUMP: + dump_execstate(regs); + break; + default: printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which); break; @@ -479,6 +484,12 @@ smp_send_stop (void) send_IPI_allbutself(IPI_CPU_STOP); } +void +smp_send_state_dump (unsigned int cpu) +{ + send_IPI_single(cpu, IPI_STATE_DUMP); +} + int __init setup_profiling_timer (unsigned int multiplier) { --- 2010-05-04.orig/xen/arch/x86/smp.c 2010-05-06 14:52:45.000000000 +0200 +++ 2010-05-04/xen/arch/x86/smp.c 2010-05-06 11:21:07.000000000 +0200 @@ -375,11 +375,24 @@ void smp_send_nmi_allbutself(void) send_IPI_mask(&cpu_online_map, APIC_DM_NMI); } +void smp_send_state_dump(unsigned int cpu) +{ + state_dump_pending(cpu) = 1; + smp_send_event_check_cpu(cpu); +} + fastcall void smp_event_check_interrupt(struct cpu_user_regs *regs) { struct cpu_user_regs *old_regs = set_irq_regs(regs); ack_APIC_irq(); perfc_incr(ipis); + if ( unlikely(state_dump_pending(smp_processor_id())) ) + { + irq_enter(); + state_dump_pending(smp_processor_id()) = 0; + dump_execstate(regs); + irq_exit(); + } set_irq_regs(old_regs); } --- 2010-05-04.orig/xen/common/keyhandler.c 2010-05-04 13:21:53.000000000 +0200 +++ 2010-05-04/xen/common/keyhandler.c 2010-05-06 11:40:55.000000000 +0200 @@ -71,19 +71,52 @@ static struct keyhandler show_handlers_k .desc = "show this message" }; -static void __dump_execstate(void *unused) +#ifdef CONFIG_SMP +static cpumask_t dump_execstate_mask; +#endif + +void dump_execstate(struct cpu_user_regs *regs) { - dump_execution_state(); - printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id()); + unsigned int cpu = smp_processor_id(); + + if ( !guest_mode(regs) ) + { + printk("\n*** Dumping CPU%u host state: ***\n", cpu); + show_execution_state(regs); + } if ( is_idle_vcpu(current) ) - printk("No guest context (CPU is idle).\n"); + printk("No guest context (CPU%u is idle).\n", cpu); else + { + 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()); + } + +#ifdef CONFIG_SMP + 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); + else + { + printk("\n"); + + console_end_sync(); + watchdog_enable(); + } +#endif } static void dump_registers(unsigned char key, struct cpu_user_regs *regs) { +#ifdef CONFIG_SMP unsigned int cpu; +#endif /* We want to get everything out that we possibly can. */ watchdog_disable(); @@ -91,17 +124,28 @@ static void dump_registers(unsigned char printk("'%c' pressed -> dumping registers\n", key); +#ifdef CONFIG_SMP + if ( alt_key_handling ) + dump_execstate_mask = cpu_online_map; +#endif + /* 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); + +#ifdef CONFIG_SMP + if ( alt_key_handling ) + return; for_each_online_cpu ( cpu ) { 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); + cpu_set(cpu, dump_execstate_mask); + smp_send_state_dump(cpu); + while ( cpu_isset(cpu, dump_execstate_mask) ) + cpu_relax(); } +#endif printk("\n"); --- 2010-05-04.orig/xen/include/asm-ia64/linux-xen/asm/ptrace.h 2010-05-06 14:52:45.000000000 +0200 +++ 2010-05-04/xen/include/asm-ia64/linux-xen/asm/ptrace.h 2010-05-04 13:22:27.000000000 +0200 @@ -280,7 +280,7 @@ struct switch_stack { # define ia64_task_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1) # define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr) #ifdef XEN -# define guest_mode(regs) (ia64_psr(regs)->cpl != 0) +# define guest_mode(regs) (ia64_psr(regs)->cpl && !ia64_psr(regs)->vm) # define guest_kernel_mode(regs) (ia64_psr(regs)->cpl == CONFIG_CPL0_EMUL) # define vmx_guest_kernel_mode(regs) (ia64_psr(regs)->cpl == 0) # define regs_increment_iip(regs) \ --- 2010-05-04.orig/xen/include/asm-x86/hardirq.h 2010-05-06 14:52:57.000000000 +0200 +++ 2010-05-04/xen/include/asm-x86/hardirq.h 2010-05-06 14:54:55.000000000 +0200 @@ -9,6 +9,7 @@ typedef struct { unsigned int __local_irq_count; unsigned int __nmi_count; bool_t __mwait_wakeup; + bool_t __state_dump_pending; } __cacheline_aligned irq_cpustat_t; #include <xen/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ --- 2010-05-04.orig/xen/include/xen/irq_cpustat.h 2010-05-06 14:52:57.000000000 +0200 +++ 2010-05-04/xen/include/xen/irq_cpustat.h 2010-05-06 14:54:49.000000000 +0200 @@ -27,5 +27,6 @@ extern irq_cpustat_t irq_stat[]; #define local_irq_count(cpu) __IRQ_STAT((cpu), __local_irq_count) #define nmi_count(cpu) __IRQ_STAT((cpu), __nmi_count) #define mwait_wakeup(cpu) __IRQ_STAT((cpu), __mwait_wakeup) +#define state_dump_pending(cpu) __IRQ_STAT((cpu), __state_dump_pending) #endif /* __irq_cpustat_h */ --- 2010-05-04.orig/xen/include/xen/lib.h 2010-05-06 14:52:45.000000000 +0200 +++ 2010-05-04/xen/include/xen/lib.h 2010-05-06 11:17:03.000000000 +0200 @@ -111,4 +111,7 @@ extern int tainted; extern char *print_tainted(char *str); extern void add_taint(unsigned); +struct cpu_user_regs; +void dump_execstate(struct cpu_user_regs *); + #endif /* __LIB_H__ */ --- 2010-05-04.orig/xen/include/xen/smp.h 2010-05-04 13:22:06.000000000 +0200 +++ 2010-05-04/xen/include/xen/smp.h 2010-05-06 10:44:43.000000000 +0200 @@ -13,6 +13,8 @@ extern void smp_send_event_check_mask(co #define smp_send_event_check_cpu(cpu) \ smp_send_event_check_mask(cpumask_of(cpu)) +extern void smp_send_state_dump(unsigned int cpu); + /* * Prepare machine for booting other CPUs. */ Attachment:
dump-exec-state.patch _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |