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.
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