direct-io.hg

changeset 14683:3a0b808d917a

xen x86: Fix double-fault handler stack overflow.
1. Shrink stack frame for __print_symbol() by introducing a lock and
making the big arrays static.
2. Double the size of the double-fault stack.

Also fix the show_stack_overflow function.

Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Sat Mar 31 16:35:02 2007 +0100 (2007-03-31)
parents fbe52b559161
children f4c721dae13a
files xen/arch/x86/traps.c xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/traps.c xen/common/symbols.c xen/drivers/char/console.c
line diff
     1.1 --- a/xen/arch/x86/traps.c	Sat Mar 31 14:05:57 2007 +0100
     1.2 +++ b/xen/arch/x86/traps.c	Sat Mar 31 16:35:02 2007 +0100
     1.3 @@ -291,7 +291,7 @@ void show_stack_overflow(unsigned long e
     1.4      unsigned long esp_top;
     1.5      unsigned long *stack, addr;
     1.6  
     1.7 -    esp_top = (esp | (STACK_SIZE - 1)) - DEBUG_STACK_SIZE;
     1.8 +    esp_top = (esp | (STACK_SIZE - 1)) - (DEBUG_STACK_SIZE - 1);
     1.9  
    1.10      /* Trigger overflow trace if %esp is within 512 bytes of the guard page. */
    1.11      if ( ((unsigned long)(esp - esp_top) > 512) &&
     2.1 --- a/xen/arch/x86/x86_32/traps.c	Sat Mar 31 14:05:57 2007 +0100
     2.2 +++ b/xen/arch/x86/x86_32/traps.c	Sat Mar 31 16:35:02 2007 +0100
     2.3 @@ -139,7 +139,7 @@ void show_page_walk(unsigned long addr)
     2.4      unmap_domain_page(l1t);
     2.5  }
     2.6  
     2.7 -#define DOUBLEFAULT_STACK_SIZE 1024
     2.8 +#define DOUBLEFAULT_STACK_SIZE 2048
     2.9  static struct tss_struct doublefault_tss;
    2.10  static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
    2.11  
    2.12 @@ -268,8 +268,7 @@ void __init percpu_traps_init(void)
    2.13      tss->ds     = __HYPERVISOR_DS;
    2.14      tss->es     = __HYPERVISOR_DS;
    2.15      tss->ss     = __HYPERVISOR_DS;
    2.16 -    tss->esp    = (unsigned long)
    2.17 -        &doublefault_stack[DOUBLEFAULT_STACK_SIZE];
    2.18 +    tss->esp    = (unsigned long)&doublefault_stack[DOUBLEFAULT_STACK_SIZE];
    2.19      tss->__cr3  = __pa(idle_pg_table);
    2.20      tss->cs     = __HYPERVISOR_CS;
    2.21      tss->eip    = (unsigned long)do_double_fault;
     3.1 --- a/xen/arch/x86/x86_64/traps.c	Sat Mar 31 14:05:57 2007 +0100
     3.2 +++ b/xen/arch/x86/x86_64/traps.c	Sat Mar 31 16:35:02 2007 +0100
     3.3 @@ -270,18 +270,18 @@ void __init percpu_traps_init(void)
     3.4      stack_bottom = (char *)get_stack_bottom();
     3.5      stack        = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1));
     3.6  
     3.7 -    /* Double-fault handler has its own per-CPU 1kB stack. */
     3.8 -    init_tss[cpu].ist[0] = (unsigned long)&stack[1024];
     3.9 +    /* Double-fault handler has its own per-CPU 2kB stack. */
    3.10 +    init_tss[cpu].ist[0] = (unsigned long)&stack[2048];
    3.11  
    3.12      /* NMI handler has its own per-CPU 1kB stack. */
    3.13 -    init_tss[cpu].ist[1] = (unsigned long)&stack[2048];
    3.14 +    init_tss[cpu].ist[1] = (unsigned long)&stack[3072];
    3.15  
    3.16      /*
    3.17       * Trampoline for SYSCALL entry from long mode.
    3.18       */
    3.19  
    3.20      /* Skip the NMI and DF stacks. */
    3.21 -    stack = &stack[2048];
    3.22 +    stack = &stack[3072];
    3.23      wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
    3.24  
    3.25      /* movq %rsp, saversp(%rip) */
     4.1 --- a/xen/common/symbols.c	Sat Mar 31 14:05:57 2007 +0100
     4.2 +++ b/xen/common/symbols.c	Sat Mar 31 16:35:02 2007 +0100
     4.3 @@ -16,6 +16,7 @@
     4.4  #include <xen/init.h>
     4.5  #include <xen/lib.h>
     4.6  #include <xen/string.h>
     4.7 +#include <xen/spinlock.h>
     4.8  
     4.9  extern unsigned long symbols_addresses[];
    4.10  extern unsigned long symbols_num_syms;
    4.11 @@ -140,12 +141,15 @@ const char *symbols_lookup(unsigned long
    4.12  void __print_symbol(const char *fmt, unsigned long address)
    4.13  {
    4.14      const char *name;
    4.15 -    unsigned long offset, size;
    4.16 -    char namebuf[KSYM_NAME_LEN+1];
    4.17 +    unsigned long offset, size, flags;
    4.18  
    4.19 +    static DEFINE_SPINLOCK(lock);
    4.20 +    static char namebuf[KSYM_NAME_LEN+1];
    4.21  #define BUFFER_SIZE sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \
    4.22  			2*(BITS_PER_LONG*3/10) + 1
    4.23 -    char buffer[BUFFER_SIZE];
    4.24 +    static char buffer[BUFFER_SIZE];
    4.25 +
    4.26 +    spin_lock_irqsave(&lock, flags);
    4.27  
    4.28      name = symbols_lookup(address, &size, &offset, namebuf);
    4.29  
    4.30 @@ -155,4 +159,6 @@ void __print_symbol(const char *fmt, uns
    4.31          snprintf(buffer, BUFFER_SIZE, "%s+%#lx/%#lx", name, offset, size);
    4.32  
    4.33      printk(fmt, buffer);
    4.34 +
    4.35 +    spin_unlock_irqrestore(&lock, flags);
    4.36  }
     5.1 --- a/xen/drivers/char/console.c	Sat Mar 31 14:05:57 2007 +0100
     5.2 +++ b/xen/drivers/char/console.c	Sat Mar 31 16:35:02 2007 +0100
     5.3 @@ -858,19 +858,20 @@ static int __init debugtrace_init(void)
     5.4  void panic(const char *fmt, ...)
     5.5  {
     5.6      va_list args;
     5.7 -    char buf[128];
     5.8      unsigned long flags;
     5.9      static DEFINE_SPINLOCK(lock);
    5.10 +    static char buf[128];
    5.11      
    5.12      debugtrace_dump();
    5.13  
    5.14 +    /* Protects buf[] and ensure multi-line message prints atomically. */
    5.15 +    spin_lock_irqsave(&lock, flags);
    5.16 +
    5.17      va_start(args, fmt);
    5.18      (void)vsnprintf(buf, sizeof(buf), fmt, args);
    5.19      va_end(args);
    5.20  
    5.21 -    /* Spit out multiline message in one go. */
    5.22      console_start_sync();
    5.23 -    spin_lock_irqsave(&lock, flags);
    5.24      printk("\n****************************************\n");
    5.25      printk("Panic on CPU %d:\n", smp_processor_id());
    5.26      printk(buf);
    5.27 @@ -879,6 +880,7 @@ void panic(const char *fmt, ...)
    5.28          printk("Manual reset required ('noreboot' specified)\n");
    5.29      else
    5.30          printk("Reboot in five seconds...\n");
    5.31 +
    5.32      spin_unlock_irqrestore(&lock, flags);
    5.33  
    5.34      debugger_trap_immediate();