ia64/xen-unstable
changeset 13132: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>
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>
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__ */