]> xenbits.xensource.com Git - xtf.git/commitdiff
Run double faults on a separate stack
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 14 Oct 2016 14:51:18 +0000 (14:51 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 18 Oct 2016 13:17:48 +0000 (14:17 +0100)
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 <andrew.cooper3@citrix.com>
arch/x86/hvm/traps.c
arch/x86/setup.c
include/arch/x86/segment.h
include/arch/x86/traps.h

index b957fe1a1c34b77721a0b324a91ac6564609754b..3cd4a3b0bb938f582256c5633cc94b8650353e95 100644 (file)
@@ -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);
index b07481480c9aea8dfdb7e19b5189991e5b738930..ea44167a61065029e0ef0d3e14bc61c783094ac3 100644 (file)
 /*
  * 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;
index a251a74a11a9d438e8f4d78ae1322587a701fe56..9b33a4e3678e2357c0f3e4c1d4860fce3b096521 100644 (file)
@@ -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
index 48687f6135eb3467dbba417d2ec68593a8bd4d70..52dff571753fe9399697ac0a1682b93fbfa9991f 100644 (file)
@@ -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 <xen/xen.h>