direct-io.hg

changeset 6848:89fc07f85b01

First part of timer merge
Signed-off-by Kevin Tian <Kevin.tian@intel.com>
Signed-off-by Eddie Dong <Eddie.dong@intel.com>
author djm@kirby.fc.hp.com
date Tue Sep 06 16:49:01 2005 -0600 (2005-09-06)
parents 9361694781fc
children b2312c14f144
files xen/arch/ia64/xen/vcpu.c xen/arch/ia64/xen/xenmisc.c xen/arch/ia64/xen/xensetup.c xen/arch/ia64/xen/xentime.c
line diff
     1.1 --- a/xen/arch/ia64/xen/vcpu.c	Tue Sep 06 16:21:40 2005 -0600
     1.2 +++ b/xen/arch/ia64/xen/vcpu.c	Tue Sep 06 16:49:01 2005 -0600
     1.3 @@ -1032,6 +1032,8 @@ void vcpu_set_next_timer(VCPU *vcpu)
     1.4  
     1.5  	if (is_idle_task(vcpu->domain)) {
     1.6  		printf("****** vcpu_set_next_timer called during idle!!\n");
     1.7 +		vcpu_safe_set_itm(s);
     1.8 +		return;
     1.9  	}
    1.10  	//s = PSCBX(vcpu,xen_itm);
    1.11  	if (d && (d > now) && (d < s)) {
     2.1 --- a/xen/arch/ia64/xen/xenmisc.c	Tue Sep 06 16:21:40 2005 -0600
     2.2 +++ b/xen/arch/ia64/xen/xenmisc.c	Tue Sep 06 16:49:01 2005 -0600
     2.3 @@ -115,29 +115,6 @@ unsigned long __hypercall_create_continu
     2.4  #endif
     2.5  
     2.6  ///////////////////////////////
     2.7 -
     2.8 -///////////////////////////////
     2.9 -// from arch/x86/apic.c
    2.10 -///////////////////////////////
    2.11 -
    2.12 -extern unsigned long domain0_ready;
    2.13 -
    2.14 -int reprogram_ac_timer(s_time_t timeout)
    2.15 -{
    2.16 -	struct vcpu *v = current;
    2.17 -
    2.18 -#ifdef CONFIG_VTI
    2.19 -//	if(VMX_DOMAIN(v))
    2.20 -		return 1;
    2.21 -#endif // CONFIG_VTI
    2.22 -	if (!domain0_ready) return 1;
    2.23 -	local_cpu_data->itm_next = timeout;
    2.24 -	if (is_idle_task(v->domain)) vcpu_safe_set_itm(timeout);
    2.25 -	else vcpu_set_next_timer(current);
    2.26 -	return 1;
    2.27 -}
    2.28 -
    2.29 -///////////////////////////////
    2.30  // from arch/ia64/page_alloc.c
    2.31  ///////////////////////////////
    2.32  DEFINE_PER_CPU(struct page_state, page_states) = {0};
     3.1 --- a/xen/arch/ia64/xen/xensetup.c	Tue Sep 06 16:21:40 2005 -0600
     3.2 +++ b/xen/arch/ia64/xen/xensetup.c	Tue Sep 06 16:49:01 2005 -0600
     3.3 @@ -252,11 +252,8 @@ void start_kernel(void)
     3.4  printk("About to call scheduler_init()\n");
     3.5      scheduler_init();
     3.6      local_irq_disable();
     3.7 -printk("About to call xen_time_init()\n");
     3.8 -    xen_time_init();
     3.9 -#ifdef CONFIG_VTI
    3.10 +printk("About to call init_xen_time()\n");
    3.11      init_xen_time(); /* initialise the time */
    3.12 -#endif // CONFIG_VTI 
    3.13  printk("About to call ac_timer_init()\n");
    3.14      ac_timer_init();
    3.15  // init_xen_time(); ???
     4.1 --- a/xen/arch/ia64/xen/xentime.c	Tue Sep 06 16:21:40 2005 -0600
     4.2 +++ b/xen/arch/ia64/xen/xentime.c	Tue Sep 06 16:49:01 2005 -0600
     4.3 @@ -26,118 +26,78 @@
     4.4  #include <asm/sal.h>
     4.5  #include <asm/sections.h>
     4.6  #include <asm/system.h>
     4.7 -#ifdef XEN
     4.8  #include <asm/vcpu.h>
     4.9  #include <linux/jiffies.h>	// not included by xen/sched.h
    4.10 -#endif
    4.11  #include <xen/softirq.h>
    4.12  
    4.13 -#ifdef XEN
    4.14  seqlock_t xtime_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
    4.15 -#endif
    4.16  
    4.17  #define TIME_KEEPER_ID  0
    4.18 -extern unsigned long wall_jiffies;
    4.19 -
    4.20 -static s_time_t        stime_irq;       /* System time at last 'time update' */
    4.21 -
    4.22  unsigned long domain0_ready = 0;
    4.23 -
    4.24 -#ifndef CONFIG_VTI
    4.25 -static inline u64 get_time_delta(void)
    4.26 -{
    4.27 -	return ia64_get_itc();
    4.28 -}
    4.29 -#else // CONFIG_VTI
    4.30  static s_time_t        stime_irq = 0x0;       /* System time at last 'time update' */
    4.31 -unsigned long itc_scale;
    4.32 +unsigned long itc_scale, ns_scale;
    4.33  unsigned long itc_at_irq;
    4.34 -static unsigned long   wc_sec, wc_nsec; /* UTC time at last 'time update'.   */
    4.35 -//static rwlock_t        time_lock = RW_LOCK_UNLOCKED;
    4.36 -static irqreturn_t vmx_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs);
    4.37  
    4.38  static inline u64 get_time_delta(void)
    4.39  {
    4.40      s64      delta_itc;
    4.41 -    u64      delta, cur_itc;
    4.42 +    u64      cur_itc;
    4.43      
    4.44      cur_itc = ia64_get_itc();
    4.45  
    4.46      delta_itc = (s64)(cur_itc - itc_at_irq);
    4.47 +
    4.48 +    /* Ensure that the returned system time is monotonically increasing. */
    4.49      if ( unlikely(delta_itc < 0) ) delta_itc = 0;
    4.50 -    delta = ((u64)delta_itc) * itc_scale;
    4.51 -    delta = delta >> 32;
    4.52 -
    4.53 -    return delta;
    4.54 +    return cycle_to_ns(delta_itc);
    4.55  }
    4.56  
    4.57 -u64 tick_to_ns(u64 tick)
    4.58 +/* We don't expect an absolute cycle value here, since then no way
    4.59 + * to prevent overflow for large norminator. Normally this conversion
    4.60 + * is used for relative offset.
    4.61 + */
    4.62 +u64 cycle_to_ns(u64 cycle)
    4.63  {
    4.64 -    return (tick * itc_scale) >> 32;
    4.65 +    return (cycle * itc_scale) >> 32;
    4.66  }
    4.67 -#endif // CONFIG_VTI
    4.68 +
    4.69 +u64 ns_to_cycle(u64 ns)
    4.70 +{
    4.71 +    return (ns * ns_scale) >> 32;
    4.72 +}
    4.73  
    4.74  s_time_t get_s_time(void)
    4.75  {
    4.76      s_time_t now;
    4.77 -    unsigned long flags;
    4.78 -
    4.79 -    read_lock_irqsave(&xtime_lock, flags);
    4.80 -
    4.81 -    now = stime_irq + get_time_delta();
    4.82 +    unsigned long flags, seq;
    4.83  
    4.84 -    /* Ensure that the returned system time is monotonically increasing. */
    4.85 -    {
    4.86 -        static s_time_t prev_now = 0;
    4.87 -        if ( unlikely(now < prev_now) )
    4.88 -            now = prev_now;
    4.89 -        prev_now = now;
    4.90 -    }
    4.91 -
    4.92 -    read_unlock_irqrestore(&xtime_lock, flags);
    4.93 +    do {
    4.94 +	seq = read_seqbegin(&xtime_lock);
    4.95 +	now = stime_irq + get_time_delta();
    4.96 +    } while (unlikely(read_seqretry(&xtime_lock, seq)));
    4.97  
    4.98      return now; 
    4.99  }
   4.100  
   4.101  void update_dom_time(struct vcpu *v)
   4.102  {
   4.103 -// FIXME: implement this?
   4.104 -//	printf("update_dom_time: called, not implemented, skipping\n");
   4.105 -	return;
   4.106 +    /* N-op here, and let dom0 to manage system time directly */
   4.107 +    return;
   4.108  }
   4.109  
   4.110  /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
   4.111  void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
   4.112  {
   4.113 -#ifdef  CONFIG_VTI
   4.114 -    u64 _nsecs;
   4.115 -
   4.116 -    write_lock_irq(&xtime_lock);
   4.117 -
   4.118 -    _nsecs = (u64)nsecs + (s64)(stime_irq - system_time_base);
   4.119 -    while ( _nsecs >= 1000000000 ) 
   4.120 -    {
   4.121 -        _nsecs -= 1000000000;
   4.122 -        secs++;
   4.123 -    }
   4.124 -
   4.125 -    wc_sec  = secs;
   4.126 -    wc_nsec = (unsigned long)_nsecs;
   4.127 -
   4.128 -    write_unlock_irq(&xtime_lock);
   4.129 -
   4.130 -    update_dom_time(current->domain);
   4.131 -#else
   4.132 -// FIXME: Should this be do_settimeofday (from linux)???
   4.133 -	printf("do_settime: called, not implemented, stopping\n");
   4.134 -	dummy();
   4.135 -#endif
   4.136 +    /* If absolute system time is managed by dom0, there's no need for such
   4.137 +     * action since only virtual itc/itm service is provided.
   4.138 +     */
   4.139 +    return;
   4.140  }
   4.141  
   4.142  irqreturn_t
   4.143  xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
   4.144  {
   4.145 -	unsigned long new_itm;
   4.146 +	unsigned long new_itm, old_itc;
   4.147  
   4.148  #define HEARTBEAT_FREQ 16	// period in seconds
   4.149  #ifdef HEARTBEAT_FREQ
   4.150 @@ -150,12 +110,6 @@ xen_timer_interrupt (int irq, void *dev_
   4.151  		count = 0;
   4.152  	}
   4.153  #endif
   4.154 -#ifndef XEN
   4.155 -	if (unlikely(cpu_is_offline(smp_processor_id()))) {
   4.156 -		return IRQ_HANDLED;
   4.157 -	}
   4.158 -#endif
   4.159 -#ifdef XEN
   4.160  	if (current->domain == dom0) {
   4.161  		// FIXME: there's gotta be a better way of doing this...
   4.162  		// We have to ensure that domain0 is launched before we
   4.163 @@ -176,35 +130,12 @@ xen_timer_interrupt (int irq, void *dev_
   4.164  			vcpu_wake(current);
   4.165  		}
   4.166  	}
   4.167 -	raise_actimer_softirq();
   4.168 -#endif
   4.169 -
   4.170 -#ifndef XEN
   4.171 -	platform_timer_interrupt(irq, dev_id, regs);
   4.172 -#endif
   4.173 -
   4.174  	new_itm = local_cpu_data->itm_next;
   4.175  
   4.176  	if (!time_after(ia64_get_itc(), new_itm))
   4.177 -#ifdef XEN
   4.178  		return;
   4.179 -#else
   4.180 -		printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
   4.181 -		       ia64_get_itc(), new_itm);
   4.182 -#endif
   4.183 -
   4.184 -#ifdef XEN
   4.185 -//	printf("GOT TO HERE!!!!!!!!!!!\n");
   4.186 -	//while(1);
   4.187 -#else
   4.188 -	profile_tick(CPU_PROFILING, regs);
   4.189 -#endif
   4.190  
   4.191  	while (1) {
   4.192 -#ifndef XEN
   4.193 -		update_process_times(user_mode(regs));
   4.194 -#endif
   4.195 -
   4.196  		new_itm += local_cpu_data->itm_delta;
   4.197  
   4.198  		if (smp_processor_id() == TIME_KEEPER_ID) {
   4.199 @@ -221,6 +152,12 @@ xen_timer_interrupt (int irq, void *dev_
   4.200  			do_timer(regs);
   4.201  #endif
   4.202  			local_cpu_data->itm_next = new_itm;
   4.203 +
   4.204 +		 	/* Updates system time (nanoseconds since boot). */
   4.205 +			old_itc = itc_at_irq;
   4.206 +			itc_at_irq = ia64_get_itc();
   4.207 +			stime_irq += cycle_to_ns(itc_at_irq - old_itc);
   4.208 +
   4.209  #ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
   4.210  			write_sequnlock(&xtime_lock);
   4.211  #endif
   4.212 @@ -251,132 +188,65 @@ xen_timer_interrupt (int irq, void *dev_
   4.213  //#endif
   4.214  		/* double check, in case we got hit by a (slow) PMI: */
   4.215  	} while (time_after_eq(ia64_get_itc(), new_itm));
   4.216 +	raise_softirq(AC_TIMER_SOFTIRQ);
   4.217 +
   4.218  	return IRQ_HANDLED;
   4.219  }
   4.220  
   4.221  static struct irqaction xen_timer_irqaction = {
   4.222 -#ifdef CONFIG_VTI
   4.223 -	.handler =	vmx_timer_interrupt,
   4.224 -#else // CONFIG_VTI
   4.225  	.handler =	xen_timer_interrupt,
   4.226 -#endif // CONFIG_VTI
   4.227 -#ifndef XEN
   4.228 -	.flags =	SA_INTERRUPT,
   4.229 -#endif
   4.230  	.name =		"timer"
   4.231  };
   4.232  
   4.233  void __init
   4.234 -xen_time_init (void)
   4.235 +ia64_time_init (void)
   4.236  {
   4.237  	register_percpu_irq(IA64_TIMER_VECTOR, &xen_timer_irqaction);
   4.238  	ia64_init_itm();
   4.239  }
   4.240  
   4.241  
   4.242 -#ifdef CONFIG_VTI
   4.243 -
   4.244  /* Late init function (after all CPUs are booted). */
   4.245  int __init init_xen_time()
   4.246  {
   4.247      struct timespec tm;
   4.248  
   4.249 +    ia64_time_init();
   4.250      itc_scale  = 1000000000UL << 32 ;
   4.251      itc_scale /= local_cpu_data->itc_freq;
   4.252 +    ns_scale = (local_cpu_data->itc_freq << 32) / 1000000000UL;
   4.253  
   4.254      /* System time ticks from zero. */
   4.255      stime_irq = (s_time_t)0;
   4.256      itc_at_irq = ia64_get_itc();
   4.257  
   4.258 -    /* Wallclock time starts as the initial RTC time. */
   4.259 -    efi_gettimeofday(&tm);
   4.260 -    wc_sec  = tm.tv_sec;
   4.261 -    wc_nsec = tm.tv_nsec;
   4.262 -
   4.263 -
   4.264      printk("Time init:\n");
   4.265      printk(".... System Time: %ldns\n", NOW());
   4.266      printk(".... scale:       %16lX\n", itc_scale);
   4.267 -    printk(".... Wall Clock:  %lds %ldus\n", wc_sec, wc_nsec/1000);
   4.268  
   4.269      return 0;
   4.270  }
   4.271  
   4.272 -static irqreturn_t
   4.273 -vmx_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
   4.274 +int reprogram_ac_timer(s_time_t timeout)
   4.275  {
   4.276 -    unsigned long new_itm;
   4.277 -    struct vcpu *v = current;
   4.278 +	struct vcpu *v = current;
   4.279 +	s_time_t expire;
   4.280 +	unsigned long seq, cur_itc, itm_next;
   4.281 +
   4.282 +	if (!domain0_ready) return 1;
   4.283 +
   4.284 +	do {
   4.285 +		seq = read_seqbegin(&xtime_lock);
   4.286 +		if ((expire = timeout - NOW()) < 0)
   4.287 +			return 0;
   4.288 +
   4.289 +		cur_itc = ia64_get_itc();
   4.290 +		itm_next = cur_itc + ns_to_cycle(expire);
   4.291 +	} while (unlikely(read_seqretry(&xtime_lock, seq)));
   4.292 +
   4.293 +	local_cpu_data->itm_next = itm_next;
   4.294 +	vcpu_set_next_timer(current);
   4.295 +	return 1;
   4.296 +}
   4.297  
   4.298  
   4.299 -    new_itm = local_cpu_data->itm_next;
   4.300 -
   4.301 -    if (!time_after(ia64_get_itc(), new_itm))
   4.302 -        return;
   4.303 -
   4.304 -    while (1) {
   4.305 -#ifdef CONFIG_SMP
   4.306 -        /*
   4.307 -         * For UP, this is done in do_timer().  Weird, but
   4.308 -         * fixing that would require updates to all
   4.309 -         * platforms.
   4.310 -         */
   4.311 -        update_process_times(user_mode(v, regs));
   4.312 -#endif
   4.313 -        new_itm += local_cpu_data->itm_delta;
   4.314 -
   4.315 -        if (smp_processor_id() == TIME_KEEPER_ID) {
   4.316 -            /*
   4.317 -             * Here we are in the timer irq handler. We have irqs locally
   4.318 -             * disabled, but we don't know if the timer_bh is running on
   4.319 -             * another CPU. We need to avoid to SMP race by acquiring the
   4.320 -             * xtime_lock.
   4.321 -             */
   4.322 -            local_cpu_data->itm_next = new_itm;
   4.323 -            
   4.324 -            write_lock_irq(&xtime_lock);
   4.325 -            /* Update jiffies counter. */
   4.326 -            (*(unsigned long *)&jiffies_64)++;
   4.327 -
   4.328 -            /* Update wall time. */
   4.329 -            wc_nsec += 1000000000/HZ;
   4.330 -            if ( wc_nsec >= 1000000000 )
   4.331 -            {
   4.332 -                wc_nsec -= 1000000000;
   4.333 -                wc_sec++;
   4.334 -            }
   4.335 -
   4.336 -            /* Updates system time (nanoseconds since boot). */
   4.337 -            stime_irq += MILLISECS(1000/HZ);
   4.338 -            itc_at_irq = ia64_get_itc();
   4.339 -
   4.340 -            write_unlock_irq(&xtime_lock);
   4.341 -            
   4.342 -        } else
   4.343 -            local_cpu_data->itm_next = new_itm;
   4.344 -
   4.345 -        if (time_after(new_itm, ia64_get_itc()))
   4.346 -            break;
   4.347 -    }
   4.348 -
   4.349 -    do {
   4.350 -        /*
   4.351 -         * If we're too close to the next clock tick for
   4.352 -         * comfort, we increase the safety margin by
   4.353 -         * intentionally dropping the next tick(s).  We do NOT
   4.354 -         * update itm.next because that would force us to call
   4.355 -         * do_timer() which in turn would let our clock run
   4.356 -         * too fast (with the potentially devastating effect
   4.357 -         * of losing monotony of time).
   4.358 -         */
   4.359 -        while (!time_after(new_itm, ia64_get_itc() + local_cpu_data->itm_delta/2))
   4.360 -            new_itm += local_cpu_data->itm_delta;
   4.361 -        ia64_set_itm(new_itm);
   4.362 -        /* double check, in case we got hit by a (slow) PMI: */
   4.363 -    } while (time_after_eq(ia64_get_itc(), new_itm));
   4.364 -    raise_softirq(AC_TIMER_SOFTIRQ);
   4.365 -    
   4.366 -    return IRQ_HANDLED;
   4.367 -}
   4.368 -#endif // CONFIG_VTI
   4.369 -