ia64/xen-unstable

changeset 18122:85a83b919653

x86: Reintroduce clocksource=tsc.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jul 21 10:39:15 2008 +0100 (2008-07-21)
parents a0ce4b040114
children c049e70af85f
files xen/arch/x86/time.c
line diff
     1.1 --- a/xen/arch/x86/time.c	Mon Jul 21 10:00:18 2008 +0100
     1.2 +++ b/xen/arch/x86/time.c	Mon Jul 21 10:39:15 2008 +0100
     1.3 @@ -481,6 +481,35 @@ static int init_pmtimer(struct platform_
     1.4  }
     1.5  
     1.6  /************************************************************
     1.7 + * PLATFORM TIMER 5: TSC
     1.8 + */
     1.9 +
    1.10 +static const char plt_tsc_name[] = "TSC";
    1.11 +#define platform_timer_is_tsc() (plt_src.name == plt_tsc_name)
    1.12 +
    1.13 +static int init_tsctimer(struct platform_timesource *pts)
    1.14 +{
    1.15 +    if ( !tsc_invariant )
    1.16 +        return 0;
    1.17 +
    1.18 +    pts->name = (char *)plt_tsc_name;
    1.19 +    return 1;
    1.20 +}
    1.21 +
    1.22 +static void make_tsctimer_record(void)
    1.23 +{
    1.24 +    struct cpu_time *t = &this_cpu(cpu_time);
    1.25 +    s_time_t now;
    1.26 +    u64 tsc;
    1.27 +
    1.28 +    rdtscll(tsc);
    1.29 +    now = scale_delta(tsc, &t->tsc_scale);
    1.30 +
    1.31 +    t->local_tsc_stamp = tsc;
    1.32 +    t->stime_local_stamp = t->stime_master_stamp = now;
    1.33 +}
    1.34 +
    1.35 +/************************************************************
    1.36   * GENERIC PLATFORM TIMER INFRASTRUCTURE
    1.37   */
    1.38  
    1.39 @@ -545,6 +574,12 @@ static void platform_time_calibration(vo
    1.40  
    1.41  static void resume_platform_timer(void)
    1.42  {
    1.43 +    if ( platform_timer_is_tsc() )
    1.44 +    {
    1.45 +        /* TODO: Save/restore TSC values. */
    1.46 +        return;
    1.47 +    }
    1.48 +
    1.49      /* No change in platform_stime across suspend/resume. */
    1.50      platform_timer_stamp = plt_stamp64;
    1.51      plt_stamp = plt_src.read_counter();
    1.52 @@ -565,6 +600,8 @@ static void init_platform_timer(void)
    1.53              rc = init_cyclone(pts);
    1.54          else if ( !strcmp(opt_clocksource, "acpi") )
    1.55              rc = init_pmtimer(pts);
    1.56 +        else if ( !strcmp(opt_clocksource, "tsc") )
    1.57 +            rc = init_tsctimer(pts);
    1.58  
    1.59          if ( rc <= 0 )
    1.60              printk("WARNING: %s clocksource '%s'.\n",
    1.61 @@ -578,6 +615,12 @@ static void init_platform_timer(void)
    1.62           !init_pmtimer(pts) )
    1.63          init_pit(pts);
    1.64  
    1.65 +    if ( platform_timer_is_tsc() )
    1.66 +    {
    1.67 +        printk("Platform timer is TSC\n");
    1.68 +        return;
    1.69 +    }
    1.70 +
    1.71      plt_mask = (u64)~0ull >> (64 - pts->counter_bits);
    1.72  
    1.73      set_time_scale(&plt_scale, pts->frequency);
    1.74 @@ -780,6 +823,10 @@ int cpu_frequency_change(u64 freq)
    1.75      struct cpu_time *t = &this_cpu(cpu_time);
    1.76      u64 curr_tsc;
    1.77  
    1.78 +    /* Nothing to do if TSC is platform timer. Assume it is constant-rate. */
    1.79 +    if ( platform_timer_is_tsc() )
    1.80 +        return 0;
    1.81 +
    1.82      /* Sanity check: CPU frequency allegedly dropping below 1MHz? */
    1.83      if ( freq < 1000000u )
    1.84      {
    1.85 @@ -861,6 +908,14 @@ static void local_time_calibration(void 
    1.86      /* The overall calibration scale multiplier. */
    1.87      u32 calibration_mul_frac;
    1.88  
    1.89 +    if ( platform_timer_is_tsc() )
    1.90 +    {
    1.91 +        make_tsctimer_record(); 
    1.92 +        update_vcpu_system_time(current);
    1.93 +        set_timer(&t->calibration_timer, NOW() + MILLISECS(10*1000));
    1.94 +        return;
    1.95 +    }
    1.96 +
    1.97      prev_tsc          = t->local_tsc_stamp;
    1.98      prev_local_stime  = t->stime_local_stamp;
    1.99      prev_master_stime = t->stime_master_stamp;
   1.100 @@ -978,6 +1033,12 @@ void init_percpu_time(void)
   1.101      unsigned long flags;
   1.102      s_time_t now;
   1.103  
   1.104 +    if ( platform_timer_is_tsc() )
   1.105 +    {
   1.106 +        make_tsctimer_record();
   1.107 +        goto out;
   1.108 +    }
   1.109 +
   1.110      local_irq_save(flags);
   1.111      rdtscll(t->local_tsc_stamp);
   1.112      now = !plt_src.read_counter ? 0 : read_platform_stime();
   1.113 @@ -986,6 +1047,7 @@ void init_percpu_time(void)
   1.114      t->stime_master_stamp = now;
   1.115      t->stime_local_stamp  = now;
   1.116  
   1.117 + out:
   1.118      init_timer(&t->calibration_timer, local_time_calibration,
   1.119                 NULL, smp_processor_id());
   1.120      set_timer(&t->calibration_timer, NOW() + EPOCH);
   1.121 @@ -994,19 +1056,19 @@ void init_percpu_time(void)
   1.122  /* Late init function (after all CPUs are booted). */
   1.123  int __init init_xen_time(void)
   1.124  {
   1.125 -    wc_sec = get_cmos_time();
   1.126 +    local_irq_disable();
   1.127  
   1.128 -    local_irq_disable();
   1.129 +    /* check if TSC is invariant during deep C state
   1.130 +       this is a new feature introduced by Nehalem*/
   1.131 +    if ( cpuid_edx(0x80000007) & (1u<<8) )
   1.132 +        tsc_invariant = 1;
   1.133  
   1.134      init_percpu_time();
   1.135  
   1.136      stime_platform_stamp = 0;
   1.137      init_platform_timer();
   1.138  
   1.139 -    /* check if TSC is invariant during deep C state
   1.140 -       this is a new feature introduced by Nehalem*/
   1.141 -    if ( cpuid_edx(0x80000007) & (1U<<8) )
   1.142 -        tsc_invariant = 1;
   1.143 +    do_settime(get_cmos_time(), 0, NOW());
   1.144  
   1.145      local_irq_enable();
   1.146  
   1.147 @@ -1120,9 +1182,9 @@ int time_resume(void)
   1.148  
   1.149      resume_platform_timer();
   1.150  
   1.151 -    do_settime(get_cmos_time() + cmos_utc_offset, 0, read_platform_stime());
   1.152 +    init_percpu_time();
   1.153  
   1.154 -    init_percpu_time();
   1.155 +    do_settime(get_cmos_time() + cmos_utc_offset, 0, NOW());
   1.156  
   1.157      if ( !is_idle_vcpu(current) )
   1.158          update_vcpu_system_time(current);