WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH, v3] reduce 'd' debug key's global impact
From: "Jan Beulich" <JBeulich@xxxxxxxxxx>
Date: Thu, 06 May 2010 14:05:41 +0100
Delivery-date: Thu, 06 May 2010 06:05:46 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>