direct-io.hg

changeset 13096:2a1edeedf28d

[HVM] Enable more than one platform timer (PIT/RTC/HPET)
programmed as periodic timer and adds them to abstract layer, which
keeps track of pending_intr_nr to avoid time interrupt lost and
sync'ed timer with TSC.

It also makes some cleanup to the time related code.

Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
author kfraser@localhost.localdomain
date Wed Dec 20 10:37:23 2006 +0000 (2006-12-20)
parents b17d1bc1febf
children 516e4faac066
files xen/arch/x86/domain.c xen/arch/x86/hvm/Makefile xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/io.c xen/arch/x86/hvm/irq.c xen/arch/x86/hvm/pmtimer.c xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vmx/intr.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/hvm/vpic.c xen/include/asm-x86/hvm/hvm.h xen/include/asm-x86/hvm/io.h xen/include/asm-x86/hvm/irq.h xen/include/asm-x86/hvm/vcpu.h xen/include/asm-x86/hvm/vlapic.h xen/include/asm-x86/hvm/vpt.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Wed Dec 20 10:14:50 2006 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Wed Dec 20 10:37:23 2006 +0000
     1.3 @@ -726,6 +726,9 @@ void context_switch(struct vcpu *prev, s
     1.4  
     1.5      local_irq_disable();
     1.6  
     1.7 +    if ( is_hvm_vcpu(prev) )
     1.8 +        pt_freeze_time(prev);
     1.9 +
    1.10      set_current(next);
    1.11  
    1.12      if ( (per_cpu(curr_vcpu, cpu) == next) || is_idle_vcpu(next) )
     2.1 --- a/xen/arch/x86/hvm/Makefile	Wed Dec 20 10:14:50 2006 +0000
     2.2 +++ b/xen/arch/x86/hvm/Makefile	Wed Dec 20 10:37:23 2006 +0000
     2.3 @@ -10,6 +10,7 @@ obj-y += irq.o
     2.4  obj-y += platform.o
     2.5  obj-y += pmtimer.o
     2.6  obj-y += rtc.o
     2.7 +obj-y += vpt.o
     2.8  obj-y += vioapic.o
     2.9  obj-y += vlapic.o
    2.10  obj-y += vpic.o
     3.1 --- a/xen/arch/x86/hvm/hvm.c	Wed Dec 20 10:14:50 2006 +0000
     3.2 +++ b/xen/arch/x86/hvm/hvm.c	Wed Dec 20 10:37:23 2006 +0000
     3.3 @@ -82,56 +82,21 @@ u64 hvm_get_guest_time(struct vcpu *v)
     3.4      return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset;
     3.5  }
     3.6  
     3.7 -void hvm_freeze_time(struct vcpu *v)
     3.8 -{
     3.9 -    struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
    3.10 -
    3.11 -    if ( pt->enabled && pt->first_injected
    3.12 -            && (v->vcpu_id == pt->bind_vcpu)
    3.13 -            && !v->arch.hvm_vcpu.guest_time ) {
    3.14 -        v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
    3.15 -        if ( !test_bit(_VCPUF_blocked, &v->vcpu_flags) )
    3.16 -        {
    3.17 -            stop_timer(&pt->timer);
    3.18 -            rtc_freeze(v);
    3.19 -        }
    3.20 -    }
    3.21 -}
    3.22 -
    3.23  void hvm_migrate_timers(struct vcpu *v)
    3.24  {
    3.25 -    struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
    3.26 -    struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
    3.27 -
    3.28 -    if ( pt->enabled )
    3.29 -    {
    3.30 -        migrate_timer(&pt->timer, v->processor);
    3.31 -    }
    3.32 +    pit_migrate_timers(v);
    3.33 +    rtc_migrate_timers(v);
    3.34 +    pmtimer_migrate_timers(v);
    3.35      migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor);
    3.36 -    migrate_timer(&vpmt->timer, v->processor);
    3.37 -    rtc_migrate_timers(v);
    3.38  }
    3.39  
    3.40  void hvm_do_resume(struct vcpu *v)
    3.41  {
    3.42      ioreq_t *p;
    3.43 -    struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
    3.44  
    3.45      hvm_stts(v);
    3.46  
    3.47 -    /* Pick up the elapsed PIT ticks and re-enable pit_timer. */
    3.48 -    if ( pt->enabled && (v->vcpu_id == pt->bind_vcpu) && pt->first_injected )
    3.49 -    {
    3.50 -        if ( v->arch.hvm_vcpu.guest_time )
    3.51 -        {
    3.52 -            hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
    3.53 -            v->arch.hvm_vcpu.guest_time = 0;
    3.54 -        }
    3.55 -        pickup_deactive_ticks(pt);
    3.56 -    }
    3.57 -
    3.58 -    /* Re-enable the RTC timer if needed */
    3.59 -    rtc_thaw(v);
    3.60 +    pt_thaw_time(v);
    3.61  
    3.62      /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
    3.63      p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
    3.64 @@ -182,7 +147,7 @@ int hvm_domain_initialise(struct domain 
    3.65  
    3.66  void hvm_domain_destroy(struct domain *d)
    3.67  {
    3.68 -    kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
    3.69 +    pit_deinit(d);
    3.70      rtc_deinit(d);
    3.71      pmtimer_deinit(d);
    3.72  
    3.73 @@ -196,7 +161,6 @@ void hvm_domain_destroy(struct domain *d
    3.74  
    3.75  int hvm_vcpu_initialise(struct vcpu *v)
    3.76  {
    3.77 -    struct hvm_domain *platform;
    3.78      int rc;
    3.79  
    3.80      if ( (rc = vlapic_init(v)) != 0 )
    3.81 @@ -214,14 +178,11 @@ int hvm_vcpu_initialise(struct vcpu *v)
    3.82          get_vio(v->domain, v->vcpu_id)->vp_eport =
    3.83              v->arch.hvm_vcpu.xen_port;
    3.84  
    3.85 +    INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
    3.86 +
    3.87      if ( v->vcpu_id != 0 )
    3.88          return 0;
    3.89  
    3.90 -    /* XXX Below should happen in hvm_domain_initialise(). */
    3.91 -    platform = &v->domain->arch.hvm_domain;
    3.92 -
    3.93 -    init_timer(&platform->pl_time.periodic_tm.timer,
    3.94 -               pt_timer_fn, v, v->processor);
    3.95      rtc_init(v, RTC_PORT(0), RTC_IRQ);
    3.96      pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
    3.97  
    3.98 @@ -240,20 +201,6 @@ void hvm_vcpu_destroy(struct vcpu *v)
    3.99      /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/
   3.100  }
   3.101  
   3.102 -int cpu_get_interrupt(struct vcpu *v, int *type)
   3.103 -{
   3.104 -    int vector;
   3.105 -
   3.106 -    if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 )
   3.107 -        return vector;
   3.108 -
   3.109 -    if ( (v->vcpu_id == 0) &&
   3.110 -         ((vector = cpu_get_pic_interrupt(v, type)) != -1) )
   3.111 -        return vector;
   3.112 -
   3.113 -    return -1;
   3.114 -}
   3.115 -
   3.116  static void hvm_vcpu_down(void)
   3.117  {
   3.118      struct vcpu *v = current;
     4.1 --- a/xen/arch/x86/hvm/i8254.c	Wed Dec 20 10:14:50 2006 +0000
     4.2 +++ b/xen/arch/x86/hvm/i8254.c	Wed Dec 20 10:37:23 2006 +0000
     4.3 @@ -81,7 +81,7 @@ static int pit_get_count(PITChannelState
     4.4      uint64_t d;
     4.5      int  counter;
     4.6  
     4.7 -    d = muldiv64(hvm_get_clock(s->vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->vcpu));
     4.8 +    d = muldiv64(hvm_get_guest_time(s->pt.vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu));
     4.9      switch(s->mode) {
    4.10      case 0:
    4.11      case 1:
    4.12 @@ -106,7 +106,7 @@ static int pit_get_out1(PITChannelState 
    4.13      uint64_t d;
    4.14      int out;
    4.15  
    4.16 -    d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->vcpu));
    4.17 +    d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu));
    4.18      switch(s->mode) {
    4.19      default:
    4.20      case 0:
    4.21 @@ -153,7 +153,7 @@ void pit_set_gate(PITState *pit, int cha
    4.22      case 5:
    4.23          if (s->gate < val) {
    4.24              /* restart counting on rising edge */
    4.25 -            s->count_load_time = hvm_get_clock(s->vcpu);
    4.26 +            s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
    4.27  //            pit_irq_timer_update(s, s->count_load_time);
    4.28          }
    4.29          break;
    4.30 @@ -161,7 +161,7 @@ void pit_set_gate(PITState *pit, int cha
    4.31      case 3:
    4.32          if (s->gate < val) {
    4.33              /* restart counting on rising edge */
    4.34 -            s->count_load_time = hvm_get_clock(s->vcpu);
    4.35 +            s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
    4.36  //            pit_irq_timer_update(s, s->count_load_time);
    4.37          }
    4.38          /* XXX: disable/enable counting */
    4.39 @@ -179,7 +179,7 @@ int pit_get_gate(PITState *pit, int chan
    4.40  void pit_time_fired(struct vcpu *v, void *priv)
    4.41  {
    4.42      PITChannelState *s = priv;
    4.43 -    s->count_load_time = hvm_get_clock(v);
    4.44 +    s->count_load_time = hvm_get_guest_time(v);
    4.45  }
    4.46  
    4.47  static inline void pit_load_count(PITChannelState *s, int val)
    4.48 @@ -190,7 +190,7 @@ static inline void pit_load_count(PITCha
    4.49  
    4.50      if (val == 0)
    4.51          val = 0x10000;
    4.52 -    s->count_load_time = hvm_get_clock(s->vcpu);
    4.53 +    s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
    4.54      s->count = val;
    4.55      period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
    4.56  
    4.57 @@ -209,16 +209,17 @@ static inline void pit_load_count(PITCha
    4.58      switch (s->mode) {
    4.59          case 2:
    4.60              /* create periodic time */
    4.61 -            s->pt = create_periodic_time (period, 0, 0, pit_time_fired, s);
    4.62 +            create_periodic_time(&s->pt, period, 0, 0, pit_time_fired, s);
    4.63              break;
    4.64          case 1:
    4.65              /* create one shot time */
    4.66 -            s->pt = create_periodic_time (period, 0, 1, pit_time_fired, s);
    4.67 +            create_periodic_time(&s->pt, period, 0, 1, pit_time_fired, s);
    4.68  #ifdef DEBUG_PIT
    4.69              printk("HVM_PIT: create one shot time.\n");
    4.70  #endif
    4.71              break;
    4.72          default:
    4.73 +            destroy_periodic_time(&s->pt);
    4.74              break;
    4.75      }
    4.76  }
    4.77 @@ -253,7 +254,7 @@ static void pit_ioport_write(void *opaqu
    4.78                      if (!(val & 0x10) && !s->status_latched) {
    4.79                          /* status latch */
    4.80                          /* XXX: add BCD and null count */
    4.81 -                        s->status =  (pit_get_out1(s, hvm_get_clock(s->vcpu)) << 7) |
    4.82 +                        s->status =  (pit_get_out1(s, hvm_get_guest_time(s->pt.vcpu)) << 7) |
    4.83                              (s->rw_mode << 4) |
    4.84                              (s->mode << 1) |
    4.85                              s->bcd;
    4.86 @@ -359,10 +360,7 @@ static void pit_reset(void *opaque)
    4.87  
    4.88      for(i = 0;i < 3; i++) {
    4.89          s = &pit->channels[i];
    4.90 -        if ( s -> pt ) {
    4.91 -            destroy_periodic_time (s->pt);
    4.92 -            s->pt = NULL;
    4.93 -        }
    4.94 +        destroy_periodic_time(&s->pt);
    4.95          s->mode = 0xff; /* the init mode */
    4.96          s->gate = (i != 2);
    4.97          pit_load_count(s, 0);
    4.98 @@ -375,10 +373,11 @@ void pit_init(struct vcpu *v, unsigned l
    4.99      PITChannelState *s;
   4.100  
   4.101      s = &pit->channels[0];
   4.102 +    s->pt.vcpu = v;
   4.103      /* the timer 0 is connected to an IRQ */
   4.104 -    s->vcpu = v;
   4.105 -    s++; s->vcpu = v;
   4.106 -    s++; s->vcpu = v;
   4.107 +    init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor);
   4.108 +    s++; s->pt.vcpu = v;
   4.109 +    s++; s->pt.vcpu = v;
   4.110  
   4.111      register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
   4.112      /* register the speaker port */
   4.113 @@ -391,6 +390,25 @@ void pit_init(struct vcpu *v, unsigned l
   4.114      return;
   4.115  }
   4.116  
   4.117 +void pit_migrate_timers(struct vcpu *v)
   4.118 +{
   4.119 +    PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
   4.120 +    PITChannelState *s;
   4.121 +
   4.122 +    s = &pit->channels[0];
   4.123 +    if ( s->pt.vcpu == v && s->pt.enabled )
   4.124 +        migrate_timer(&s->pt.timer, v->processor);
   4.125 +}
   4.126 +
   4.127 +void pit_deinit(struct domain *d)
   4.128 +{
   4.129 +    PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
   4.130 +    PITChannelState *s;
   4.131 +
   4.132 +    s = &pit->channels[0];
   4.133 +    kill_timer(&s->pt.timer);
   4.134 +}
   4.135 +
   4.136  /* the intercept action for PIT DM retval:0--not handled; 1--handled */  
   4.137  static int handle_pit_io(ioreq_t *p)
   4.138  {
   4.139 @@ -426,7 +444,8 @@ static void speaker_ioport_write(void *o
   4.140  static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
   4.141  {
   4.142      PITState *pit = opaque;
   4.143 -    int out = pit_get_out(pit, 2, hvm_get_clock(pit->channels[2].vcpu));
   4.144 +    int out = pit_get_out(pit, 2,
   4.145 +                          hvm_get_guest_time(pit->channels[2].pt.vcpu));
   4.146      /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
   4.147      unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1;
   4.148      return ((pit->speaker_data_on << 1) | pit_get_gate(pit, 2) |
     5.1 --- a/xen/arch/x86/hvm/intercept.c	Wed Dec 20 10:14:50 2006 +0000
     5.2 +++ b/xen/arch/x86/hvm/intercept.c	Wed Dec 20 10:37:23 2006 +0000
     5.3 @@ -263,98 +263,6 @@ int register_io_handler(
     5.4  
     5.5      return 1;
     5.6  }
     5.7 -
     5.8 -static __inline__ void missed_ticks(struct periodic_time *pt)
     5.9 -{
    5.10 -    s_time_t missed_ticks;
    5.11 -
    5.12 -    missed_ticks = NOW() - pt->scheduled;
    5.13 -    if ( missed_ticks > 0 ) {
    5.14 -        missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
    5.15 -        if ( missed_ticks > 1000 ) {
    5.16 -            /* TODO: Adjust guest time togther */
    5.17 -            pt->pending_intr_nr++;
    5.18 -        }
    5.19 -        else {
    5.20 -            pt->pending_intr_nr += missed_ticks;
    5.21 -        }
    5.22 -        pt->scheduled += missed_ticks * pt->period;
    5.23 -    }
    5.24 -}
    5.25 -
    5.26 -/* hook function for the platform periodic time */
    5.27 -void pt_timer_fn(void *data)
    5.28 -{
    5.29 -    struct vcpu *v = data;
    5.30 -    struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
    5.31 -
    5.32 -    pt->pending_intr_nr++;
    5.33 -    pt->scheduled += pt->period;
    5.34 -
    5.35 -    /* Pick up missed timer ticks. */
    5.36 -    missed_ticks(pt);
    5.37 -
    5.38 -    /* No need to run the timer while a VCPU is descheduled. */
    5.39 -    if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
    5.40 -        set_timer(&pt->timer, pt->scheduled);
    5.41 -
    5.42 -    vcpu_kick(v);
    5.43 -}
    5.44 -
    5.45 -/* pick up missed timer ticks at deactive time */
    5.46 -void pickup_deactive_ticks(struct periodic_time *pt)
    5.47 -{
    5.48 -    if ( !active_timer(&(pt->timer)) ) {
    5.49 -        missed_ticks(pt);
    5.50 -        set_timer(&pt->timer, pt->scheduled);
    5.51 -    }
    5.52 -}
    5.53 -
    5.54 -/*
    5.55 - * period: fire frequency in ns.
    5.56 - */
    5.57 -struct periodic_time * create_periodic_time(
    5.58 -        u32 period, 
    5.59 -        char irq,
    5.60 -        char one_shot,
    5.61 -        time_cb *cb,
    5.62 -        void *data)
    5.63 -{
    5.64 -    struct periodic_time *pt = &(current->domain->arch.hvm_domain.pl_time.periodic_tm);
    5.65 -    if ( pt->enabled ) {
    5.66 -        stop_timer (&pt->timer);
    5.67 -        pt->enabled = 0;
    5.68 -    }
    5.69 -    pt->bind_vcpu = 0; /* timer interrupt delivered to BSP by default */
    5.70 -    pt->pending_intr_nr = 0;
    5.71 -    pt->first_injected = 0;
    5.72 -    if (period < 900000) { /* < 0.9 ms */
    5.73 -        printk("HVM_PlatformTime: program too small period %u\n",period);
    5.74 -        period = 900000;   /* force to 0.9ms */
    5.75 -    }
    5.76 -    pt->period = period;
    5.77 -    pt->irq = irq;
    5.78 -    pt->period_cycles = (u64)period * cpu_khz / 1000000L;
    5.79 -    pt->one_shot = one_shot;
    5.80 -    if ( one_shot ) {
    5.81 -        printk("HVM_PL: No support for one shot platform time yet\n");
    5.82 -    }
    5.83 -    pt->scheduled = NOW() + period;
    5.84 -    set_timer (&pt->timer,pt->scheduled);
    5.85 -    pt->enabled = 1;
    5.86 -    pt->cb = cb;
    5.87 -    pt->priv = data;
    5.88 -    return pt;
    5.89 -}
    5.90 -
    5.91 -void destroy_periodic_time(struct periodic_time *pt)
    5.92 -{
    5.93 -    if ( pt->enabled ) {
    5.94 -        stop_timer(&pt->timer);
    5.95 -        pt->enabled = 0;
    5.96 -    }
    5.97 -}
    5.98 -
    5.99  /*
   5.100   * Local variables:
   5.101   * mode: C
     6.1 --- a/xen/arch/x86/hvm/io.c	Wed Dec 20 10:14:50 2006 +0000
     6.2 +++ b/xen/arch/x86/hvm/io.c	Wed Dec 20 10:37:23 2006 +0000
     6.3 @@ -691,25 +691,7 @@ static void hvm_mmio_assist(struct cpu_u
     6.4  
     6.5  void hvm_interrupt_post(struct vcpu *v, int vector, int type)
     6.6  {
     6.7 -    struct  periodic_time *pt = 
     6.8 -        &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
     6.9 -
    6.10 -    if ( pt->enabled && v->vcpu_id == pt->bind_vcpu 
    6.11 -            && is_periodic_irq(v, vector, type) ) {
    6.12 -        if ( !pt->first_injected ) {
    6.13 -            pt->pending_intr_nr = 0;
    6.14 -            pt->last_plt_gtime = hvm_get_guest_time(v);
    6.15 -            pt->scheduled = NOW() + pt->period;
    6.16 -            set_timer(&pt->timer, pt->scheduled);
    6.17 -            pt->first_injected = 1;
    6.18 -        } else {
    6.19 -            pt->pending_intr_nr--;
    6.20 -            pt->last_plt_gtime += pt->period_cycles;
    6.21 -            hvm_set_guest_time(v, pt->last_plt_gtime);
    6.22 -        }
    6.23 -        if (pt->cb)
    6.24 -            pt->cb(v, pt->priv);
    6.25 -    }
    6.26 +    pt_intr_post(v, vector, type);
    6.27      
    6.28      switch(type) {
    6.29      case APIC_DM_EXTINT:
     7.1 --- a/xen/arch/x86/hvm/irq.c	Wed Dec 20 10:14:50 2006 +0000
     7.2 +++ b/xen/arch/x86/hvm/irq.c	Wed Dec 20 10:37:23 2006 +0000
     7.3 @@ -225,3 +225,51 @@ void hvm_set_callback_gsi(struct domain 
     7.4      dprintk(XENLOG_G_INFO, "Dom%u callback GSI changed %u -> %u\n",
     7.5              d->domain_id, old_gsi, gsi);
     7.6  }
     7.7 +
     7.8 +int cpu_has_pending_irq(struct vcpu *v)
     7.9 +{
    7.10 +    struct hvm_domain *plat = &v->domain->arch.hvm_domain;
    7.11 +    int dummy;
    7.12 +
    7.13 +    /* APIC */
    7.14 +    if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
    7.15 +        return 1;
    7.16 +
    7.17 +    /* PIC */
    7.18 +    if ( !vlapic_accept_pic_intr(v) )
    7.19 +        return 0;
    7.20 +
    7.21 +    return plat->irq.vpic[0].int_output;
    7.22 +}
    7.23 +
    7.24 +int cpu_get_interrupt(struct vcpu *v, int *type)
    7.25 +{
    7.26 +    int vector;
    7.27 +
    7.28 +    if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 )
    7.29 +        return vector;
    7.30 +
    7.31 +    if ( (v->vcpu_id == 0) &&
    7.32 +         ((vector = cpu_get_pic_interrupt(v, type)) != -1) )
    7.33 +        return vector;
    7.34 +
    7.35 +    return -1;
    7.36 +}
    7.37 +
    7.38 +int get_intr_vector(struct vcpu* v, int irq, int type)
    7.39 +{
    7.40 +    if ( type == APIC_DM_EXTINT )
    7.41 +        return v->domain->arch.hvm_domain.irq.vpic[irq >> 3].irq_base
    7.42 +                + (irq & 0x7);
    7.43 +
    7.44 +    return domain_vioapic(v->domain)->redirtbl[irq].fields.vector;
    7.45 +}
    7.46 +
    7.47 +int is_irq_masked(struct vcpu *v, int irq)
    7.48 +{
    7.49 +    if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7))
    7.50 +            && domain_vioapic(v->domain)->redirtbl[irq].fields.mask )
    7.51 +        return 1;
    7.52 +
    7.53 +    return 0;
    7.54 +}
     8.1 --- a/xen/arch/x86/hvm/pmtimer.c	Wed Dec 20 10:14:50 2006 +0000
     8.2 +++ b/xen/arch/x86/hvm/pmtimer.c	Wed Dec 20 10:37:23 2006 +0000
     8.3 @@ -55,6 +55,14 @@ void pmtimer_init(struct vcpu *v, int ba
     8.4      register_portio_handler(v->domain, base, 4, handle_pmt_io);
     8.5  }
     8.6  
     8.7 +void pmtimer_migrate_timers(struct vcpu *v)
     8.8 +{
     8.9 +    struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
    8.10 +
    8.11 +    if (vpmt->vcpu == v)
    8.12 +        migrate_timer(&vpmt->timer, v->processor);
    8.13 +}
    8.14 +
    8.15  void pmtimer_deinit(struct domain *d)
    8.16  {
    8.17      PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
     9.1 --- a/xen/arch/x86/hvm/rtc.c	Wed Dec 20 10:14:50 2006 +0000
     9.2 +++ b/xen/arch/x86/hvm/rtc.c	Wed Dec 20 10:37:23 2006 +0000
     9.3 @@ -30,17 +30,18 @@
     9.4  
     9.5  /* #define DEBUG_RTC */
     9.6  
     9.7 -/* Callback that fires the RTC's periodic interrupt */
     9.8 -void rtc_pie_callback(void *opaque)
     9.9 +void rtc_periodic_cb(struct vcpu *v, void *opaque)
    9.10  {
    9.11      RTCState *s = opaque;
    9.12 -    /* Record that we have fired */
    9.13 -    s->cmos_data[RTC_REG_C] |= (RTC_IRQF|RTC_PF); /* 0xc0 */
    9.14 -    /* Fire */
    9.15 -    hvm_isa_irq_assert(s->vcpu->domain, s->irq);
    9.16 -    /* Remember to fire again */
    9.17 -    s->next_pie = NOW() + s->period;
    9.18 -    set_timer(&s->pie_timer, s->next_pie);
    9.19 +    s->cmos_data[RTC_REG_C] |= 0xc0;
    9.20 +}
    9.21 +
    9.22 +int is_rtc_periodic_irq(void *opaque)
    9.23 +{
    9.24 +    RTCState *s = opaque;
    9.25 +
    9.26 +    return !(s->cmos_data[RTC_REG_C] & RTC_AF || 
    9.27 +           s->cmos_data[RTC_REG_C] & RTC_UF);
    9.28  }
    9.29  
    9.30  /* Enable/configure/disable the periodic timer based on the RTC_PIE and
    9.31 @@ -58,17 +59,13 @@ static void rtc_timer_update(RTCState *s
    9.32          
    9.33          period = 1 << (period_code - 1); /* period in 32 Khz cycles */
    9.34          period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */
    9.35 -        s->period = period;
    9.36  #ifdef DEBUG_RTC
    9.37          printk("HVM_RTC: period = %uns\n", period);
    9.38  #endif
    9.39 -        s->next_pie = NOW() + s->period;
    9.40 -        set_timer(&s->pie_timer, s->next_pie);
    9.41 -    }
    9.42 +        create_periodic_time(&s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s);
    9.43 +    } 
    9.44      else
    9.45 -    {
    9.46 -        stop_timer(&s->pie_timer);
    9.47 -    }
    9.48 +        destroy_periodic_time(&s->pt);
    9.49  }
    9.50  
    9.51  static void rtc_set_time(RTCState *s);
    9.52 @@ -292,8 +289,8 @@ static void rtc_update_second2(void *opa
    9.53                s->current_tm.tm_hour) )
    9.54          {
    9.55              s->cmos_data[RTC_REG_C] |= 0xa0; 
    9.56 -            hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
    9.57 -            hvm_isa_irq_assert(s->vcpu->domain, s->irq);
    9.58 +            hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
    9.59 +            hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq);
    9.60          }
    9.61      }
    9.62  
    9.63 @@ -301,8 +298,8 @@ static void rtc_update_second2(void *opa
    9.64      if ( s->cmos_data[RTC_REG_B] & RTC_UIE )
    9.65      {
    9.66          s->cmos_data[RTC_REG_C] |= 0x90; 
    9.67 -        hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
    9.68 -        hvm_isa_irq_assert(s->vcpu->domain, s->irq);
    9.69 +        hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
    9.70 +        hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq);
    9.71      }
    9.72  
    9.73      /* clear update in progress bit */
    9.74 @@ -336,7 +333,7 @@ static uint32_t rtc_ioport_read(void *op
    9.75          break;
    9.76      case RTC_REG_C:
    9.77          ret = s->cmos_data[s->cmos_index];
    9.78 -        hvm_isa_irq_deassert(s->vcpu->domain, s->irq);
    9.79 +        hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq);
    9.80          s->cmos_data[RTC_REG_C] = 0x00; 
    9.81          break;
    9.82      default:
    9.83 @@ -377,36 +374,25 @@ static int handle_rtc_io(ioreq_t *p)
    9.84      return 0;
    9.85  }
    9.86  
    9.87 -/* Stop the periodic interrupts from this RTC */
    9.88 -void rtc_freeze(struct vcpu *v)
    9.89 -{
    9.90 -    RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
    9.91 -    stop_timer(&s->pie_timer);
    9.92 -}
    9.93 -
    9.94 -/* Start them again */
    9.95 -void rtc_thaw(struct vcpu *v)
    9.96 -{
    9.97 -    RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
    9.98 -    if ( (s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT) /* Period is not zero */
    9.99 -         && (s->cmos_data[RTC_REG_B] & RTC_PIE) ) 
   9.100 -        set_timer(&s->pie_timer, s->next_pie);
   9.101 -}
   9.102 -
   9.103  /* Move the RTC timers on to this vcpu's current cpu */
   9.104  void rtc_migrate_timers(struct vcpu *v)
   9.105  {
   9.106      RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
   9.107 -    migrate_timer(&s->second_timer, v->processor);
   9.108 -    migrate_timer(&s->second_timer2, v->processor);
   9.109 -    migrate_timer(&s->pie_timer, v->processor);
   9.110 +
   9.111 +    if ( s->pt.vcpu == v )
   9.112 +    {
   9.113 +        if ( s->pt.enabled )
   9.114 +            migrate_timer(&s->pt.timer, v->processor);
   9.115 +        migrate_timer(&s->second_timer, v->processor);
   9.116 +        migrate_timer(&s->second_timer2, v->processor);
   9.117 +    }
   9.118  }
   9.119  
   9.120  void rtc_init(struct vcpu *v, int base, int irq)
   9.121  {
   9.122      RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
   9.123  
   9.124 -    s->vcpu = v;
   9.125 +    s->pt.vcpu = v;
   9.126      s->irq = irq;
   9.127      s->cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
   9.128      s->cmos_data[RTC_REG_B] = RTC_24H;
   9.129 @@ -416,9 +402,9 @@ void rtc_init(struct vcpu *v, int base, 
   9.130      s->current_tm = gmtime(get_localtime(v->domain));
   9.131      rtc_copy_date(s);
   9.132  
   9.133 +    init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor);
   9.134      init_timer(&s->second_timer, rtc_update_second, s, v->processor);
   9.135      init_timer(&s->second_timer2, rtc_update_second2, s, v->processor);
   9.136 -    init_timer(&s->pie_timer, rtc_pie_callback, s, v->processor);
   9.137  
   9.138      s->next_second_time = NOW() + 1000000000ULL;
   9.139      set_timer(&s->second_timer2, s->next_second_time);
   9.140 @@ -430,7 +416,7 @@ void rtc_deinit(struct domain *d)
   9.141  {
   9.142      RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
   9.143  
   9.144 +    kill_timer(&s->pt.timer);
   9.145      kill_timer(&s->second_timer);
   9.146      kill_timer(&s->second_timer2);
   9.147 -    kill_timer(&s->pie_timer);
   9.148  }
    10.1 --- a/xen/arch/x86/hvm/svm/intr.c	Wed Dec 20 10:14:50 2006 +0000
    10.2 +++ b/xen/arch/x86/hvm/svm/intr.c	Wed Dec 20 10:37:23 2006 +0000
    10.3 @@ -63,8 +63,7 @@ asmlinkage void svm_intr_assist(void)
    10.4  {
    10.5      struct vcpu *v = current;
    10.6      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
    10.7 -    struct hvm_domain *plat=&v->domain->arch.hvm_domain;
    10.8 -    struct periodic_time *pt = &plat->pl_time.periodic_tm;
    10.9 +    struct periodic_time *pt;
   10.10      int intr_type = APIC_DM_EXTINT;
   10.11      int intr_vector = -1;
   10.12      int re_injecting = 0;
   10.13 @@ -95,11 +94,7 @@ asmlinkage void svm_intr_assist(void)
   10.14      /* Now let's check for newer interrrupts  */
   10.15      else
   10.16      {
   10.17 -        if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr )
   10.18 -        {
   10.19 -            hvm_isa_irq_deassert(current->domain, pt->irq);
   10.20 -            hvm_isa_irq_assert(current->domain, pt->irq);
   10.21 -        }
   10.22 +        pt_update_irq(v);
   10.23  
   10.24          hvm_set_callback_irq_level();
   10.25  
   10.26 @@ -130,8 +125,7 @@ asmlinkage void svm_intr_assist(void)
   10.27      case APIC_DM_FIXED:
   10.28      case APIC_DM_LOWEST:
   10.29          /* Re-injecting a PIT interruptt? */
   10.30 -        if ( re_injecting && pt->enabled && 
   10.31 -             is_periodic_irq(v, intr_vector, intr_type) )
   10.32 +        if ( re_injecting && (pt = is_pt_irq(v, intr_vector, intr_type)) )
   10.33              ++pt->pending_intr_nr;
   10.34          /* let's inject this interrupt */
   10.35          TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0);
    11.1 --- a/xen/arch/x86/hvm/svm/svm.c	Wed Dec 20 10:14:50 2006 +0000
    11.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Wed Dec 20 10:37:23 2006 +0000
    11.3 @@ -46,6 +46,7 @@
    11.4  #include <asm/hvm/svm/intr.h>
    11.5  #include <asm/x86_emulate.h>
    11.6  #include <public/sched.h>
    11.7 +#include <asm/hvm/vpt.h>
    11.8  
    11.9  #define SVM_EXTRA_DEBUG
   11.10  
   11.11 @@ -770,7 +771,6 @@ static void arch_svm_do_launch(struct vc
   11.12  
   11.13  static void svm_ctxt_switch_from(struct vcpu *v)
   11.14  {
   11.15 -    hvm_freeze_time(v);
   11.16      svm_save_dr(v);
   11.17  }
   11.18  
   11.19 @@ -1994,6 +1994,7 @@ static inline void svm_do_msr_access(
   11.20          switch (ecx)
   11.21          {
   11.22          case MSR_IA32_TIME_STAMP_COUNTER:
   11.23 +            pt_reset(v);
   11.24              hvm_set_guest_time(v, msr_content);
   11.25              break;
   11.26          case MSR_IA32_SYSENTER_CS:
    12.1 --- a/xen/arch/x86/hvm/vlapic.c	Wed Dec 20 10:14:50 2006 +0000
    12.2 +++ b/xen/arch/x86/hvm/vlapic.c	Wed Dec 20 10:37:23 2006 +0000
    12.3 @@ -154,16 +154,6 @@ int vlapic_set_irq(struct vlapic *vlapic
    12.4      return ret;
    12.5  }
    12.6  
    12.7 -s_time_t get_apictime_scheduled(struct vcpu *v)
    12.8 -{
    12.9 -    struct vlapic *vlapic = vcpu_vlapic(v);
   12.10 -
   12.11 -    if ( !vlapic_lvt_enabled(vlapic, APIC_LVTT) )
   12.12 -        return -1;
   12.13 -
   12.14 -    return vlapic->vlapic_timer.expires;
   12.15 -}
   12.16 -
   12.17  int vlapic_find_highest_isr(struct vlapic *vlapic)
   12.18  {
   12.19      int result;
   12.20 @@ -836,23 +826,6 @@ int cpu_get_apic_interrupt(struct vcpu *
   12.21      return highest_irr;
   12.22  }
   12.23  
   12.24 -/* check to see if there is pending interrupt  */
   12.25 -int cpu_has_pending_irq(struct vcpu *v)
   12.26 -{
   12.27 -    struct hvm_domain *plat = &v->domain->arch.hvm_domain;
   12.28 -    int dummy;
   12.29 -
   12.30 -    /* APIC */
   12.31 -    if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
   12.32 -        return 1;
   12.33 -
   12.34 -    /* PIC */
   12.35 -    if ( !vlapic_accept_pic_intr(v) )
   12.36 -        return 0;
   12.37 -
   12.38 -    return plat->irq.vpic[0].int_output;
   12.39 -}
   12.40 -
   12.41  void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
   12.42  {
   12.43      struct vlapic *vlapic = vcpu_vlapic(v);
    13.1 --- a/xen/arch/x86/hvm/vmx/intr.c	Wed Dec 20 10:14:50 2006 +0000
    13.2 +++ b/xen/arch/x86/hvm/vmx/intr.c	Wed Dec 20 10:37:23 2006 +0000
    13.3 @@ -91,17 +91,11 @@ asmlinkage void vmx_intr_assist(void)
    13.4      int highest_vector;
    13.5      unsigned long eflags;
    13.6      struct vcpu *v = current;
    13.7 -    struct hvm_domain *plat=&v->domain->arch.hvm_domain;
    13.8 -    struct periodic_time *pt = &plat->pl_time.periodic_tm;
    13.9      unsigned int idtv_info_field;
   13.10      unsigned long inst_len;
   13.11      int    has_ext_irq;
   13.12  
   13.13 -    if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr )
   13.14 -    {
   13.15 -        hvm_isa_irq_deassert(current->domain, pt->irq);
   13.16 -        hvm_isa_irq_assert(current->domain, pt->irq);
   13.17 -    }
   13.18 +    pt_update_irq(v);
   13.19  
   13.20      hvm_set_callback_irq_level();
   13.21  
    14.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Dec 20 10:14:50 2006 +0000
    14.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Dec 20 10:37:23 2006 +0000
    14.3 @@ -46,6 +46,7 @@
    14.4  #include <asm/hvm/vpic.h>
    14.5  #include <asm/hvm/vlapic.h>
    14.6  #include <asm/x86_emulate.h>
    14.7 +#include <asm/hvm/vpt.h>
    14.8  
    14.9  static void vmx_ctxt_switch_from(struct vcpu *v);
   14.10  static void vmx_ctxt_switch_to(struct vcpu *v);
   14.11 @@ -372,8 +373,6 @@ static inline void vmx_restore_dr(struct
   14.12  
   14.13  static void vmx_ctxt_switch_from(struct vcpu *v)
   14.14  {
   14.15 -    hvm_freeze_time(v);
   14.16 -
   14.17      /* NB. MSR_SHADOW_GS_BASE may be changed by swapgs instrucion in guest,
   14.18       * so we must save it. */
   14.19      rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.msr_state.shadow_gs);
   14.20 @@ -2072,13 +2071,7 @@ static inline int vmx_do_msr_write(struc
   14.21  
   14.22      switch (ecx) {
   14.23      case MSR_IA32_TIME_STAMP_COUNTER:
   14.24 -        {
   14.25 -            struct periodic_time *pt =
   14.26 -                &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
   14.27 -            if ( pt->enabled && pt->first_injected
   14.28 -                    && v->vcpu_id == pt->bind_vcpu )
   14.29 -                pt->first_injected = 0;
   14.30 -        }
   14.31 +        pt_reset(v);
   14.32          hvm_set_guest_time(v, msr_content);
   14.33          break;
   14.34      case MSR_IA32_SYSENTER_CS:
    15.1 --- a/xen/arch/x86/hvm/vpic.c	Wed Dec 20 10:14:50 2006 +0000
    15.2 +++ b/xen/arch/x86/hvm/vpic.c	Wed Dec 20 10:37:23 2006 +0000
    15.3 @@ -445,19 +445,3 @@ int cpu_get_pic_interrupt(struct vcpu *v
    15.4      *type = APIC_DM_EXTINT;
    15.5      return vector;
    15.6  }
    15.7 -
    15.8 -int is_periodic_irq(struct vcpu *v, int irq, int type)
    15.9 -{
   15.10 -    int vec;
   15.11 -    struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
   15.12 -
   15.13 -    if ( pt->irq != 0 )
   15.14 -        return 0;
   15.15 -
   15.16 -    if ( type == APIC_DM_EXTINT )
   15.17 -        vec = v->domain->arch.hvm_domain.irq.vpic[0].irq_base;
   15.18 -    else
   15.19 -        vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector;
   15.20 -
   15.21 -    return (irq == vec);
   15.22 -}
    16.1 --- a/xen/include/asm-x86/hvm/hvm.h	Wed Dec 20 10:14:50 2006 +0000
    16.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Wed Dec 20 10:37:23 2006 +0000
    16.3 @@ -223,7 +223,7 @@ void hvm_cpuid(unsigned int input, unsig
    16.4                                     unsigned int *ecx, unsigned int *edx);
    16.5  void hvm_stts(struct vcpu *v);
    16.6  void hvm_set_guest_time(struct vcpu *v, u64 gtime);
    16.7 -void hvm_freeze_time(struct vcpu *v);
    16.8 +u64 hvm_get_guest_time(struct vcpu *v);
    16.9  void hvm_migrate_timers(struct vcpu *v);
   16.10  void hvm_do_resume(struct vcpu *v);
   16.11  
    17.1 --- a/xen/include/asm-x86/hvm/io.h	Wed Dec 20 10:14:50 2006 +0000
    17.2 +++ b/xen/include/asm-x86/hvm/io.h	Wed Dec 20 10:37:23 2006 +0000
    17.3 @@ -147,8 +147,6 @@ extern void send_pio_req(unsigned long p
    17.4  extern void handle_mmio(unsigned long gpa);
    17.5  extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
    17.6  extern void hvm_io_assist(struct vcpu *v);
    17.7 -extern int cpu_get_interrupt(struct vcpu *v, int *type);
    17.8 -extern int cpu_has_pending_irq(struct vcpu *v);
    17.9  
   17.10  #endif /* __ASM_X86_HVM_IO_H__ */
   17.11  
    18.1 --- a/xen/include/asm-x86/hvm/irq.h	Wed Dec 20 10:14:50 2006 +0000
    18.2 +++ b/xen/include/asm-x86/hvm/irq.h	Wed Dec 20 10:37:23 2006 +0000
    18.3 @@ -104,4 +104,9 @@ void hvm_set_pci_link_route(struct domai
    18.4  void hvm_set_callback_irq_level(void);
    18.5  void hvm_set_callback_gsi(struct domain *d, unsigned int gsi);
    18.6  
    18.7 +int cpu_get_interrupt(struct vcpu *v, int *type);
    18.8 +int cpu_has_pending_irq(struct vcpu *v);
    18.9 +int get_intr_vector(struct vcpu* vcpu, int irq, int type);
   18.10 +int is_irq_masked(struct vcpu *v, int irq);
   18.11 +
   18.12  #endif /* __ASM_X86_HVM_IRQ_H__ */
    19.1 --- a/xen/include/asm-x86/hvm/vcpu.h	Wed Dec 20 10:14:50 2006 +0000
    19.2 +++ b/xen/include/asm-x86/hvm/vcpu.h	Wed Dec 20 10:37:23 2006 +0000
    19.3 @@ -35,6 +35,7 @@ struct hvm_vcpu {
    19.4      struct vlapic       vlapic;
    19.5      s64                 cache_tsc_offset;
    19.6      u64                 guest_time;
    19.7 +    struct list_head    tm_list;
    19.8  
    19.9      /* For AP startup */
   19.10      unsigned long       init_sipi_sipi_state;
    20.1 --- a/xen/include/asm-x86/hvm/vlapic.h	Wed Dec 20 10:14:50 2006 +0000
    20.2 +++ b/xen/include/asm-x86/hvm/vlapic.h	Wed Dec 20 10:37:23 2006 +0000
    20.3 @@ -89,8 +89,6 @@ int vlapic_accept_pic_intr(struct vcpu *
    20.4  struct vlapic *apic_round_robin(
    20.5      struct domain *d, uint8_t vector, uint32_t bitmap);
    20.6  
    20.7 -s_time_t get_apictime_scheduled(struct vcpu *v);
    20.8 -
    20.9  int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
   20.10  
   20.11  #endif /* __ASM_X86_HVM_VLAPIC_H__ */
    21.1 --- a/xen/include/asm-x86/hvm/vpt.h	Wed Dec 20 10:14:50 2006 +0000
    21.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Wed Dec 20 10:37:23 2006 +0000
    21.3 @@ -27,11 +27,33 @@
    21.4  #include <xen/errno.h>
    21.5  #include <xen/time.h>
    21.6  #include <xen/timer.h>
    21.7 +#include <xen/list.h>
    21.8  #include <asm/hvm/vpic.h>
    21.9  
   21.10  #define PIT_FREQ 1193181
   21.11  #define PIT_BASE 0x40
   21.12  
   21.13 +/*
   21.14 + * Abstract layer of periodic time, one short time.
   21.15 + */
   21.16 +typedef void time_cb(struct vcpu *v, void *opaque);
   21.17 +
   21.18 +struct periodic_time {
   21.19 +    struct list_head list;
   21.20 +    char enabled;
   21.21 +    char one_shot;              /* one shot time */
   21.22 +    int irq;
   21.23 +    struct vcpu *vcpu;          /* vcpu timer interrupt delivers to */
   21.24 +    u32 pending_intr_nr;        /* the couner for pending timer interrupts */
   21.25 +    u32 period;                 /* frequency in ns */
   21.26 +    u64 period_cycles;          /* frequency in cpu cycles */
   21.27 +    s_time_t scheduled;         /* scheduled timer interrupt */
   21.28 +    u64 last_plt_gtime;         /* platform time when last IRQ is injected */
   21.29 +    struct timer timer;         /* ac_timer */
   21.30 +    time_cb *cb;
   21.31 +    void *priv;                 /* ponit back to platform time source */
   21.32 +};
   21.33 +
   21.34  typedef struct PITChannelState {
   21.35      int count; /* can be 65536 */
   21.36      u16 latched_count;
   21.37 @@ -47,8 +69,7 @@ typedef struct PITChannelState {
   21.38      u8 gate; /* timer start */
   21.39      s64 count_load_time;
   21.40      /* irq handling */
   21.41 -    struct vcpu      *vcpu;
   21.42 -    struct periodic_time *pt;
   21.43 +    struct periodic_time pt;
   21.44  } PITChannelState;
   21.45  
   21.46  typedef struct PITState {
   21.47 @@ -66,10 +87,7 @@ typedef struct RTCState {
   21.48      int64_t next_second_time;
   21.49      struct timer second_timer;
   21.50      struct timer second_timer2;
   21.51 -    struct timer pie_timer;
   21.52 -    int period;
   21.53 -    s_time_t next_pie;
   21.54 -    struct vcpu      *vcpu;
   21.55 +    struct periodic_time pt;
   21.56  } RTCState;
   21.57  
   21.58  #define FREQUENCE_PMTIMER  3579545
   21.59 @@ -82,58 +100,35 @@ typedef struct PMTState {
   21.60      struct vcpu *vcpu;
   21.61  } PMTState;
   21.62  
   21.63 -/*
   21.64 - * Abstract layer of periodic time, one short time.
   21.65 - */
   21.66 -typedef void time_cb(struct vcpu *v, void *opaque);
   21.67 -
   21.68 -struct periodic_time {
   21.69 -    char enabled;               /* enabled */
   21.70 -    char one_shot;              /* one shot time */
   21.71 -    char irq;
   21.72 -    char first_injected;        /* flag to prevent shadow window */
   21.73 -    u32 bind_vcpu;              /* vcpu timer interrupt delivers to */
   21.74 -    u32 pending_intr_nr;        /* the couner for pending timer interrupts */
   21.75 -    u32 period;                 /* frequency in ns */
   21.76 -    u64 period_cycles;          /* frequency in cpu cycles */
   21.77 -    s_time_t scheduled;         /* scheduled timer interrupt */
   21.78 -    u64 last_plt_gtime;         /* platform time when last IRQ is injected */
   21.79 -    struct timer timer;         /* ac_timer */
   21.80 -    time_cb *cb;
   21.81 -    void *priv;                 /* ponit back to platform time source */
   21.82 +struct pl_time {    /* platform time */
   21.83 +    struct PITState  vpit;
   21.84 +    struct RTCState  vrtc;
   21.85 +    struct PMTState  vpmt;
   21.86  };
   21.87  
   21.88 -struct pl_time {    /* platform time */
   21.89 -    struct periodic_time periodic_tm;
   21.90 -    struct PITState      vpit;
   21.91 -    struct RTCState      vrtc;
   21.92 -    struct PMTState      vpmt;
   21.93 -};
   21.94 -
   21.95 -extern u64 hvm_get_guest_time(struct vcpu *v);
   21.96 -static inline int64_t hvm_get_clock(struct vcpu *v)
   21.97 -{
   21.98 -    return hvm_get_guest_time(v);
   21.99 -}
  21.100 -
  21.101  #define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
  21.102  
  21.103 -/* to hook the ioreq packet to get the PIT initialization info */
  21.104 -extern void hvm_hooks_assist(struct vcpu *v);
  21.105 -extern void pickup_deactive_ticks(struct periodic_time *vpit);
  21.106 -extern struct periodic_time *create_periodic_time(
  21.107 -    u32 period, char irq, char one_shot, time_cb *cb, void *data);
  21.108 -extern void destroy_periodic_time(struct periodic_time *pt);
  21.109 +void pt_freeze_time(struct vcpu *v);
  21.110 +void pt_thaw_time(struct vcpu *v);
  21.111 +void pt_timer_fn(void *data);
  21.112 +void pt_update_irq(struct vcpu *v);
  21.113 +struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
  21.114 +void pt_intr_post(struct vcpu *v, int vector, int type);
  21.115 +void pt_reset(struct vcpu *v);
  21.116 +void create_periodic_time(struct periodic_time *pt, u32 period, char irq, 
  21.117 +                          char one_shot, time_cb *cb, void *data);
  21.118 +void destroy_periodic_time(struct periodic_time *pt);
  21.119 +
  21.120  int pv_pit_handler(int port, int data, int write);
  21.121  void pit_init(struct vcpu *v, unsigned long cpu_khz);
  21.122 +void pit_migrate_timers(struct vcpu *v);
  21.123 +void pit_deinit(struct domain *d);
  21.124  void rtc_init(struct vcpu *v, int base, int irq);
  21.125 -void rtc_deinit(struct domain *d);
  21.126 -void rtc_freeze(struct vcpu *v);
  21.127 -void rtc_thaw(struct vcpu *v);
  21.128  void rtc_migrate_timers(struct vcpu *v);
  21.129 +void rtc_deinit(struct domain *d);
  21.130 +int is_rtc_periodic_irq(void *opaque);
  21.131  void pmtimer_init(struct vcpu *v, int base);
  21.132 +void pmtimer_migrate_timers(struct vcpu *v);
  21.133  void pmtimer_deinit(struct domain *d);
  21.134 -void pt_timer_fn(void *data);
  21.135 -void pit_time_fired(struct vcpu *v, void *priv);
  21.136  
  21.137  #endif /* __ASM_X86_HVM_VPT_H__ */