i386: make double fault TSS per-CPU
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 22 Sep 2008 13:00:24 +0000 (14:00 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 22 Sep 2008 13:00:24 +0000 (14:00 +0100)
As a follow-up to the per-CPU-GDT patch, this also makes the double
fault TSS (and the associated stack) per-CPU.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
xen/arch/x86/boot/x86_32.S
xen/arch/x86/smpboot.c
xen/arch/x86/x86_32/traps.c
xen/include/asm-x86/desc.h

index 2cabb18cf330a664074c4bdb62c1b25a82dc5eca..fa183db86cc9258949bc578296d0f3fcf5f6aae0 100644 (file)
@@ -95,7 +95,7 @@ ENTRY(idle_pg_table)
         .long ((MACH2PHYS_VIRT_END - 1) >> 12) & 0xffff,                \
               ((MACH2PHYS_VIRT_END - 1) >> 12) & (0xf << 16) | (d)
 ENTRY(boot_cpu_gdt_table)
-        .quad 0x0000000000000000     /* unused */
+        .quad 0x0000000000000000     /* double fault TSS */
         .quad 0x00cf9a000000ffff     /* 0xe008 ring 0 4.00GB code at 0x0 */
         .quad 0x00cf92000000ffff     /* 0xe010 ring 0 4.00GB data at 0x0 */
         GUEST_DESC(0x00c0ba00)       /* 0xe019 ring 1 3.xxGB code at 0x0 */
index 46ab83105d0b029b9b8c7e0e6cf58a4d001c681d..a09755feb9d0497cc674780e9e4a9a2b459c106f 100644 (file)
@@ -901,6 +901,13 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
                        = l1e_from_page(virt_to_page(gdt) + i,
                                        __PAGE_HYPERVISOR);
 
+#ifdef __i386__
+       if (!per_cpu(doublefault_tss, cpu)) {
+               per_cpu(doublefault_tss, cpu) = alloc_xenheap_page();
+               memset(per_cpu(doublefault_tss, cpu), 0, PAGE_SIZE);
+       }
+#endif
+
        /*
         * This grunge runs the startup process for
         * the targeted processor.
index 39977c42d1e79e7336c67c3c2828ae3770b3cb72..e3d716ec74730b19cfa852fbc33726ac3ee0e105 100644 (file)
@@ -188,9 +188,9 @@ void show_page_walk(unsigned long addr)
     unmap_domain_page(l1t);
 }
 
-#define DOUBLEFAULT_STACK_SIZE 2048
-static struct tss_struct doublefault_tss;
-static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
+DEFINE_PER_CPU(struct tss_struct *, doublefault_tss);
+static unsigned char __attribute__ ((__section__ (".bss.page_aligned")))
+    boot_cpu_doublefault_space[PAGE_SIZE];
 
 asmlinkage void do_double_fault(void)
 {
@@ -303,34 +303,36 @@ static void set_task_gate(unsigned int n, unsigned int sel)
 
 void __devinit subarch_percpu_traps_init(void)
 {
-    struct tss_struct *tss = &doublefault_tss;
+    struct tss_struct *tss = this_cpu(doublefault_tss);
     asmlinkage int hypercall(void);
 
-    if ( smp_processor_id() != 0 )
-        return;
+    if ( !tss )
+    {
+        /* The hypercall entry vector is only accessible from ring 1. */
+        _set_gate(idt_table+HYPERCALL_VECTOR, 14, 1, &hypercall);
 
-    /* The hypercall entry vector is only accessible from ring 1. */
-    _set_gate(idt_table+HYPERCALL_VECTOR, 14, 1, &hypercall);
+        tss = (void *)boot_cpu_doublefault_space;
+        this_cpu(doublefault_tss) = tss;
+    }
 
     /*
      * Make a separate task for double faults. This will get us debug output if
      * we blow the kernel stack.
      */
-    memset(tss, 0, sizeof(*tss));
     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)tss + PAGE_SIZE;
     tss->__cr3  = __pa(idle_pg_table);
     tss->cs     = __HYPERVISOR_CS;
     tss->eip    = (unsigned long)do_double_fault;
     tss->eflags = 2;
     tss->bitmap = IOBMP_INVALID_OFFSET;
     _set_tssldt_desc(
-        boot_cpu_gdt_table + __DOUBLEFAULT_TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
+        this_cpu(gdt_table) + DOUBLEFAULT_TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
         (unsigned long)tss, 235, 9);
 
-    set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3);
+    set_task_gate(TRAP_double_fault, DOUBLEFAULT_TSS_ENTRY << 3);
 }
 
 void init_int80_direct_trap(struct vcpu *v)
index 23491015133f8e4545decda97d7f40024ed8b87d..f59f372092d79293231677eb2cac107e9b1e841e 100644 (file)
@@ -47,7 +47,7 @@
 #define FLAT_COMPAT_USER_DS   FLAT_USER_DS
 #define FLAT_COMPAT_USER_SS   FLAT_USER_SS
 
-#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
+#define DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
 
 #define TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
 #define LDT_ENTRY (TSS_ENTRY + 1)
@@ -199,6 +199,8 @@ do {                                                     \
         (((u32)(addr) & 0x00FF0000U) >> 16);             \
 } while (0)
 
+DECLARE_PER_CPU(struct tss_struct *, doublefault_tss);
+
 #endif
 
 struct desc_ptr {