ia64/xen-unstable

changeset 722:7a9d47fea66c

bitkeeper revision 1.428 (3f677454_j81KDQLm_L7AscjYn2nYg)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk
author iap10@labyrinth.cl.cam.ac.uk
date Tue Sep 16 20:36:36 2003 +0000 (2003-09-16)
parents 2c22db3e819b d0cdb9994a2b
children 115b02b108a1 efd1ad397eb3
files xen/arch/i386/entry.S xen/arch/i386/nmi.c xen/arch/i386/process.c xen/arch/i386/setup.c xen/arch/i386/traps.c xen/common/schedule.c xen/include/asm-i386/desc.h xen/include/xeno/sched.h
line diff
     1.1 --- a/xen/arch/i386/entry.S	Tue Sep 16 20:36:20 2003 +0000
     1.2 +++ b/xen/arch/i386/entry.S	Tue Sep 16 20:36:36 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	Tue Sep 16 20:36:20 2003 +0000
     2.2 +++ b/xen/arch/i386/nmi.c	Tue Sep 16 20:36:36 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/process.c	Tue Sep 16 20:36:20 2003 +0000
     3.2 +++ b/xen/arch/i386/process.c	Tue Sep 16 20:36:36 2003 +0000
     3.3 @@ -73,9 +73,8 @@ void cpu_idle (void)
     3.4  {
     3.5      int cpu = smp_processor_id();
     3.6  
     3.7 +    /* Just some sanity to ensure that the scheduler is set up okay. */
     3.8      ASSERT(current->domain == IDLE_DOMAIN_ID);
     3.9 -
    3.10 -    current->has_cpu = 1;
    3.11      (void)wake_up(current);
    3.12      schedule();
    3.13  
     4.1 --- a/xen/arch/i386/setup.c	Tue Sep 16 20:36:20 2003 +0000
     4.2 +++ b/xen/arch/i386/setup.c	Tue Sep 16 20:36:36 2003 +0000
     4.3 @@ -271,6 +271,8 @@ void __init cpu_init(void)
     4.4      mapcache[nr] = (unsigned long *)get_free_page(GFP_KERNEL);
     4.5      clear_page(mapcache[nr]);
     4.6      *pl2e = mk_l2_pgentry(__pa(mapcache[nr]) | PAGE_HYPERVISOR);
     4.7 +
     4.8 +    init_idle_task();
     4.9  }
    4.10  
    4.11  static void __init do_initcalls(void)
     5.1 --- a/xen/arch/i386/traps.c	Tue Sep 16 20:36:20 2003 +0000
     5.2 +++ b/xen/arch/i386/traps.c	Tue Sep 16 20:36:36 2003 +0000
     5.3 @@ -41,6 +41,10 @@ struct guest_trap_bounce {
     5.4      unsigned long  eip;               /*  12 */
     5.5  } guest_trap_bounce[NR_CPUS] = { { 0 } };
     5.6  
     5.7 +#define DOUBLEFAULT_STACK_SIZE 1024
     5.8 +static struct tss_struct doublefault_tss;
     5.9 +static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
    5.10 +
    5.11  asmlinkage int hypervisor_call(void);
    5.12  asmlinkage void lcall7(void);
    5.13  asmlinkage void lcall27(void);
    5.14 @@ -58,7 +62,6 @@ asmlinkage void overflow(void);
    5.15  asmlinkage void bounds(void);
    5.16  asmlinkage void invalid_op(void);
    5.17  asmlinkage void device_not_available(void);
    5.18 -asmlinkage void double_fault(void);
    5.19  asmlinkage void coprocessor_segment_overrun(void);
    5.20  asmlinkage void invalid_TSS(void);
    5.21  asmlinkage void segment_not_present(void);
    5.22 @@ -119,19 +122,17 @@ void show_stack(unsigned long * esp)
    5.23      unsigned long *stack;
    5.24      int i;
    5.25  
    5.26 -    // debugging aid: "show_stack(NULL);" prints the
    5.27 -    // back trace for this cpu.
    5.28 -
    5.29 -    if(esp==NULL)
    5.30 -        esp=(unsigned long*)&esp;
    5.31 +    if ( esp == NULL )
    5.32 +        esp = (unsigned long *)&esp;
    5.33  
    5.34      printk("Stack trace from ESP=%p:\n", esp);
    5.35  
    5.36      stack = esp;
    5.37 -    for(i=0; i < kstack_depth_to_print; i++) {
    5.38 -        if (((long) stack & (THREAD_SIZE-1)) == 0)
    5.39 +    for ( i = 0; i < kstack_depth_to_print; i++ )
    5.40 +    {
    5.41 +        if ( ((long)stack & (THREAD_SIZE-1)) == 0 )
    5.42              break;
    5.43 -        if (i && ((i % 8) == 0))
    5.44 +        if ( i && ((i % 8) == 0) )
    5.45              printk("\n       ");
    5.46          if ( kernel_text_address(*stack) )
    5.47              printk("[%08lx] ", *stack++);
    5.48 @@ -139,7 +140,6 @@ void show_stack(unsigned long * esp)
    5.49              printk("%08lx ", *stack++);            
    5.50      }
    5.51      printk("\n");
    5.52 -    //show_trace(esp);
    5.53  }
    5.54  
    5.55  void show_registers(struct pt_regs *regs)
    5.56 @@ -240,7 +240,6 @@ DO_ERROR_NOCODE( 4, "overflow", overflow
    5.57  DO_ERROR_NOCODE( 5, "bounds", bounds)
    5.58  DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
    5.59  DO_ERROR_NOCODE( 7, "device not available", device_not_available)
    5.60 -DO_ERROR( 8, "double fault", double_fault)
    5.61  DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
    5.62  DO_ERROR(10, "invalid TSS", invalid_TSS)
    5.63  DO_ERROR(11, "segment not present", segment_not_present)
    5.64 @@ -251,6 +250,38 @@ DO_ERROR(17, "alignment check", alignmen
    5.65  DO_ERROR_NOCODE(18, "machine check", machine_check)
    5.66  DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
    5.67  
    5.68 +asmlinkage void do_double_fault(void)
    5.69 +{
    5.70 +    extern spinlock_t console_lock;
    5.71 +    struct tss_struct *tss = &doublefault_tss;
    5.72 +    unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1;
    5.73 +
    5.74 +    /* Disable the NMI watchdog. It's useless now. */
    5.75 +    watchdog_on = 0;
    5.76 +
    5.77 +    /* Find information saved during fault and dump it to the console. */
    5.78 +    tss = &init_tss[cpu];
    5.79 +    printk("CPU:    %d\nEIP:    %04x:[<%08lx>]      \nEFLAGS: %08lx\n",
    5.80 +           cpu, tss->cs, tss->eip, tss->eflags);
    5.81 +    printk("CR3:    %08lx\n", tss->__cr3);
    5.82 +    printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
    5.83 +           tss->eax, tss->ebx, tss->ecx, tss->edx);
    5.84 +    printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
    5.85 +           tss->esi, tss->edi, tss->ebp, tss->esp);
    5.86 +    printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   ss: %04x\n",
    5.87 +           tss->ds, tss->es, tss->fs, tss->gs, tss->ss);
    5.88 +    printk("************************************\n");
    5.89 +    printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu);
    5.90 +    printk("System needs manual reset.\n");
    5.91 +    printk("************************************\n");
    5.92 +
    5.93 +    /* Lock up the console to prevent spurious output from other CPUs. */
    5.94 +    spin_lock(&console_lock); 
    5.95 +
    5.96 +    /* Wait for manual reset. */
    5.97 +    for ( ; ; ) ;
    5.98 +}
    5.99 +
   5.100  asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
   5.101  {
   5.102      struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
   5.103 @@ -603,6 +634,12 @@ static void __init set_system_gate(unsig
   5.104      _set_gate(idt_table+n,14,3,addr);
   5.105  }
   5.106  
   5.107 +static void set_task_gate(unsigned int n, unsigned int sel)
   5.108 +{
   5.109 +    idt_table[n].a = sel << 16;
   5.110 +    idt_table[n].b = 0x8500;
   5.111 +}
   5.112 +
   5.113  #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
   5.114  	*((gate_addr)+1) = ((base) & 0xff000000) | \
   5.115  		(((base) & 0x00ff0000)>>16) | \
   5.116 @@ -632,6 +669,25 @@ void set_tss_desc(unsigned int n, void *
   5.117  void __init trap_init(void)
   5.118  {
   5.119      /*
   5.120 +     * Make a separate task for double faults. This will get us debug output if
   5.121 +     * we blow the kernel stack.
   5.122 +     */
   5.123 +    struct tss_struct *tss = &doublefault_tss;
   5.124 +    memset(tss, 0, sizeof(*tss));
   5.125 +    tss->ds     = __HYPERVISOR_DS;
   5.126 +    tss->es     = __HYPERVISOR_DS;
   5.127 +    tss->ss     = __HYPERVISOR_DS;
   5.128 +    tss->esp    = (unsigned long)
   5.129 +        &doublefault_stack[DOUBLEFAULT_STACK_SIZE];
   5.130 +    tss->__cr3  = __pa(idle0_pg_table);
   5.131 +    tss->cs     = __HYPERVISOR_CS;
   5.132 +    tss->eip    = (unsigned long)do_double_fault;
   5.133 +    tss->eflags = 2;
   5.134 +    tss->bitmap = INVALID_IO_BITMAP_OFFSET;
   5.135 +    _set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY,
   5.136 +                     (int)tss, 235, 0x89);
   5.137 +
   5.138 +    /*
   5.139       * Note that interrupt gates are always used, rather than trap gates. We 
   5.140       * must have interrupts disabled until DS/ES/FS/GS are saved because the 
   5.141       * first activation must have the "bad" value(s) for these registers and 
   5.142 @@ -647,7 +703,7 @@ void __init trap_init(void)
   5.143      set_intr_gate(5,&bounds);
   5.144      set_intr_gate(6,&invalid_op);
   5.145      set_intr_gate(7,&device_not_available);
   5.146 -    set_intr_gate(8,&double_fault);
   5.147 +    set_task_gate(8,__DOUBLEFAULT_TSS_ENTRY<<3);
   5.148      set_intr_gate(9,&coprocessor_segment_overrun);
   5.149      set_intr_gate(10,&invalid_TSS);
   5.150      set_intr_gate(11,&segment_not_present);
     6.1 --- a/xen/common/schedule.c	Tue Sep 16 20:36:20 2003 +0000
     6.2 +++ b/xen/common/schedule.c	Tue Sep 16 20:36:36 2003 +0000
     6.3 @@ -1,22 +1,15 @@
     6.4  /* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
     6.5   ****************************************************************************
     6.6 - * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge
     6.7 + * (C) 2002-2003 - Rolf Neugebauer - Intel Research Cambridge
     6.8 + * (C) 2002-2003 University of Cambridge
     6.9   ****************************************************************************
    6.10   *
    6.11 - *        File: schedule.c
    6.12 - *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
    6.13 - *     Changes: 
    6.14 - *              
    6.15 - *        Date: Nov 2002
    6.16 + *        File: common/schedule.c
    6.17 + *      Author: Rolf Neugebar & Keir Fraser
    6.18   * 
    6.19 - * Environment: Xen Hypervisor
    6.20   * Description: CPU scheduling
    6.21   *              implements A Borrowed Virtual Time scheduler.
    6.22   *              (see Duda & Cheriton SOSP'99)
    6.23 - *
    6.24 - ****************************************************************************
    6.25 - * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
    6.26 - ****************************************************************************
    6.27   */
    6.28  
    6.29  #include <xeno/config.h>
    6.30 @@ -39,20 +32,16 @@
    6.31  #define TRC(_x)
    6.32  #endif
    6.33  
    6.34 -#define SCHED_HISTO
    6.35 +/*#define SCHED_HISTO*/
    6.36  #ifdef SCHED_HISTO
    6.37  #define BUCKETS 31
    6.38  #endif
    6.39  
    6.40 +#define MCU            (s32)MICROSECS(100)    /* Minimum unit */
    6.41 +#define MCU_ADVANCE    10                     /* default weight */
    6.42 +#define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */
    6.43 +static s32 ctx_allow = (s32)MILLISECS(5);     /* context switch allowance */
    6.44  
    6.45 -#define MCU          (s32)MICROSECS(100)    /* Minimum unit */
    6.46 -#define MCU_ADVANCE  10                     /* default weight */
    6.47 -#define TIME_SLOP    (s32)MICROSECS(50)     /* allow time to slip a bit */
    6.48 -static s32 ctx_allow=(s32)MILLISECS(5);     /* context switch allowance */
    6.49 -
    6.50 -/*****************************************************************************
    6.51 - * per CPU data for the scheduler.
    6.52 - *****************************************************************************/
    6.53  typedef struct schedule_data_st
    6.54  {
    6.55      spinlock_t          lock;           /* lock for protecting this */
    6.56 @@ -64,61 +53,59 @@ typedef struct schedule_data_st
    6.57  #ifdef SCHED_HISTO
    6.58      u32                 hist[BUCKETS];  /* for scheduler latency histogram */
    6.59  #endif
    6.60 -
    6.61  } __cacheline_aligned schedule_data_t;
    6.62  schedule_data_t schedule_data[NR_CPUS];
    6.63  
    6.64 -struct ac_timer     v_timer;        /* scheduling timer  */
    6.65 +struct ac_timer v_timer;        /* scheduling timer  */
    6.66  static void virt_timer(unsigned long foo);
    6.67  static void dump_rqueue(struct list_head *queue, char *name);
    6.68  
    6.69  
    6.70 -/*****************************************************************************
    6.71 - * Some convenience functions
    6.72 - *****************************************************************************/
    6.73 -/* add a task to the head of the runqueue */
    6.74  static inline void __add_to_runqueue_head(struct task_struct * p)
    6.75 -{
    6.76 -    
    6.77 +{    
    6.78      list_add(&p->run_list, &schedule_data[p->processor].runqueue);
    6.79  }
    6.80 -/* add a task to the tail of the runqueue */
    6.81 +
    6.82  static inline void __add_to_runqueue_tail(struct task_struct * p)
    6.83  {
    6.84      list_add_tail(&p->run_list, &schedule_data[p->processor].runqueue);
    6.85  }
    6.86  
    6.87 -/* remove a task from runqueue  */
    6.88  static inline void __del_from_runqueue(struct task_struct * p)
    6.89  {
    6.90      list_del(&p->run_list);
    6.91      p->run_list.next = NULL;
    6.92  }
    6.93 -/* is task on run queue?  */
    6.94 +
    6.95  static inline int __task_on_runqueue(struct task_struct *p)
    6.96  {
    6.97 -    return (p->run_list.next != NULL);
    6.98 +    return p->run_list.next != NULL;
    6.99  }
   6.100  
   6.101  #define next_domain(p) \\
   6.102          list_entry((p)->run_list.next, struct task_struct, run_list)
   6.103  
   6.104 -/* calculate evt  */
   6.105  static void __calc_evt(struct task_struct *p)
   6.106  {
   6.107      s_time_t now = NOW();
   6.108 -    if (p->warpback) {
   6.109 -        if (((now - p->warped) < p->warpl) &&
   6.110 -            ((now - p->uwarped) > p->warpu)) {
   6.111 +    if ( p->warpback ) 
   6.112 +    {
   6.113 +        if ( ((now - p->warped) < p->warpl) &&
   6.114 +             ((now - p->uwarped) > p->warpu) )
   6.115 +        {
   6.116              /* allowed to warp */
   6.117              p->evt = p->avt - p->warp;
   6.118 -        } else {
   6.119 +        } 
   6.120 +        else 
   6.121 +        {
   6.122              /* warped for too long -> unwarp */
   6.123              p->evt      = p->avt;
   6.124              p->uwarped  = now;
   6.125              p->warpback = 0;
   6.126          }
   6.127 -    } else {
   6.128 +    } 
   6.129 +    else 
   6.130 +    {
   6.131          p->evt = p->avt;
   6.132      }
   6.133  }
   6.134 @@ -132,11 +119,14 @@ void sched_add_domain(struct task_struct
   6.135      p->state       = TASK_SUSPENDED;
   6.136      p->mcu_advance = MCU_ADVANCE;
   6.137  
   6.138 -    if (p->domain == IDLE_DOMAIN_ID) {
   6.139 +    if ( p->domain == IDLE_DOMAIN_ID )
   6.140 +    {
   6.141          p->avt = 0xffffffff;
   6.142          p->evt = 0xffffffff;
   6.143          schedule_data[p->processor].idle = p;
   6.144 -    } else {
   6.145 +    } 
   6.146 +    else 
   6.147 +    {
   6.148          /* set avt end evt to system virtual time */
   6.149          p->avt         = schedule_data[p->processor].svt;
   6.150          p->evt         = schedule_data[p->processor].svt;
   6.151 @@ -154,6 +144,19 @@ void sched_rem_domain(struct task_struct
   6.152  }
   6.153  
   6.154  
   6.155 +void init_idle_task(void)
   6.156 +{
   6.157 +    unsigned long flags;
   6.158 +    struct task_struct *p = current;
   6.159 +    spin_lock_irqsave(&schedule_data[p->processor].lock, flags);
   6.160 +    p->has_cpu = 1;
   6.161 +    p->state = TASK_RUNNING;
   6.162 +    if ( !__task_on_runqueue(p) )
   6.163 +        __add_to_runqueue_head(p);
   6.164 +    spin_unlock_irqrestore(&schedule_data[p->processor].lock, flags);
   6.165 +}
   6.166 +
   6.167 +
   6.168  /****************************************************************************
   6.169   * wake up a domain which had been sleeping
   6.170   ****************************************************************************/
     7.1 --- a/xen/include/asm-i386/desc.h	Tue Sep 16 20:36:20 2003 +0000
     7.2 +++ b/xen/include/asm-i386/desc.h	Tue Sep 16 20:36:36 2003 +0000
     7.3 @@ -3,6 +3,8 @@
     7.4  
     7.5  #define LDT_ENTRY_SIZE 8
     7.6  
     7.7 +#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
     7.8 +
     7.9  #define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
    7.10  #define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1)
    7.11  
     8.1 --- a/xen/include/xeno/sched.h	Tue Sep 16 20:36:20 2003 +0000
     8.2 +++ b/xen/include/xeno/sched.h	Tue Sep 16 20:36:36 2003 +0000
     8.3 @@ -271,6 +271,7 @@ void sched_rem_domain(struct task_struct
     8.4  long sched_bvtctl(unsigned long ctx_allow);
     8.5  long sched_adjdom(int dom, unsigned long mcu_adv, unsigned long warp, 
     8.6                    unsigned long warpl, unsigned long warpu);
     8.7 +void init_idle_task(void);
     8.8  int  wake_up(struct task_struct *p);
     8.9  long schedule_timeout(long timeout);
    8.10  long do_yield(void);