From: Andrew Cooper Date: Fri, 14 Oct 2016 14:51:18 +0000 (+0000) Subject: Run double faults on a separate stack X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=e161cc3b0bde81a0f82a445735240596fdc2525e;p=xtf.git Run double faults on a separate stack For 64bit, use interrupt stack tables. For 32bit, use a task gate referring to a dedicated double fault TSS. This allows some situations to print error information rather than falling into a triple fault. Signed-off-by: Andrew Cooper --- diff --git a/arch/x86/hvm/traps.c b/arch/x86/hvm/traps.c index b957fe1..3cd4a3b 100644 --- a/arch/x86/hvm/traps.c +++ b/arch/x86/hvm/traps.c @@ -38,12 +38,32 @@ hw_tss tss __aligned(16) = #elif defined(__x86_64__) .rsp0 = (unsigned long)&boot_stack[2 * PAGE_SIZE], + .ist[0] = (unsigned long)&boot_stack[3 * PAGE_SIZE], #endif .iopb = X86_TSS_INVALID_IO_BITMAP, }; +#if defined(__i386__) +static hw_tss tss_DF __aligned(16) = +{ + .esp = (unsigned long)&boot_stack[3 * PAGE_SIZE], + .ss = __KERN_DS, + .ds = __KERN_DS, + .es = __KERN_DS, + .fs = __KERN_DS, + .gs = __KERN_DS, + + .eip = (unsigned long)&entry_DF, + .cs = __KERN_CS, + + .cr3 = (unsigned long)&cr3_target, + + .iopb = X86_TSS_INVALID_IO_BITMAP, +}; +#endif + void pack_gate32(struct seg_gate32 *gate, unsigned type, uint32_t func, unsigned dpl, unsigned seg) { @@ -82,6 +102,18 @@ static void setup_gate(unsigned int entry, void *addr, unsigned int dpl) #endif } +static void setup_doublefault(void) +{ +#if defined(__i386__) + gdt[GDTE_TSS_DF] = + (typeof(*gdt))INIT_GDTE((unsigned long)&tss_DF, 0x67, 0x89); + + pack_gate32(&idt[X86_EXC_DF], 5, 0, 0, GDTE_TSS_DF * 8); +#elif defined(__x86_64__) + pack_gate64(&idt[X86_EXC_DF], 14, (unsigned long)entry_DF, 0, 1, __KERN_CS); +#endif +} + int xtf_set_idte(unsigned int vector, struct xtf_idte *idte) { #if defined(__i386__) @@ -103,7 +135,7 @@ void arch_init_traps(void) setup_gate(X86_EXC_BR, &entry_BR, 0); setup_gate(X86_EXC_UD, &entry_UD, 0); setup_gate(X86_EXC_NM, &entry_NM, 0); - setup_gate(X86_EXC_DF, &entry_DF, 0); + setup_doublefault(); setup_gate(X86_EXC_TS, &entry_TS, 0); setup_gate(X86_EXC_NP, &entry_NP, 0); setup_gate(X86_EXC_SS, &entry_SS, 0); diff --git a/arch/x86/setup.c b/arch/x86/setup.c index b074814..ea44167 100644 --- a/arch/x86/setup.c +++ b/arch/x86/setup.c @@ -12,10 +12,11 @@ /* * XTF Stack layout: * + * boot_stack[page 3] Emergency entrypoint * boot_stack[page 2] Exception entrypoints * boot_stack[page 1] Top of work stack */ -uint8_t boot_stack[2 * PAGE_SIZE] __aligned(PAGE_SIZE); +uint8_t boot_stack[3 * PAGE_SIZE] __aligned(PAGE_SIZE); uint32_t x86_features[FSCAPINTS]; enum x86_vendor x86_vendor; unsigned int x86_family, x86_model, x86_stepping; diff --git a/include/arch/x86/segment.h b/include/arch/x86/segment.h index a251a74..9b33a4e 100644 --- a/include/arch/x86/segment.h +++ b/include/arch/x86/segment.h @@ -16,7 +16,8 @@ * 4 - 64bit userspace code * 5 - 32bit userspace code * 6 - 32bit userspace data - * 7 - TSS (two slots in long mode) + * 7/8 - TSS (two slots in long mode) + * 8 - DF TSS (32bit only) * * 9-12 - Available for test use */ @@ -29,6 +30,7 @@ #define GDTE_DS32_DPL3 6 #define GDTE_TSS 7 +#define GDTE_TSS_DF 8 #define GDTE_AVAIL0 9 #define GDTE_AVAIL1 10 diff --git a/include/arch/x86/traps.h b/include/arch/x86/traps.h index 48687f6..52dff57 100644 --- a/include/arch/x86/traps.h +++ b/include/arch/x86/traps.h @@ -23,7 +23,7 @@ void __noreturn arch_crash_hard(void); unsigned long cpu_regs_sp(const struct cpu_regs *regs); unsigned int cpu_regs_ss(const struct cpu_regs *regs); -extern uint8_t boot_stack[2 * PAGE_SIZE]; +extern uint8_t boot_stack[3 * PAGE_SIZE]; #if defined(CONFIG_PV) #include