ia64/xen-unstable
changeset 719:d0cdb9994a2b
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.
desc.h, traps.c, nmi.c, entry.S:
Execute double-fault handler in a separate task.
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Fri Sep 12 17:37:51 2003 +0000 (2003-09-12) |
parents | ec38a236c5db |
children | 7a9d47fea66c |
files | xen/arch/i386/entry.S xen/arch/i386/nmi.c xen/arch/i386/traps.c xen/include/asm-i386/desc.h |
line diff
1.1 --- a/xen/arch/i386/entry.S Fri Sep 12 15:13:51 2003 +0000 1.2 +++ b/xen/arch/i386/entry.S Fri Sep 12 17:37:51 2003 +0000 1.3 @@ -590,10 +590,6 @@ ENTRY(coprocessor_segment_overrun) 1.4 pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun) 1.5 jmp error_code 1.6 1.7 -ENTRY(double_fault) 1.8 - pushl $ SYMBOL_NAME(do_double_fault) 1.9 - jmp error_code 1.10 - 1.11 ENTRY(invalid_TSS) 1.12 pushl $ SYMBOL_NAME(do_invalid_TSS) 1.13 jmp error_code
2.1 --- a/xen/arch/i386/nmi.c Fri Sep 12 15:13:51 2003 +0000 2.2 +++ b/xen/arch/i386/nmi.c Fri Sep 12 17:37:51 2003 +0000 2.3 @@ -230,7 +230,7 @@ static int __pminit setup_p4_watchdog(vo 2.4 return 1; 2.5 } 2.6 2.7 -void __pminit setup_apic_nmi_watchdog (void) 2.8 +void __pminit setup_apic_nmi_watchdog(void) 2.9 { 2.10 if (!nmi_watchdog) 2.11 return;
3.1 --- a/xen/arch/i386/traps.c Fri Sep 12 15:13:51 2003 +0000 3.2 +++ b/xen/arch/i386/traps.c Fri Sep 12 17:37:51 2003 +0000 3.3 @@ -41,6 +41,10 @@ struct guest_trap_bounce { 3.4 unsigned long eip; /* 12 */ 3.5 } guest_trap_bounce[NR_CPUS] = { { 0 } }; 3.6 3.7 +#define DOUBLEFAULT_STACK_SIZE 1024 3.8 +static struct tss_struct doublefault_tss; 3.9 +static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE]; 3.10 + 3.11 asmlinkage int hypervisor_call(void); 3.12 asmlinkage void lcall7(void); 3.13 asmlinkage void lcall27(void); 3.14 @@ -58,7 +62,6 @@ asmlinkage void overflow(void); 3.15 asmlinkage void bounds(void); 3.16 asmlinkage void invalid_op(void); 3.17 asmlinkage void device_not_available(void); 3.18 -asmlinkage void double_fault(void); 3.19 asmlinkage void coprocessor_segment_overrun(void); 3.20 asmlinkage void invalid_TSS(void); 3.21 asmlinkage void segment_not_present(void); 3.22 @@ -119,19 +122,17 @@ void show_stack(unsigned long * esp) 3.23 unsigned long *stack; 3.24 int i; 3.25 3.26 - // debugging aid: "show_stack(NULL);" prints the 3.27 - // back trace for this cpu. 3.28 - 3.29 - if(esp==NULL) 3.30 - esp=(unsigned long*)&esp; 3.31 + if ( esp == NULL ) 3.32 + esp = (unsigned long *)&esp; 3.33 3.34 printk("Stack trace from ESP=%p:\n", esp); 3.35 3.36 stack = esp; 3.37 - for(i=0; i < kstack_depth_to_print; i++) { 3.38 - if (((long) stack & (THREAD_SIZE-1)) == 0) 3.39 + for ( i = 0; i < kstack_depth_to_print; i++ ) 3.40 + { 3.41 + if ( ((long)stack & (THREAD_SIZE-1)) == 0 ) 3.42 break; 3.43 - if (i && ((i % 8) == 0)) 3.44 + if ( i && ((i % 8) == 0) ) 3.45 printk("\n "); 3.46 if ( kernel_text_address(*stack) ) 3.47 printk("[%08lx] ", *stack++); 3.48 @@ -139,7 +140,6 @@ void show_stack(unsigned long * esp) 3.49 printk("%08lx ", *stack++); 3.50 } 3.51 printk("\n"); 3.52 - //show_trace(esp); 3.53 } 3.54 3.55 void show_registers(struct pt_regs *regs) 3.56 @@ -240,7 +240,6 @@ DO_ERROR_NOCODE( 4, "overflow", overflow 3.57 DO_ERROR_NOCODE( 5, "bounds", bounds) 3.58 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op) 3.59 DO_ERROR_NOCODE( 7, "device not available", device_not_available) 3.60 -DO_ERROR( 8, "double fault", double_fault) 3.61 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun) 3.62 DO_ERROR(10, "invalid TSS", invalid_TSS) 3.63 DO_ERROR(11, "segment not present", segment_not_present) 3.64 @@ -251,6 +250,38 @@ DO_ERROR(17, "alignment check", alignmen 3.65 DO_ERROR_NOCODE(18, "machine check", machine_check) 3.66 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error) 3.67 3.68 +asmlinkage void do_double_fault(void) 3.69 +{ 3.70 + extern spinlock_t console_lock; 3.71 + struct tss_struct *tss = &doublefault_tss; 3.72 + unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1; 3.73 + 3.74 + /* Disable the NMI watchdog. It's useless now. */ 3.75 + watchdog_on = 0; 3.76 + 3.77 + /* Find information saved during fault and dump it to the console. */ 3.78 + tss = &init_tss[cpu]; 3.79 + printk("CPU: %d\nEIP: %04x:[<%08lx>] \nEFLAGS: %08lx\n", 3.80 + cpu, tss->cs, tss->eip, tss->eflags); 3.81 + printk("CR3: %08lx\n", tss->__cr3); 3.82 + printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", 3.83 + tss->eax, tss->ebx, tss->ecx, tss->edx); 3.84 + printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", 3.85 + tss->esi, tss->edi, tss->ebp, tss->esp); 3.86 + printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", 3.87 + tss->ds, tss->es, tss->fs, tss->gs, tss->ss); 3.88 + printk("************************************\n"); 3.89 + printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu); 3.90 + printk("System needs manual reset.\n"); 3.91 + printk("************************************\n"); 3.92 + 3.93 + /* Lock up the console to prevent spurious output from other CPUs. */ 3.94 + spin_lock(&console_lock); 3.95 + 3.96 + /* Wait for manual reset. */ 3.97 + for ( ; ; ) ; 3.98 +} 3.99 + 3.100 asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) 3.101 { 3.102 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id(); 3.103 @@ -603,6 +634,12 @@ static void __init set_system_gate(unsig 3.104 _set_gate(idt_table+n,14,3,addr); 3.105 } 3.106 3.107 +static void set_task_gate(unsigned int n, unsigned int sel) 3.108 +{ 3.109 + idt_table[n].a = sel << 16; 3.110 + idt_table[n].b = 0x8500; 3.111 +} 3.112 + 3.113 #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\ 3.114 *((gate_addr)+1) = ((base) & 0xff000000) | \ 3.115 (((base) & 0x00ff0000)>>16) | \ 3.116 @@ -632,6 +669,25 @@ void set_tss_desc(unsigned int n, void * 3.117 void __init trap_init(void) 3.118 { 3.119 /* 3.120 + * Make a separate task for double faults. This will get us debug output if 3.121 + * we blow the kernel stack. 3.122 + */ 3.123 + struct tss_struct *tss = &doublefault_tss; 3.124 + memset(tss, 0, sizeof(*tss)); 3.125 + tss->ds = __HYPERVISOR_DS; 3.126 + tss->es = __HYPERVISOR_DS; 3.127 + tss->ss = __HYPERVISOR_DS; 3.128 + tss->esp = (unsigned long) 3.129 + &doublefault_stack[DOUBLEFAULT_STACK_SIZE]; 3.130 + tss->__cr3 = __pa(idle0_pg_table); 3.131 + tss->cs = __HYPERVISOR_CS; 3.132 + tss->eip = (unsigned long)do_double_fault; 3.133 + tss->eflags = 2; 3.134 + tss->bitmap = INVALID_IO_BITMAP_OFFSET; 3.135 + _set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY, 3.136 + (int)tss, 235, 0x89); 3.137 + 3.138 + /* 3.139 * Note that interrupt gates are always used, rather than trap gates. We 3.140 * must have interrupts disabled until DS/ES/FS/GS are saved because the 3.141 * first activation must have the "bad" value(s) for these registers and 3.142 @@ -647,7 +703,7 @@ void __init trap_init(void) 3.143 set_intr_gate(5,&bounds); 3.144 set_intr_gate(6,&invalid_op); 3.145 set_intr_gate(7,&device_not_available); 3.146 - set_intr_gate(8,&double_fault); 3.147 + set_task_gate(8,__DOUBLEFAULT_TSS_ENTRY<<3); 3.148 set_intr_gate(9,&coprocessor_segment_overrun); 3.149 set_intr_gate(10,&invalid_TSS); 3.150 set_intr_gate(11,&segment_not_present);
4.1 --- a/xen/include/asm-i386/desc.h Fri Sep 12 15:13:51 2003 +0000 4.2 +++ b/xen/include/asm-i386/desc.h Fri Sep 12 17:37:51 2003 +0000 4.3 @@ -3,6 +3,8 @@ 4.4 4.5 #define LDT_ENTRY_SIZE 8 4.6 4.7 +#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY 4.8 + 4.9 #define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8) 4.10 #define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1) 4.11