]> xenbits.xensource.com Git - xen.git/commitdiff
x86/traps: prevent interleaving of concurrent cpu state dumps
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 11 Feb 2016 15:48:38 +0000 (16:48 +0100)
committerJan Beulich <jbeulich@suse.com>
Thu, 11 Feb 2016 15:48:38 +0000 (16:48 +0100)
If two cpus enter show_execution_state() concurrently, the resulting console
output interleaved, and of no help debugging the situation further.

As calls to these locations are rare and usually important, it is acceptable
to serialise them.  These codepaths are also on the terminal error paths, so
the console lock must be the lock used for serialisation, to allow
console_force_unlock() to function properly.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/traps.c
xen/drivers/char/console.c
xen/include/xen/console.h

index d19250a907167ed68d16241ed83894adb6b76583..ab7deee678c058d466230b7a24e8bacc2439b6f0 100644 (file)
@@ -416,12 +416,19 @@ void show_stack_overflow(unsigned int cpu, const struct cpu_user_regs *regs)
 
 void show_execution_state(const struct cpu_user_regs *regs)
 {
+    /* Prevent interleaving of output. */
+    unsigned long flags = console_lock_recursive_irqsave();
+
     show_registers(regs);
     show_stack(regs);
+
+    console_unlock_recursive_irqrestore(flags);
 }
 
 void vcpu_show_execution_state(struct vcpu *v)
 {
+    unsigned long flags;
+
     printk("*** Dumping Dom%d vcpu#%d state: ***\n",
            v->domain->domain_id, v->vcpu_id);
 
@@ -433,10 +440,15 @@ void vcpu_show_execution_state(struct vcpu *v)
 
     vcpu_pause(v); /* acceptably dangerous */
 
+    /* Prevent interleaving of output. */
+    flags = console_lock_recursive_irqsave();
+
     vcpu_show_registers(v);
     if ( guest_kernel_mode(v, &v->arch.user_regs) )
         show_guest_stack(v, &v->arch.user_regs);
 
+    console_unlock_recursive_irqrestore(flags);
+
     vcpu_unpause(v);
 }
 
index e0083f1cd47d2f878e8067ebd3ea1a877717fb5c..f4f61412d4d294b7f48e8ce21d2233b3ea15da69 100644 (file)
@@ -865,6 +865,22 @@ void console_end_log_everything(void)
     atomic_dec(&print_everything);
 }
 
+unsigned long console_lock_recursive_irqsave(void)
+{
+    unsigned long flags;
+
+    local_irq_save(flags);
+    spin_lock_recursive(&console_lock);
+
+    return flags;
+}
+
+void console_unlock_recursive_irqrestore(unsigned long flags)
+{
+    spin_unlock_recursive(&console_lock);
+    local_irq_restore(flags);
+}
+
 void console_force_unlock(void)
 {
     watchdog_disable();
index c7fd9ca8ea0859eb4fccd7f85871a518a1841e8b..ea06fd8078de6ab3dad1df9900ba894bca5035cf 100644 (file)
@@ -21,6 +21,8 @@ int console_has(const char *device);
 
 int fill_console_start_info(struct dom0_vga_console_info *);
 
+unsigned long console_lock_recursive_irqsave(void);
+void console_unlock_recursive_irqrestore(unsigned long flags);
 void console_force_unlock(void);
 
 void console_start_sync(void);