[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH, v3] reduce 'd' debug key's global impact



Given the abstraction you created, I decided it was best to put the x86
implementation of smp_send_state_dump() in the spurious-interrupt handler.
Also I changed the keyhandler.c changes around a bunch and removed the
needless CONFIG_SMP ifdefs. I checked the result in as xen-unstable:21309.

 Thanks,
 Keir

On 06/05/2010 14:05, "Jan Beulich" <JBeulich@xxxxxxxxxx> wrote:

> 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.
>   */
> 
> 



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.