diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-09-12 17:37:51 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-09-12 17:37:51 +0000 |
commit | f9a8899e057af28352514a8e3a930b60f6aac893 (patch) | |
tree | 528e6d0ae7c6420ad47dcb03718572f61dc07e90 /xen | |
parent | ba7bd1f062b9d9d52aabc15b6412f2446e124697 (diff) | |
download | xen-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.S | 4 | ||||
-rw-r--r-- | xen/arch/i386/nmi.c | 2 | ||||
-rw-r--r-- | xen/arch/i386/traps.c | 80 | ||||
-rw-r--r-- | xen/include/asm-i386/desc.h | 2 |
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) |