aboutsummaryrefslogtreecommitdiffstats
path: root/xen
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-09-12 17:37:51 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-09-12 17:37:51 +0000
commitf9a8899e057af28352514a8e3a930b60f6aac893 (patch)
tree528e6d0ae7c6420ad47dcb03718572f61dc07e90 /xen
parentba7bd1f062b9d9d52aabc15b6412f2446e124697 (diff)
downloadxen-f9a8899e057af28352514a8e3a930b60f6aac893.tar.gz
xen-f9a8899e057af28352514a8e3a930b60f6aac893.tar.bz2
xen-f9a8899e057af28352514a8e3a930b60f6aac893.zip
bitkeeper revision 1.424.1.2 (3f62046f1f138hjcyAygLT-TQ0w_Zw)
desc.h, traps.c, nmi.c, entry.S: Execute double-fault handler in a separate task.
Diffstat (limited to 'xen')
-rw-r--r--xen/arch/i386/entry.S4
-rw-r--r--xen/arch/i386/nmi.c2
-rw-r--r--xen/arch/i386/traps.c80
-rw-r--r--xen/include/asm-i386/desc.h2
4 files changed, 71 insertions, 17 deletions
diff --git a/xen/arch/i386/entry.S b/xen/arch/i386/entry.S
index 1460cf77ed..84dda61578 100644
--- a/xen/arch/i386/entry.S
+++ b/xen/arch/i386/entry.S
@@ -590,10 +590,6 @@ ENTRY(coprocessor_segment_overrun)
pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
jmp error_code
-ENTRY(double_fault)
- pushl $ SYMBOL_NAME(do_double_fault)
- jmp error_code
-
ENTRY(invalid_TSS)
pushl $ SYMBOL_NAME(do_invalid_TSS)
jmp error_code
diff --git a/xen/arch/i386/nmi.c b/xen/arch/i386/nmi.c
index 7b338a98d9..a2555752ae 100644
--- a/xen/arch/i386/nmi.c
+++ b/xen/arch/i386/nmi.c
@@ -230,7 +230,7 @@ static int __pminit setup_p4_watchdog(void)
return 1;
}
-void __pminit setup_apic_nmi_watchdog (void)
+void __pminit setup_apic_nmi_watchdog(void)
{
if (!nmi_watchdog)
return;
diff --git a/xen/arch/i386/traps.c b/xen/arch/i386/traps.c
index 5109d01af2..6989c8bef6 100644
--- a/xen/arch/i386/traps.c
+++ b/xen/arch/i386/traps.c
@@ -41,6 +41,10 @@ struct guest_trap_bounce {
unsigned long eip; /* 12 */
} guest_trap_bounce[NR_CPUS] = { { 0 } };
+#define DOUBLEFAULT_STACK_SIZE 1024
+static struct tss_struct doublefault_tss;
+static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
+
asmlinkage int hypervisor_call(void);
asmlinkage void lcall7(void);
asmlinkage void lcall27(void);
@@ -58,7 +62,6 @@ asmlinkage void overflow(void);
asmlinkage void bounds(void);
asmlinkage void invalid_op(void);
asmlinkage void device_not_available(void);
-asmlinkage void double_fault(void);
asmlinkage void coprocessor_segment_overrun(void);
asmlinkage void invalid_TSS(void);
asmlinkage void segment_not_present(void);
@@ -119,19 +122,17 @@ void show_stack(unsigned long * esp)
unsigned long *stack;
int i;
- // debugging aid: "show_stack(NULL);" prints the
- // back trace for this cpu.
-
- if(esp==NULL)
- esp=(unsigned long*)&esp;
+ if ( esp == NULL )
+ esp = (unsigned long *)&esp;
printk("Stack trace from ESP=%p:\n", esp);
stack = esp;
- for(i=0; i < kstack_depth_to_print; i++) {
- if (((long) stack & (THREAD_SIZE-1)) == 0)
+ for ( i = 0; i < kstack_depth_to_print; i++ )
+ {
+ if ( ((long)stack & (THREAD_SIZE-1)) == 0 )
break;
- if (i && ((i % 8) == 0))
+ if ( i && ((i % 8) == 0) )
printk("\n ");
if ( kernel_text_address(*stack) )
printk("[%08lx] ", *stack++);
@@ -139,7 +140,6 @@ void show_stack(unsigned long * esp)
printk("%08lx ", *stack++);
}
printk("\n");
- //show_trace(esp);
}
void show_registers(struct pt_regs *regs)
@@ -240,7 +240,6 @@ DO_ERROR_NOCODE( 4, "overflow", overflow)
DO_ERROR_NOCODE( 5, "bounds", bounds)
DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
DO_ERROR_NOCODE( 7, "device not available", device_not_available)
-DO_ERROR( 8, "double fault", double_fault)
DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
DO_ERROR(10, "invalid TSS", invalid_TSS)
DO_ERROR(11, "segment not present", segment_not_present)
@@ -251,6 +250,38 @@ DO_ERROR(17, "alignment check", alignment_check)
DO_ERROR_NOCODE(18, "machine check", machine_check)
DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
+asmlinkage void do_double_fault(void)
+{
+ extern spinlock_t console_lock;
+ struct tss_struct *tss = &doublefault_tss;
+ unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1;
+
+ /* Disable the NMI watchdog. It's useless now. */
+ watchdog_on = 0;
+
+ /* Find information saved during fault and dump it to the console. */
+ tss = &init_tss[cpu];
+ printk("CPU: %d\nEIP: %04x:[<%08lx>] \nEFLAGS: %08lx\n",
+ cpu, tss->cs, tss->eip, tss->eflags);
+ printk("CR3: %08lx\n", tss->__cr3);
+ printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
+ tss->eax, tss->ebx, tss->ecx, tss->edx);
+ printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
+ tss->esi, tss->edi, tss->ebp, tss->esp);
+ printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
+ tss->ds, tss->es, tss->fs, tss->gs, tss->ss);
+ printk("************************************\n");
+ printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu);
+ printk("System needs manual reset.\n");
+ printk("************************************\n");
+
+ /* Lock up the console to prevent spurious output from other CPUs. */
+ spin_lock(&console_lock);
+
+ /* Wait for manual reset. */
+ for ( ; ; ) ;
+}
+
asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
{
struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
@@ -603,6 +634,12 @@ static void __init set_system_gate(unsigned int n, void *addr)
_set_gate(idt_table+n,14,3,addr);
}
+static void set_task_gate(unsigned int n, unsigned int sel)
+{
+ idt_table[n].a = sel << 16;
+ idt_table[n].b = 0x8500;
+}
+
#define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
*((gate_addr)+1) = ((base) & 0xff000000) | \
(((base) & 0x00ff0000)>>16) | \
@@ -632,6 +669,25 @@ void set_tss_desc(unsigned int n, void *addr)
void __init trap_init(void)
{
/*
+ * Make a separate task for double faults. This will get us debug output if
+ * we blow the kernel stack.
+ */
+ struct tss_struct *tss = &doublefault_tss;
+ 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->__cr3 = __pa(idle0_pg_table);
+ tss->cs = __HYPERVISOR_CS;
+ tss->eip = (unsigned long)do_double_fault;
+ tss->eflags = 2;
+ tss->bitmap = INVALID_IO_BITMAP_OFFSET;
+ _set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY,
+ (int)tss, 235, 0x89);
+
+ /*
* Note that interrupt gates are always used, rather than trap gates. We
* must have interrupts disabled until DS/ES/FS/GS are saved because the
* first activation must have the "bad" value(s) for these registers and
@@ -647,7 +703,7 @@ void __init trap_init(void)
set_intr_gate(5,&bounds);
set_intr_gate(6,&invalid_op);
set_intr_gate(7,&device_not_available);
- set_intr_gate(8,&double_fault);
+ set_task_gate(8,__DOUBLEFAULT_TSS_ENTRY<<3);
set_intr_gate(9,&coprocessor_segment_overrun);
set_intr_gate(10,&invalid_TSS);
set_intr_gate(11,&segment_not_present);
diff --git a/xen/include/asm-i386/desc.h b/xen/include/asm-i386/desc.h
index facb3a6452..c3b01d69d5 100644
--- a/xen/include/asm-i386/desc.h
+++ b/xen/include/asm-i386/desc.h
@@ -3,6 +3,8 @@
#define LDT_ENTRY_SIZE 8
+#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
+
#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1)