ia64/xen-unstable

changeset 16245:b5a2cbca3930

hvm, x86: Allow virtual timer mode to be specified.

In HVM config file:
timer_mode=0 # Default: virtual time is delayed when timer ticks are
# missed dur to preemption
timer_mode=1 # Virtual time always equals wall time, even while missed
# ticks are pending

From: Haitao Shan <haitao.shan@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Fri Oct 26 09:56:54 2007 +0100 (2007-10-26)
parents a9171b9c3fd8
children fd09283562e2
files tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendConstants.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xm/create.py tools/python/xen/xm/xenapi_create.py xen/arch/x86/domain.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpt.c xen/include/asm-x86/hvm/hvm.h xen/include/asm-x86/hvm/vpt.h xen/include/public/hvm/params.h
line diff
     1.1 --- a/tools/python/xen/xend/XendConfig.py	Thu Oct 25 17:27:57 2007 +0100
     1.2 +++ b/tools/python/xen/xend/XendConfig.py	Fri Oct 26 09:56:54 2007 +0100
     1.3 @@ -127,7 +127,7 @@ XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 
     1.4                          'fda', 'fdb', 'keymap', 'isa', 'localtime', 'monitor', 
     1.5                          'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
     1.6                          'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
     1.7 -                        'vncconsole', 'vncdisplay', 'vnclisten',
     1.8 +                        'vncconsole', 'vncdisplay', 'vnclisten', 'timer_mode',
     1.9                          'vncpasswd', 'vncunused', 'xauthority', 'pci', 'vhpt']
    1.10  
    1.11  # Xen API console 'other_config' keys.
     2.1 --- a/tools/python/xen/xend/XendConstants.py	Thu Oct 25 17:27:57 2007 +0100
     2.2 +++ b/tools/python/xen/xend/XendConstants.py	Fri Oct 26 09:56:54 2007 +0100
     2.3 @@ -46,6 +46,7 @@ HVM_PARAM_BUFIOREQ_PFN = 6
     2.4  HVM_PARAM_NVRAM_FD     = 7
     2.5  HVM_PARAM_VHPT_SIZE    = 8
     2.6  HVM_PARAM_BUFPIOREQ_PFN = 9
     2.7 +HVM_PARAM_TIMER_MODE   = 10
     2.8  
     2.9  restart_modes = [
    2.10      "restart",
     3.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Oct 25 17:27:57 2007 +0100
     3.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Oct 26 09:56:54 2007 +0100
     3.3 @@ -1596,6 +1596,11 @@ class XendDomainInfo:
     3.4  
     3.5          self._recreateDom()
     3.6  
     3.7 +        # Set timer configration of domain
     3.8 +        if hvm:
     3.9 +            xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE,
    3.10 +                long(self.info["platform"].get("timer_mode")))
    3.11 +
    3.12          # Set maximum number of vcpus in domain
    3.13          xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max']))
    3.14  
     4.1 --- a/tools/python/xen/xm/create.py	Thu Oct 25 17:27:57 2007 +0100
     4.2 +++ b/tools/python/xen/xm/create.py	Fri Oct 26 09:56:54 2007 +0100
     4.3 @@ -194,6 +194,11 @@ gopts.var('pae', val='PAE',
     4.4            fn=set_int, default=1,
     4.5            use="Disable or enable PAE of HVM domain.")
     4.6  
     4.7 +gopts.var('timer_mode', val='TIMER_MODE',
     4.8 +          fn=set_int, default=0,
     4.9 +          use="""Timer mode (0=delay virtual time when ticks are missed;
    4.10 +          1=virtual time is always wallclock time.""")
    4.11 +
    4.12  gopts.var('acpi', val='ACPI',
    4.13            fn=set_int, default=1,
    4.14            use="Disable or enable ACPI of HVM domain.")
    4.15 @@ -724,7 +729,7 @@ def configure_vifs(config_devs, vals):
    4.16  def configure_hvm(config_image, vals):
    4.17      """Create the config for HVM devices.
    4.18      """
    4.19 -    args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
    4.20 +    args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 'timer_mode',
    4.21               'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
    4.22               'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
    4.23               'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
     5.1 --- a/tools/python/xen/xm/xenapi_create.py	Thu Oct 25 17:27:57 2007 +0100
     5.2 +++ b/tools/python/xen/xm/xenapi_create.py	Fri Oct 26 09:56:54 2007 +0100
     5.3 @@ -818,7 +818,7 @@ class sxp2xml:
     5.4  
     5.5  
     5.6      def extract_platform(self, image, document):
     5.7 -        platform_keys = ['acpi', 'apic', 'pae', 'vhpt']
     5.8 +        platform_keys = ['acpi', 'apic', 'pae', 'vhpt', 'timer_mode']
     5.9  
    5.10          def extract_platform_key(key):
    5.11              platform = document.createElement("platform")
     6.1 --- a/xen/arch/x86/domain.c	Thu Oct 25 17:27:57 2007 +0100
     6.2 +++ b/xen/arch/x86/domain.c	Fri Oct 26 09:56:54 2007 +0100
     6.3 @@ -1279,7 +1279,7 @@ void context_switch(struct vcpu *prev, s
     6.4      local_irq_disable();
     6.5  
     6.6      if ( is_hvm_vcpu(prev) && !list_empty(&prev->arch.hvm_vcpu.tm_list) )
     6.7 -        pt_freeze_time(prev);
     6.8 +        pt_save_timer(prev);
     6.9  
    6.10      set_current(next);
    6.11  
     7.1 --- a/xen/arch/x86/hvm/hvm.c	Thu Oct 25 17:27:57 2007 +0100
     7.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Oct 26 09:56:54 2007 +0100
     7.3 @@ -89,17 +89,17 @@ void hvm_enable(struct hvm_function_tabl
     7.4      }
     7.5  }
     7.6  
     7.7 -void hvm_set_guest_time(struct vcpu *v, u64 gtime)
     7.8 +void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc)
     7.9  {
    7.10      u64 host_tsc;
    7.11  
    7.12      rdtscll(host_tsc);
    7.13  
    7.14 -    v->arch.hvm_vcpu.cache_tsc_offset = gtime - host_tsc;
    7.15 +    v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - host_tsc;
    7.16      hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
    7.17  }
    7.18  
    7.19 -u64 hvm_get_guest_time(struct vcpu *v)
    7.20 +u64 hvm_get_guest_tsc(struct vcpu *v)
    7.21  {
    7.22      u64 host_tsc;
    7.23  
    7.24 @@ -121,7 +121,7 @@ void hvm_do_resume(struct vcpu *v)
    7.25      if ( !v->fpu_dirtied )
    7.26          hvm_funcs.stts(v);
    7.27  
    7.28 -    pt_thaw_time(v);
    7.29 +    pt_restore_timer(v);
    7.30  
    7.31      /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
    7.32      p = &get_ioreq(v)->vp_ioreq;
    7.33 @@ -1843,6 +1843,12 @@ long do_hvm_op(unsigned long op, XEN_GUE
    7.34                  hvm_set_callback_via(d, a.value);
    7.35                  hvm_latch_shinfo_size(d);
    7.36                  break;
    7.37 +            case HVM_PARAM_TIMER_MODE:
    7.38 +                rc = -EINVAL;
    7.39 +                if ( (a.value != HVMPTM_delay_for_missed_ticks) &&
    7.40 +                     (a.value != HVMPTM_no_delay_for_missed_ticks) )
    7.41 +                    goto param_fail;
    7.42 +                break;
    7.43              }
    7.44              d->arch.hvm_domain.params[a.index] = a.value;
    7.45              rc = 0;
     8.1 --- a/xen/arch/x86/hvm/vlapic.c	Thu Oct 25 17:27:57 2007 +0100
     8.2 +++ b/xen/arch/x86/hvm/vlapic.c	Fri Oct 26 09:56:54 2007 +0100
     8.3 @@ -430,7 +430,7 @@ static uint32_t vlapic_get_tmcct(struct 
     8.4      uint32_t tmcct, tmict = vlapic_get_reg(vlapic, APIC_TMICT);
     8.5      uint64_t counter_passed;
     8.6  
     8.7 -    counter_passed = (hvm_get_guest_time(v) - vlapic->pt.last_plt_gtime) // TSC
     8.8 +    counter_passed = (hvm_get_guest_time(v) - vlapic->timer_last_update) // TSC
     8.9                       * 1000000000ULL / ticks_per_sec(v) // NS
    8.10                       / APIC_BUS_CYCLE_NS / vlapic->hw.timer_divisor;
    8.11      tmcct = tmict - counter_passed;
    8.12 @@ -531,6 +531,11 @@ static unsigned long vlapic_read(struct 
    8.13      return 0;
    8.14  }
    8.15  
    8.16 +void vlapic_pt_cb(struct vcpu *v, void *data)
    8.17 +{
    8.18 +    *(s_time_t *)data = hvm_get_guest_time(v);
    8.19 +}
    8.20 +
    8.21  static void vlapic_write(struct vcpu *v, unsigned long address,
    8.22                           unsigned long len, unsigned long val)
    8.23  {
    8.24 @@ -660,7 +665,8 @@ static void vlapic_write(struct vcpu *v,
    8.25  
    8.26          vlapic_set_reg(vlapic, APIC_TMICT, val);
    8.27          create_periodic_time(current, &vlapic->pt, period, vlapic->pt.irq,
    8.28 -                             !vlapic_lvtt_period(vlapic), NULL, vlapic);
    8.29 +                             !vlapic_lvtt_period(vlapic), vlapic_pt_cb,
    8.30 +                             &vlapic->timer_last_update);
    8.31  
    8.32          HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
    8.33                      "bus cycle is %uns, "
    8.34 @@ -820,7 +826,8 @@ static void lapic_rearm(struct vlapic *s
    8.35  
    8.36          s->pt.irq = lvtt & APIC_VECTOR_MASK;
    8.37          create_periodic_time(vlapic_vcpu(s), &s->pt, period, s->pt.irq,
    8.38 -                             !vlapic_lvtt_period(s), NULL, s);
    8.39 +                             !vlapic_lvtt_period(s), vlapic_pt_cb,
    8.40 +                             &s->timer_last_update);
    8.41  
    8.42          printk("lapic_load to rearm the actimer:"
    8.43                      "bus cycle is %uns, "
     9.1 --- a/xen/arch/x86/hvm/vpt.c	Thu Oct 25 17:27:57 2007 +0100
     9.2 +++ b/xen/arch/x86/hvm/vpt.c	Fri Oct 26 09:56:54 2007 +0100
     9.3 @@ -23,6 +23,12 @@
     9.4  #include <asm/hvm/vpt.h>
     9.5  #include <asm/event.h>
     9.6  
     9.7 +static int pt_support_time_frozen(struct domain *d)
     9.8 +{
     9.9 +    return (d->arch.hvm_domain.params[HVM_PARAM_TIMER_MODE] == 
    9.10 +            HVMPTM_delay_for_missed_ticks);
    9.11 +}
    9.12 +
    9.13  static void pt_lock(struct periodic_time *pt)
    9.14  {
    9.15      struct vcpu *v;
    9.16 @@ -67,7 +73,12 @@ static void missed_ticks(struct periodic
    9.17      pt->scheduled += missed_ticks * pt->period;
    9.18  }
    9.19  
    9.20 -void pt_freeze_time(struct vcpu *v)
    9.21 +static __inline__ void pt_freeze_time(struct vcpu *v)
    9.22 +{
    9.23 +    v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
    9.24 +}
    9.25 +
    9.26 +void pt_save_timer(struct vcpu *v)
    9.27  {
    9.28      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
    9.29      struct periodic_time *pt;
    9.30 @@ -77,32 +88,39 @@ void pt_freeze_time(struct vcpu *v)
    9.31  
    9.32      spin_lock(&v->arch.hvm_vcpu.tm_lock);
    9.33  
    9.34 -    v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
    9.35 -
    9.36      list_for_each_entry ( pt, head, list )
    9.37          stop_timer(&pt->timer);
    9.38  
    9.39 +    if ( pt_support_time_frozen(v->domain) )
    9.40 +        pt_freeze_time(v);
    9.41 +
    9.42      spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    9.43  }
    9.44  
    9.45 -void pt_thaw_time(struct vcpu *v)
    9.46 +static __inline__ void pt_thaw_time(struct vcpu *v)
    9.47 +{
    9.48 +    if ( v->arch.hvm_vcpu.guest_time )
    9.49 +    {
    9.50 +        hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
    9.51 +        v->arch.hvm_vcpu.guest_time = 0;
    9.52 +    }
    9.53 +}
    9.54 +
    9.55 +void pt_restore_timer(struct vcpu *v)
    9.56  {
    9.57      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
    9.58      struct periodic_time *pt;
    9.59  
    9.60      spin_lock(&v->arch.hvm_vcpu.tm_lock);
    9.61  
    9.62 -    if ( v->arch.hvm_vcpu.guest_time )
    9.63 +    list_for_each_entry ( pt, head, list )
    9.64      {
    9.65 -        hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
    9.66 -        v->arch.hvm_vcpu.guest_time = 0;
    9.67 +        missed_ticks(pt);
    9.68 +        set_timer(&pt->timer, pt->scheduled);
    9.69 +    }
    9.70  
    9.71 -        list_for_each_entry ( pt, head, list )
    9.72 -        {
    9.73 -            missed_ticks(pt);
    9.74 -            set_timer(&pt->timer, pt->scheduled);
    9.75 -        }
    9.76 -    }
    9.77 +    if ( pt_support_time_frozen(v->domain) )
    9.78 +        pt_thaw_time(v);
    9.79  
    9.80      spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    9.81  }
    9.82 @@ -218,7 +236,8 @@ void pt_intr_post(struct vcpu *v, struct
    9.83          pt->last_plt_gtime += pt->period_cycles;
    9.84      }
    9.85  
    9.86 -    if ( hvm_get_guest_time(v) < pt->last_plt_gtime )
    9.87 +    if ( pt_support_time_frozen(v->domain) &&
    9.88 +            hvm_get_guest_time(v) < pt->last_plt_gtime )
    9.89          hvm_set_guest_time(v, pt->last_plt_gtime);
    9.90  
    9.91      cb = pt->cb;
    10.1 --- a/xen/include/asm-x86/hvm/hvm.h	Thu Oct 25 17:27:57 2007 +0100
    10.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Fri Oct 26 09:56:54 2007 +0100
    10.3 @@ -175,8 +175,10 @@ void hvm_vcpu_reset(struct vcpu *vcpu);
    10.4  
    10.5  void hvm_send_assist_req(struct vcpu *v);
    10.6  
    10.7 -void hvm_set_guest_time(struct vcpu *v, u64 gtime);
    10.8 -u64 hvm_get_guest_time(struct vcpu *v);
    10.9 +void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc);
   10.10 +u64 hvm_get_guest_tsc(struct vcpu *v);
   10.11 +#define hvm_set_guest_time(vcpu, gtime) hvm_set_guest_tsc(vcpu, gtime)
   10.12 +#define hvm_get_guest_time(vcpu)        hvm_get_guest_tsc(vcpu)
   10.13  
   10.14  #define hvm_paging_enabled(v) \
   10.15      (!!((v)->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PG))
    11.1 --- a/xen/include/asm-x86/hvm/vpt.h	Thu Oct 25 17:27:57 2007 +0100
    11.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Fri Oct 26 09:56:54 2007 +0100
    11.3 @@ -133,8 +133,8 @@ struct pl_time {    /* platform time */
    11.4  
    11.5  #define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
    11.6  
    11.7 -void pt_freeze_time(struct vcpu *v);
    11.8 -void pt_thaw_time(struct vcpu *v);
    11.9 +void pt_save_timer(struct vcpu *v);
   11.10 +void pt_restore_timer(struct vcpu *v);
   11.11  void pt_update_irq(struct vcpu *v);
   11.12  void pt_intr_post(struct vcpu *v, struct hvm_intack intack);
   11.13  void pt_reset(struct vcpu *v);
    12.1 --- a/xen/include/public/hvm/params.h	Thu Oct 25 17:27:57 2007 +0100
    12.2 +++ b/xen/include/public/hvm/params.h	Fri Oct 26 09:56:54 2007 +0100
    12.3 @@ -54,9 +54,23 @@
    12.4  #define HVM_PARAM_NVRAM_FD     7
    12.5  #define HVM_PARAM_VHPT_SIZE    8
    12.6  #define HVM_PARAM_BUFPIOREQ_PFN	9
    12.7 -#define HVM_NR_PARAMS          10
    12.8 -#else
    12.9 -#define HVM_NR_PARAMS          7
   12.10  #endif
   12.11  
   12.12 +/*
   12.13 + * Set mode for virtual timers (currently x86 only):
   12.14 + *  delay_for_missed_ticks (default):
   12.15 + *   Do not advance a vcpu's time beyond the correct delivery time for
   12.16 + *   interrupts that have been missed due to preemption. Deliver missed
   12.17 + *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
   12.18 + *   time stepwise for each one.
   12.19 + *  no_delay_for_missed_ticks:
   12.20 + *   As above, missed interrupts are delivered, but guest time always tracks
   12.21 + *   wallclock (i.e., real) time while doing so.
   12.22 + */
   12.23 +#define HVM_PARAM_TIMER_MODE   10
   12.24 +#define HVMPTM_delay_for_missed_ticks    0
   12.25 +#define HVMPTM_no_delay_for_missed_ticks 1
   12.26 +
   12.27 +#define HVM_NR_PARAMS          11
   12.28 +
   12.29  #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */