]> xenbits.xensource.com Git - xen.git/commitdiff
xen x86: Fix double-fault handler stack overflow.
authorKeir Fraser <keir@xensource.com>
Sat, 31 Mar 2007 15:35:02 +0000 (16:35 +0100)
committerKeir Fraser <keir@xensource.com>
Sat, 31 Mar 2007 15:35:02 +0000 (16:35 +0100)
 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>
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

index e1adce3b9eb919055122ba46494e37f6d7961edc..99a332b874c69b4cac3296266a5d470bb67a58da 100644 (file)
@@ -291,7 +291,7 @@ void show_stack_overflow(unsigned long esp)
     unsigned long esp_top;
     unsigned long *stack, addr;
 
-    esp_top = (esp | (STACK_SIZE - 1)) - DEBUG_STACK_SIZE;
+    esp_top = (esp | (STACK_SIZE - 1)) - (DEBUG_STACK_SIZE - 1);
 
     /* Trigger overflow trace if %esp is within 512 bytes of the guard page. */
     if ( ((unsigned long)(esp - esp_top) > 512) &&
index fe22212dd460c7c2a9a438a42886c1d9eecd28fd..da8ca6bf5c1bf5d85ed9532b4e405538351a7e65 100644 (file)
@@ -139,7 +139,7 @@ void show_page_walk(unsigned long addr)
     unmap_domain_page(l1t);
 }
 
-#define DOUBLEFAULT_STACK_SIZE 1024
+#define DOUBLEFAULT_STACK_SIZE 2048
 static struct tss_struct doublefault_tss;
 static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
 
@@ -268,8 +268,7 @@ void __init percpu_traps_init(void)
     tss->ds     = __HYPERVISOR_DS;
     tss->es     = __HYPERVISOR_DS;
     tss->ss     = __HYPERVISOR_DS;
-    tss->esp    = (unsigned long)
-        &doublefault_stack[DOUBLEFAULT_STACK_SIZE];
+    tss->esp    = (unsigned long)&doublefault_stack[DOUBLEFAULT_STACK_SIZE];
     tss->__cr3  = __pa(idle_pg_table);
     tss->cs     = __HYPERVISOR_CS;
     tss->eip    = (unsigned long)do_double_fault;
index dbdb47b65ea0f956d3b58a07a8fd2a5592b2084d..9e4502e93499cc1cfbf30dde77076500492f7bf6 100644 (file)
@@ -270,18 +270,18 @@ void __init percpu_traps_init(void)
     stack_bottom = (char *)get_stack_bottom();
     stack        = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1));
 
-    /* Double-fault handler has its own per-CPU 1kB stack. */
-    init_tss[cpu].ist[0] = (unsigned long)&stack[1024];
+    /* Double-fault handler has its own per-CPU 2kB stack. */
+    init_tss[cpu].ist[0] = (unsigned long)&stack[2048];
 
     /* NMI handler has its own per-CPU 1kB stack. */
-    init_tss[cpu].ist[1] = (unsigned long)&stack[2048];
+    init_tss[cpu].ist[1] = (unsigned long)&stack[3072];
 
     /*
      * Trampoline for SYSCALL entry from long mode.
      */
 
     /* Skip the NMI and DF stacks. */
-    stack = &stack[2048];
+    stack = &stack[3072];
     wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
 
     /* movq %rsp, saversp(%rip) */
index f4134b7ed5e525e3bddc1ffd61e54c951597927a..60f3c335a695516a8d52fdefb891b000b623e07f 100644 (file)
@@ -16,6 +16,7 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/string.h>
+#include <xen/spinlock.h>
 
 extern unsigned long symbols_addresses[];
 extern unsigned long symbols_num_syms;
@@ -140,12 +141,15 @@ const char *symbols_lookup(unsigned long addr,
 void __print_symbol(const char *fmt, unsigned long address)
 {
     const char *name;
-    unsigned long offset, size;
-    char namebuf[KSYM_NAME_LEN+1];
+    unsigned long offset, size, flags;
 
+    static DEFINE_SPINLOCK(lock);
+    static char namebuf[KSYM_NAME_LEN+1];
 #define BUFFER_SIZE sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \
                        2*(BITS_PER_LONG*3/10) + 1
-    char buffer[BUFFER_SIZE];
+    static char buffer[BUFFER_SIZE];
+
+    spin_lock_irqsave(&lock, flags);
 
     name = symbols_lookup(address, &size, &offset, namebuf);
 
@@ -155,4 +159,6 @@ void __print_symbol(const char *fmt, unsigned long address)
         snprintf(buffer, BUFFER_SIZE, "%s+%#lx/%#lx", name, offset, size);
 
     printk(fmt, buffer);
+
+    spin_unlock_irqrestore(&lock, flags);
 }
index 87786f152fad1c109ba270b12a251133d732db1e..d35a4c880926825648c91b0cedd4198b37e9ce86 100644 (file)
@@ -858,19 +858,20 @@ __initcall(debugtrace_init);
 void panic(const char *fmt, ...)
 {
     va_list args;
-    char buf[128];
     unsigned long flags;
     static DEFINE_SPINLOCK(lock);
+    static char buf[128];
     
     debugtrace_dump();
 
+    /* Protects buf[] and ensure multi-line message prints atomically. */
+    spin_lock_irqsave(&lock, flags);
+
     va_start(args, fmt);
     (void)vsnprintf(buf, sizeof(buf), fmt, args);
     va_end(args);
 
-    /* Spit out multiline message in one go. */
     console_start_sync();
-    spin_lock_irqsave(&lock, flags);
     printk("\n****************************************\n");
     printk("Panic on CPU %d:\n", smp_processor_id());
     printk(buf);
@@ -879,6 +880,7 @@ void panic(const char *fmt, ...)
         printk("Manual reset required ('noreboot' specified)\n");
     else
         printk("Reboot in five seconds...\n");
+
     spin_unlock_irqrestore(&lock, flags);
 
     debugger_trap_immediate();