# HG changeset patch # User Keir Fraser # Date 1222088424 -3600 # Node ID 6d3b932cbecac19bf71d7be51e4f4489089ed753 # Parent 7f1a36b834e183904f069948d3037d50492d98d2 i386: make double fault TSS per-CPU 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 Index: xen-3.3.1-testing/xen/arch/x86/boot/x86_32.S =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/boot/x86_32.S +++ xen-3.3.1-testing/xen/arch/x86/boot/x86_32.S @@ -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: xen-3.3.1-testing/xen/arch/x86/smpboot.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/smpboot.c +++ xen-3.3.1-testing/xen/arch/x86/smpboot.c @@ -893,6 +893,13 @@ static int __devinit do_boot_cpu(int api = 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: xen-3.3.1-testing/xen/arch/x86/x86_32/traps.c =================================================================== --- xen-3.3.1-testing.orig/xen/arch/x86/x86_32/traps.c +++ xen-3.3.1-testing/xen/arch/x86/x86_32/traps.c @@ -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 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: xen-3.3.1-testing/xen/include/asm-x86/desc.h =================================================================== --- xen-3.3.1-testing.orig/xen/include/asm-x86/desc.h +++ xen-3.3.1-testing/xen/include/asm-x86/desc.h @@ -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 {