[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Enable more than one platform timer (PIT/RTC/HPET)
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1166611043 0 # Node ID 2a1edeedf28d9c72492255fba638fbca61da7ee3 # Parent b17d1bc1febf265b3700dbd34d511947c0cd02e2 [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@xxxxxxxxx> Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx> --- xen/arch/x86/domain.c | 3 + xen/arch/x86/hvm/Makefile | 1 xen/arch/x86/hvm/hvm.c | 67 ++-------------------------- xen/arch/x86/hvm/i8254.c | 53 +++++++++++++++------- xen/arch/x86/hvm/intercept.c | 92 -------------------------------------- xen/arch/x86/hvm/io.c | 20 -------- xen/arch/x86/hvm/irq.c | 48 ++++++++++++++++++++ xen/arch/x86/hvm/pmtimer.c | 8 +++ xen/arch/x86/hvm/rtc.c | 80 +++++++++++++-------------------- xen/arch/x86/hvm/svm/intr.c | 12 +---- xen/arch/x86/hvm/svm/svm.c | 3 - xen/arch/x86/hvm/vlapic.c | 27 ----------- xen/arch/x86/hvm/vmx/intr.c | 8 --- xen/arch/x86/hvm/vmx/vmx.c | 11 ---- xen/arch/x86/hvm/vpic.c | 16 ------ xen/include/asm-x86/hvm/hvm.h | 2 xen/include/asm-x86/hvm/io.h | 2 xen/include/asm-x86/hvm/irq.h | 5 ++ xen/include/asm-x86/hvm/vcpu.h | 1 xen/include/asm-x86/hvm/vlapic.h | 2 xen/include/asm-x86/hvm/vpt.h | 93 ++++++++++++++++++--------------------- 21 files changed, 196 insertions(+), 358 deletions(-) diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/domain.c Wed Dec 20 10:37:23 2006 +0000 @@ -726,6 +726,9 @@ void context_switch(struct vcpu *prev, s local_irq_disable(); + if ( is_hvm_vcpu(prev) ) + pt_freeze_time(prev); + set_current(next); if ( (per_cpu(curr_vcpu, cpu) == next) || is_idle_vcpu(next) ) diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/Makefile --- a/xen/arch/x86/hvm/Makefile Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/Makefile Wed Dec 20 10:37:23 2006 +0000 @@ -10,6 +10,7 @@ obj-y += platform.o obj-y += platform.o obj-y += pmtimer.o obj-y += rtc.o +obj-y += vpt.o obj-y += vioapic.o obj-y += vlapic.o obj-y += vpic.o diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/hvm.c Wed Dec 20 10:37:23 2006 +0000 @@ -82,56 +82,21 @@ u64 hvm_get_guest_time(struct vcpu *v) return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset; } -void hvm_freeze_time(struct vcpu *v) -{ - struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm; - - if ( pt->enabled && pt->first_injected - && (v->vcpu_id == pt->bind_vcpu) - && !v->arch.hvm_vcpu.guest_time ) { - v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v); - if ( !test_bit(_VCPUF_blocked, &v->vcpu_flags) ) - { - stop_timer(&pt->timer); - rtc_freeze(v); - } - } -} - void hvm_migrate_timers(struct vcpu *v) { - struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; - struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; - - if ( pt->enabled ) - { - migrate_timer(&pt->timer, v->processor); - } + pit_migrate_timers(v); + rtc_migrate_timers(v); + pmtimer_migrate_timers(v); migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor); - migrate_timer(&vpmt->timer, v->processor); - rtc_migrate_timers(v); } void hvm_do_resume(struct vcpu *v) { ioreq_t *p; - struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; hvm_stts(v); - /* Pick up the elapsed PIT ticks and re-enable pit_timer. */ - if ( pt->enabled && (v->vcpu_id == pt->bind_vcpu) && pt->first_injected ) - { - if ( v->arch.hvm_vcpu.guest_time ) - { - hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time); - v->arch.hvm_vcpu.guest_time = 0; - } - pickup_deactive_ticks(pt); - } - - /* Re-enable the RTC timer if needed */ - rtc_thaw(v); + pt_thaw_time(v); /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */ p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; @@ -182,7 +147,7 @@ int hvm_domain_initialise(struct domain void hvm_domain_destroy(struct domain *d) { - kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer); + pit_deinit(d); rtc_deinit(d); pmtimer_deinit(d); @@ -196,7 +161,6 @@ void hvm_domain_destroy(struct domain *d int hvm_vcpu_initialise(struct vcpu *v) { - struct hvm_domain *platform; int rc; if ( (rc = vlapic_init(v)) != 0 ) @@ -214,14 +178,11 @@ int hvm_vcpu_initialise(struct vcpu *v) get_vio(v->domain, v->vcpu_id)->vp_eport = v->arch.hvm_vcpu.xen_port; + INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list); + if ( v->vcpu_id != 0 ) return 0; - /* XXX Below should happen in hvm_domain_initialise(). */ - platform = &v->domain->arch.hvm_domain; - - init_timer(&platform->pl_time.periodic_tm.timer, - pt_timer_fn, v, v->processor); rtc_init(v, RTC_PORT(0), RTC_IRQ); pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); @@ -238,20 +199,6 @@ void hvm_vcpu_destroy(struct vcpu *v) /* Event channel is already freed by evtchn_destroy(). */ /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/ -} - -int cpu_get_interrupt(struct vcpu *v, int *type) -{ - int vector; - - if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 ) - return vector; - - if ( (v->vcpu_id == 0) && - ((vector = cpu_get_pic_interrupt(v, type)) != -1) ) - return vector; - - return -1; } static void hvm_vcpu_down(void) diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/i8254.c Wed Dec 20 10:37:23 2006 +0000 @@ -81,7 +81,7 @@ static int pit_get_count(PITChannelState uint64_t d; int counter; - d = muldiv64(hvm_get_clock(s->vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->vcpu)); + d = muldiv64(hvm_get_guest_time(s->pt.vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu)); switch(s->mode) { case 0: case 1: @@ -106,7 +106,7 @@ static int pit_get_out1(PITChannelState uint64_t d; int out; - d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->vcpu)); + d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu)); switch(s->mode) { default: case 0: @@ -153,7 +153,7 @@ void pit_set_gate(PITState *pit, int cha case 5: if (s->gate < val) { /* restart counting on rising edge */ - s->count_load_time = hvm_get_clock(s->vcpu); + s->count_load_time = hvm_get_guest_time(s->pt.vcpu); // pit_irq_timer_update(s, s->count_load_time); } break; @@ -161,7 +161,7 @@ void pit_set_gate(PITState *pit, int cha case 3: if (s->gate < val) { /* restart counting on rising edge */ - s->count_load_time = hvm_get_clock(s->vcpu); + s->count_load_time = hvm_get_guest_time(s->pt.vcpu); // pit_irq_timer_update(s, s->count_load_time); } /* XXX: disable/enable counting */ @@ -179,7 +179,7 @@ void pit_time_fired(struct vcpu *v, void void pit_time_fired(struct vcpu *v, void *priv) { PITChannelState *s = priv; - s->count_load_time = hvm_get_clock(v); + s->count_load_time = hvm_get_guest_time(v); } static inline void pit_load_count(PITChannelState *s, int val) @@ -190,7 +190,7 @@ static inline void pit_load_count(PITCha if (val == 0) val = 0x10000; - s->count_load_time = hvm_get_clock(s->vcpu); + s->count_load_time = hvm_get_guest_time(s->pt.vcpu); s->count = val; period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ); @@ -209,16 +209,17 @@ static inline void pit_load_count(PITCha switch (s->mode) { case 2: /* create periodic time */ - s->pt = create_periodic_time (period, 0, 0, pit_time_fired, s); + create_periodic_time(&s->pt, period, 0, 0, pit_time_fired, s); break; case 1: /* create one shot time */ - s->pt = create_periodic_time (period, 0, 1, pit_time_fired, s); + create_periodic_time(&s->pt, period, 0, 1, pit_time_fired, s); #ifdef DEBUG_PIT printk("HVM_PIT: create one shot time.\n"); #endif break; default: + destroy_periodic_time(&s->pt); break; } } @@ -253,7 +254,7 @@ static void pit_ioport_write(void *opaqu if (!(val & 0x10) && !s->status_latched) { /* status latch */ /* XXX: add BCD and null count */ - s->status = (pit_get_out1(s, hvm_get_clock(s->vcpu)) << 7) | + s->status = (pit_get_out1(s, hvm_get_guest_time(s->pt.vcpu)) << 7) | (s->rw_mode << 4) | (s->mode << 1) | s->bcd; @@ -359,10 +360,7 @@ static void pit_reset(void *opaque) for(i = 0;i < 3; i++) { s = &pit->channels[i]; - if ( s -> pt ) { - destroy_periodic_time (s->pt); - s->pt = NULL; - } + destroy_periodic_time(&s->pt); s->mode = 0xff; /* the init mode */ s->gate = (i != 2); pit_load_count(s, 0); @@ -375,10 +373,11 @@ void pit_init(struct vcpu *v, unsigned l PITChannelState *s; s = &pit->channels[0]; + s->pt.vcpu = v; /* the timer 0 is connected to an IRQ */ - s->vcpu = v; - s++; s->vcpu = v; - s++; s->vcpu = v; + init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor); + s++; s->pt.vcpu = v; + s++; s->pt.vcpu = v; register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io); /* register the speaker port */ @@ -391,6 +390,25 @@ void pit_init(struct vcpu *v, unsigned l return; } +void pit_migrate_timers(struct vcpu *v) +{ + PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit; + PITChannelState *s; + + s = &pit->channels[0]; + if ( s->pt.vcpu == v && s->pt.enabled ) + migrate_timer(&s->pt.timer, v->processor); +} + +void pit_deinit(struct domain *d) +{ + PITState *pit = &d->arch.hvm_domain.pl_time.vpit; + PITChannelState *s; + + s = &pit->channels[0]; + kill_timer(&s->pt.timer); +} + /* the intercept action for PIT DM retval:0--not handled; 1--handled */ static int handle_pit_io(ioreq_t *p) { @@ -426,7 +444,8 @@ static uint32_t speaker_ioport_read(void static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) { PITState *pit = opaque; - int out = pit_get_out(pit, 2, hvm_get_clock(pit->channels[2].vcpu)); + int out = pit_get_out(pit, 2, + hvm_get_guest_time(pit->channels[2].pt.vcpu)); /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1; return ((pit->speaker_data_on << 1) | pit_get_gate(pit, 2) | diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/intercept.c --- a/xen/arch/x86/hvm/intercept.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/intercept.c Wed Dec 20 10:37:23 2006 +0000 @@ -263,98 +263,6 @@ int register_io_handler( return 1; } - -static __inline__ void missed_ticks(struct periodic_time *pt) -{ - s_time_t missed_ticks; - - missed_ticks = NOW() - pt->scheduled; - if ( missed_ticks > 0 ) { - missed_ticks = missed_ticks / (s_time_t) pt->period + 1; - if ( missed_ticks > 1000 ) { - /* TODO: Adjust guest time togther */ - pt->pending_intr_nr++; - } - else { - pt->pending_intr_nr += missed_ticks; - } - pt->scheduled += missed_ticks * pt->period; - } -} - -/* hook function for the platform periodic time */ -void pt_timer_fn(void *data) -{ - struct vcpu *v = data; - struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; - - pt->pending_intr_nr++; - pt->scheduled += pt->period; - - /* Pick up missed timer ticks. */ - missed_ticks(pt); - - /* No need to run the timer while a VCPU is descheduled. */ - if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) - set_timer(&pt->timer, pt->scheduled); - - vcpu_kick(v); -} - -/* pick up missed timer ticks at deactive time */ -void pickup_deactive_ticks(struct periodic_time *pt) -{ - if ( !active_timer(&(pt->timer)) ) { - missed_ticks(pt); - set_timer(&pt->timer, pt->scheduled); - } -} - -/* - * period: fire frequency in ns. - */ -struct periodic_time * create_periodic_time( - u32 period, - char irq, - char one_shot, - time_cb *cb, - void *data) -{ - struct periodic_time *pt = &(current->domain->arch.hvm_domain.pl_time.periodic_tm); - if ( pt->enabled ) { - stop_timer (&pt->timer); - pt->enabled = 0; - } - pt->bind_vcpu = 0; /* timer interrupt delivered to BSP by default */ - pt->pending_intr_nr = 0; - pt->first_injected = 0; - if (period < 900000) { /* < 0.9 ms */ - printk("HVM_PlatformTime: program too small period %u\n",period); - period = 900000; /* force to 0.9ms */ - } - pt->period = period; - pt->irq = irq; - pt->period_cycles = (u64)period * cpu_khz / 1000000L; - pt->one_shot = one_shot; - if ( one_shot ) { - printk("HVM_PL: No support for one shot platform time yet\n"); - } - pt->scheduled = NOW() + period; - set_timer (&pt->timer,pt->scheduled); - pt->enabled = 1; - pt->cb = cb; - pt->priv = data; - return pt; -} - -void destroy_periodic_time(struct periodic_time *pt) -{ - if ( pt->enabled ) { - stop_timer(&pt->timer); - pt->enabled = 0; - } -} - /* * Local variables: * mode: C diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/io.c Wed Dec 20 10:37:23 2006 +0000 @@ -691,25 +691,7 @@ static void hvm_mmio_assist(struct cpu_u void hvm_interrupt_post(struct vcpu *v, int vector, int type) { - struct periodic_time *pt = - &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - - if ( pt->enabled && v->vcpu_id == pt->bind_vcpu - && is_periodic_irq(v, vector, type) ) { - if ( !pt->first_injected ) { - pt->pending_intr_nr = 0; - pt->last_plt_gtime = hvm_get_guest_time(v); - pt->scheduled = NOW() + pt->period; - set_timer(&pt->timer, pt->scheduled); - pt->first_injected = 1; - } else { - pt->pending_intr_nr--; - pt->last_plt_gtime += pt->period_cycles; - hvm_set_guest_time(v, pt->last_plt_gtime); - } - if (pt->cb) - pt->cb(v, pt->priv); - } + pt_intr_post(v, vector, type); switch(type) { case APIC_DM_EXTINT: diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/irq.c --- a/xen/arch/x86/hvm/irq.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/irq.c Wed Dec 20 10:37:23 2006 +0000 @@ -225,3 +225,51 @@ void hvm_set_callback_gsi(struct domain dprintk(XENLOG_G_INFO, "Dom%u callback GSI changed %u -> %u\n", d->domain_id, old_gsi, gsi); } + +int cpu_has_pending_irq(struct vcpu *v) +{ + struct hvm_domain *plat = &v->domain->arch.hvm_domain; + int dummy; + + /* APIC */ + if ( cpu_get_apic_interrupt(v, &dummy) != -1 ) + return 1; + + /* PIC */ + if ( !vlapic_accept_pic_intr(v) ) + return 0; + + return plat->irq.vpic[0].int_output; +} + +int cpu_get_interrupt(struct vcpu *v, int *type) +{ + int vector; + + if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 ) + return vector; + + if ( (v->vcpu_id == 0) && + ((vector = cpu_get_pic_interrupt(v, type)) != -1) ) + return vector; + + return -1; +} + +int get_intr_vector(struct vcpu* v, int irq, int type) +{ + if ( type == APIC_DM_EXTINT ) + return v->domain->arch.hvm_domain.irq.vpic[irq >> 3].irq_base + + (irq & 0x7); + + return domain_vioapic(v->domain)->redirtbl[irq].fields.vector; +} + +int is_irq_masked(struct vcpu *v, int irq) +{ + if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7)) + && domain_vioapic(v->domain)->redirtbl[irq].fields.mask ) + return 1; + + return 0; +} diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/pmtimer.c --- a/xen/arch/x86/hvm/pmtimer.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/pmtimer.c Wed Dec 20 10:37:23 2006 +0000 @@ -55,6 +55,14 @@ void pmtimer_init(struct vcpu *v, int ba register_portio_handler(v->domain, base, 4, handle_pmt_io); } +void pmtimer_migrate_timers(struct vcpu *v) +{ + struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; + + if (vpmt->vcpu == v) + migrate_timer(&vpmt->timer, v->processor); +} + void pmtimer_deinit(struct domain *d) { PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/rtc.c --- a/xen/arch/x86/hvm/rtc.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/rtc.c Wed Dec 20 10:37:23 2006 +0000 @@ -30,17 +30,18 @@ /* #define DEBUG_RTC */ -/* Callback that fires the RTC's periodic interrupt */ -void rtc_pie_callback(void *opaque) -{ - RTCState *s = opaque; - /* Record that we have fired */ - s->cmos_data[RTC_REG_C] |= (RTC_IRQF|RTC_PF); /* 0xc0 */ - /* Fire */ - hvm_isa_irq_assert(s->vcpu->domain, s->irq); - /* Remember to fire again */ - s->next_pie = NOW() + s->period; - set_timer(&s->pie_timer, s->next_pie); +void rtc_periodic_cb(struct vcpu *v, void *opaque) +{ + RTCState *s = opaque; + s->cmos_data[RTC_REG_C] |= 0xc0; +} + +int is_rtc_periodic_irq(void *opaque) +{ + RTCState *s = opaque; + + return !(s->cmos_data[RTC_REG_C] & RTC_AF || + s->cmos_data[RTC_REG_C] & RTC_UF); } /* Enable/configure/disable the periodic timer based on the RTC_PIE and @@ -58,17 +59,13 @@ static void rtc_timer_update(RTCState *s period = 1 << (period_code - 1); /* period in 32 Khz cycles */ period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */ - s->period = period; #ifdef DEBUG_RTC printk("HVM_RTC: period = %uns\n", period); #endif - s->next_pie = NOW() + s->period; - set_timer(&s->pie_timer, s->next_pie); - } - else - { - stop_timer(&s->pie_timer); - } + create_periodic_time(&s->pt, period, RTC_IRQ, 0, rtc_periodic_cb, s); + } + else + destroy_periodic_time(&s->pt); } static void rtc_set_time(RTCState *s); @@ -292,8 +289,8 @@ static void rtc_update_second2(void *opa s->current_tm.tm_hour) ) { s->cmos_data[RTC_REG_C] |= 0xa0; - hvm_isa_irq_deassert(s->vcpu->domain, s->irq); - hvm_isa_irq_assert(s->vcpu->domain, s->irq); + hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq); + hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq); } } @@ -301,8 +298,8 @@ static void rtc_update_second2(void *opa if ( s->cmos_data[RTC_REG_B] & RTC_UIE ) { s->cmos_data[RTC_REG_C] |= 0x90; - hvm_isa_irq_deassert(s->vcpu->domain, s->irq); - hvm_isa_irq_assert(s->vcpu->domain, s->irq); + hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq); + hvm_isa_irq_assert(s->pt.vcpu->domain, s->irq); } /* clear update in progress bit */ @@ -336,7 +333,7 @@ static uint32_t rtc_ioport_read(void *op break; case RTC_REG_C: ret = s->cmos_data[s->cmos_index]; - hvm_isa_irq_deassert(s->vcpu->domain, s->irq); + hvm_isa_irq_deassert(s->pt.vcpu->domain, s->irq); s->cmos_data[RTC_REG_C] = 0x00; break; default: @@ -377,36 +374,25 @@ static int handle_rtc_io(ioreq_t *p) return 0; } -/* Stop the periodic interrupts from this RTC */ -void rtc_freeze(struct vcpu *v) -{ - RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc; - stop_timer(&s->pie_timer); -} - -/* Start them again */ -void rtc_thaw(struct vcpu *v) -{ - RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc; - if ( (s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT) /* Period is not zero */ - && (s->cmos_data[RTC_REG_B] & RTC_PIE) ) - set_timer(&s->pie_timer, s->next_pie); -} - /* Move the RTC timers on to this vcpu's current cpu */ void rtc_migrate_timers(struct vcpu *v) { RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc; - migrate_timer(&s->second_timer, v->processor); - migrate_timer(&s->second_timer2, v->processor); - migrate_timer(&s->pie_timer, v->processor); + + if ( s->pt.vcpu == v ) + { + if ( s->pt.enabled ) + migrate_timer(&s->pt.timer, v->processor); + migrate_timer(&s->second_timer, v->processor); + migrate_timer(&s->second_timer2, v->processor); + } } void rtc_init(struct vcpu *v, int base, int irq) { RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc; - s->vcpu = v; + s->pt.vcpu = v; s->irq = irq; s->cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */ s->cmos_data[RTC_REG_B] = RTC_24H; @@ -416,9 +402,9 @@ void rtc_init(struct vcpu *v, int base, s->current_tm = gmtime(get_localtime(v->domain)); rtc_copy_date(s); + init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor); init_timer(&s->second_timer, rtc_update_second, s, v->processor); init_timer(&s->second_timer2, rtc_update_second2, s, v->processor); - init_timer(&s->pie_timer, rtc_pie_callback, s, v->processor); s->next_second_time = NOW() + 1000000000ULL; set_timer(&s->second_timer2, s->next_second_time); @@ -430,7 +416,7 @@ void rtc_deinit(struct domain *d) { RTCState *s = &d->arch.hvm_domain.pl_time.vrtc; + kill_timer(&s->pt.timer); kill_timer(&s->second_timer); kill_timer(&s->second_timer2); - kill_timer(&s->pie_timer); -} +} diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/svm/intr.c --- a/xen/arch/x86/hvm/svm/intr.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/svm/intr.c Wed Dec 20 10:37:23 2006 +0000 @@ -63,8 +63,7 @@ asmlinkage void svm_intr_assist(void) { struct vcpu *v = current; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - struct hvm_domain *plat=&v->domain->arch.hvm_domain; - struct periodic_time *pt = &plat->pl_time.periodic_tm; + struct periodic_time *pt; int intr_type = APIC_DM_EXTINT; int intr_vector = -1; int re_injecting = 0; @@ -95,11 +94,7 @@ asmlinkage void svm_intr_assist(void) /* Now let's check for newer interrrupts */ else { - if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr ) - { - hvm_isa_irq_deassert(current->domain, pt->irq); - hvm_isa_irq_assert(current->domain, pt->irq); - } + pt_update_irq(v); hvm_set_callback_irq_level(); @@ -130,8 +125,7 @@ asmlinkage void svm_intr_assist(void) case APIC_DM_FIXED: case APIC_DM_LOWEST: /* Re-injecting a PIT interruptt? */ - if ( re_injecting && pt->enabled && - is_periodic_irq(v, intr_vector, intr_type) ) + if ( re_injecting && (pt = is_pt_irq(v, intr_vector, intr_type)) ) ++pt->pending_intr_nr; /* let's inject this interrupt */ TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0); diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Dec 20 10:37:23 2006 +0000 @@ -46,6 +46,7 @@ #include <asm/hvm/svm/intr.h> #include <asm/x86_emulate.h> #include <public/sched.h> +#include <asm/hvm/vpt.h> #define SVM_EXTRA_DEBUG @@ -770,7 +771,6 @@ static void arch_svm_do_launch(struct vc static void svm_ctxt_switch_from(struct vcpu *v) { - hvm_freeze_time(v); svm_save_dr(v); } @@ -1994,6 +1994,7 @@ static inline void svm_do_msr_access( switch (ecx) { case MSR_IA32_TIME_STAMP_COUNTER: + pt_reset(v); hvm_set_guest_time(v, msr_content); break; case MSR_IA32_SYSENTER_CS: diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/vlapic.c Wed Dec 20 10:37:23 2006 +0000 @@ -154,16 +154,6 @@ int vlapic_set_irq(struct vlapic *vlapic return ret; } -s_time_t get_apictime_scheduled(struct vcpu *v) -{ - struct vlapic *vlapic = vcpu_vlapic(v); - - if ( !vlapic_lvt_enabled(vlapic, APIC_LVTT) ) - return -1; - - return vlapic->vlapic_timer.expires; -} - int vlapic_find_highest_isr(struct vlapic *vlapic) { int result; @@ -836,23 +826,6 @@ int cpu_get_apic_interrupt(struct vcpu * return highest_irr; } -/* check to see if there is pending interrupt */ -int cpu_has_pending_irq(struct vcpu *v) -{ - struct hvm_domain *plat = &v->domain->arch.hvm_domain; - int dummy; - - /* APIC */ - if ( cpu_get_apic_interrupt(v, &dummy) != -1 ) - return 1; - - /* PIC */ - if ( !vlapic_accept_pic_intr(v) ) - return 0; - - return plat->irq.vpic[0].int_output; -} - void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode) { struct vlapic *vlapic = vcpu_vlapic(v); diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/vmx/intr.c --- a/xen/arch/x86/hvm/vmx/intr.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/intr.c Wed Dec 20 10:37:23 2006 +0000 @@ -91,17 +91,11 @@ asmlinkage void vmx_intr_assist(void) int highest_vector; unsigned long eflags; struct vcpu *v = current; - struct hvm_domain *plat=&v->domain->arch.hvm_domain; - struct periodic_time *pt = &plat->pl_time.periodic_tm; unsigned int idtv_info_field; unsigned long inst_len; int has_ext_irq; - if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr ) - { - hvm_isa_irq_deassert(current->domain, pt->irq); - hvm_isa_irq_assert(current->domain, pt->irq); - } + pt_update_irq(v); hvm_set_callback_irq_level(); diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Dec 20 10:37:23 2006 +0000 @@ -46,6 +46,7 @@ #include <asm/hvm/vpic.h> #include <asm/hvm/vlapic.h> #include <asm/x86_emulate.h> +#include <asm/hvm/vpt.h> static void vmx_ctxt_switch_from(struct vcpu *v); static void vmx_ctxt_switch_to(struct vcpu *v); @@ -372,8 +373,6 @@ static inline void vmx_restore_dr(struct static void vmx_ctxt_switch_from(struct vcpu *v) { - hvm_freeze_time(v); - /* NB. MSR_SHADOW_GS_BASE may be changed by swapgs instrucion in guest, * so we must save it. */ rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.msr_state.shadow_gs); @@ -2072,13 +2071,7 @@ static inline int vmx_do_msr_write(struc switch (ecx) { case MSR_IA32_TIME_STAMP_COUNTER: - { - struct periodic_time *pt = - &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - if ( pt->enabled && pt->first_injected - && v->vcpu_id == pt->bind_vcpu ) - pt->first_injected = 0; - } + pt_reset(v); hvm_set_guest_time(v, msr_content); break; case MSR_IA32_SYSENTER_CS: diff -r b17d1bc1febf -r 2a1edeedf28d xen/arch/x86/hvm/vpic.c --- a/xen/arch/x86/hvm/vpic.c Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/arch/x86/hvm/vpic.c Wed Dec 20 10:37:23 2006 +0000 @@ -445,19 +445,3 @@ int cpu_get_pic_interrupt(struct vcpu *v *type = APIC_DM_EXTINT; return vector; } - -int is_periodic_irq(struct vcpu *v, int irq, int type) -{ - int vec; - struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; - - if ( pt->irq != 0 ) - return 0; - - if ( type == APIC_DM_EXTINT ) - vec = v->domain->arch.hvm_domain.irq.vpic[0].irq_base; - else - vec = domain_vioapic(v->domain)->redirtbl[0].fields.vector; - - return (irq == vec); -} diff -r b17d1bc1febf -r 2a1edeedf28d xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/include/asm-x86/hvm/hvm.h Wed Dec 20 10:37:23 2006 +0000 @@ -223,7 +223,7 @@ void hvm_cpuid(unsigned int input, unsig unsigned int *ecx, unsigned int *edx); void hvm_stts(struct vcpu *v); void hvm_set_guest_time(struct vcpu *v, u64 gtime); -void hvm_freeze_time(struct vcpu *v); +u64 hvm_get_guest_time(struct vcpu *v); void hvm_migrate_timers(struct vcpu *v); void hvm_do_resume(struct vcpu *v); diff -r b17d1bc1febf -r 2a1edeedf28d xen/include/asm-x86/hvm/io.h --- a/xen/include/asm-x86/hvm/io.h Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/include/asm-x86/hvm/io.h Wed Dec 20 10:37:23 2006 +0000 @@ -147,8 +147,6 @@ extern void handle_mmio(unsigned long gp extern void handle_mmio(unsigned long gpa); extern void hvm_interrupt_post(struct vcpu *v, int vector, int type); extern void hvm_io_assist(struct vcpu *v); -extern int cpu_get_interrupt(struct vcpu *v, int *type); -extern int cpu_has_pending_irq(struct vcpu *v); #endif /* __ASM_X86_HVM_IO_H__ */ diff -r b17d1bc1febf -r 2a1edeedf28d xen/include/asm-x86/hvm/irq.h --- a/xen/include/asm-x86/hvm/irq.h Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/include/asm-x86/hvm/irq.h Wed Dec 20 10:37:23 2006 +0000 @@ -104,4 +104,9 @@ void hvm_set_callback_irq_level(void); void hvm_set_callback_irq_level(void); void hvm_set_callback_gsi(struct domain *d, unsigned int gsi); +int cpu_get_interrupt(struct vcpu *v, int *type); +int cpu_has_pending_irq(struct vcpu *v); +int get_intr_vector(struct vcpu* vcpu, int irq, int type); +int is_irq_masked(struct vcpu *v, int irq); + #endif /* __ASM_X86_HVM_IRQ_H__ */ diff -r b17d1bc1febf -r 2a1edeedf28d xen/include/asm-x86/hvm/vcpu.h --- a/xen/include/asm-x86/hvm/vcpu.h Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/include/asm-x86/hvm/vcpu.h Wed Dec 20 10:37:23 2006 +0000 @@ -35,6 +35,7 @@ struct hvm_vcpu { struct vlapic vlapic; s64 cache_tsc_offset; u64 guest_time; + struct list_head tm_list; /* For AP startup */ unsigned long init_sipi_sipi_state; diff -r b17d1bc1febf -r 2a1edeedf28d xen/include/asm-x86/hvm/vlapic.h --- a/xen/include/asm-x86/hvm/vlapic.h Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/include/asm-x86/hvm/vlapic.h Wed Dec 20 10:37:23 2006 +0000 @@ -89,8 +89,6 @@ struct vlapic *apic_round_robin( struct vlapic *apic_round_robin( struct domain *d, uint8_t vector, uint32_t bitmap); -s_time_t get_apictime_scheduled(struct vcpu *v); - int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda); #endif /* __ASM_X86_HVM_VLAPIC_H__ */ diff -r b17d1bc1febf -r 2a1edeedf28d xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Wed Dec 20 10:14:50 2006 +0000 +++ b/xen/include/asm-x86/hvm/vpt.h Wed Dec 20 10:37:23 2006 +0000 @@ -27,10 +27,32 @@ #include <xen/errno.h> #include <xen/time.h> #include <xen/timer.h> +#include <xen/list.h> #include <asm/hvm/vpic.h> #define PIT_FREQ 1193181 #define PIT_BASE 0x40 + +/* + * Abstract layer of periodic time, one short time. + */ +typedef void time_cb(struct vcpu *v, void *opaque); + +struct periodic_time { + struct list_head list; + char enabled; + char one_shot; /* one shot time */ + int irq; + struct vcpu *vcpu; /* vcpu timer interrupt delivers to */ + u32 pending_intr_nr; /* the couner for pending timer interrupts */ + u32 period; /* frequency in ns */ + u64 period_cycles; /* frequency in cpu cycles */ + s_time_t scheduled; /* scheduled timer interrupt */ + u64 last_plt_gtime; /* platform time when last IRQ is injected */ + struct timer timer; /* ac_timer */ + time_cb *cb; + void *priv; /* ponit back to platform time source */ +}; typedef struct PITChannelState { int count; /* can be 65536 */ @@ -47,8 +69,7 @@ typedef struct PITChannelState { u8 gate; /* timer start */ s64 count_load_time; /* irq handling */ - struct vcpu *vcpu; - struct periodic_time *pt; + struct periodic_time pt; } PITChannelState; typedef struct PITState { @@ -66,10 +87,7 @@ typedef struct RTCState { int64_t next_second_time; struct timer second_timer; struct timer second_timer2; - struct timer pie_timer; - int period; - s_time_t next_pie; - struct vcpu *vcpu; + struct periodic_time pt; } RTCState; #define FREQUENCE_PMTIMER 3579545 @@ -82,58 +100,35 @@ typedef struct PMTState { struct vcpu *vcpu; } PMTState; -/* - * Abstract layer of periodic time, one short time. - */ -typedef void time_cb(struct vcpu *v, void *opaque); - -struct periodic_time { - char enabled; /* enabled */ - char one_shot; /* one shot time */ - char irq; - char first_injected; /* flag to prevent shadow window */ - u32 bind_vcpu; /* vcpu timer interrupt delivers to */ - u32 pending_intr_nr; /* the couner for pending timer interrupts */ - u32 period; /* frequency in ns */ - u64 period_cycles; /* frequency in cpu cycles */ - s_time_t scheduled; /* scheduled timer interrupt */ - u64 last_plt_gtime; /* platform time when last IRQ is injected */ - struct timer timer; /* ac_timer */ - time_cb *cb; - void *priv; /* ponit back to platform time source */ +struct pl_time { /* platform time */ + struct PITState vpit; + struct RTCState vrtc; + struct PMTState vpmt; }; - -struct pl_time { /* platform time */ - struct periodic_time periodic_tm; - struct PITState vpit; - struct RTCState vrtc; - struct PMTState vpmt; -}; - -extern u64 hvm_get_guest_time(struct vcpu *v); -static inline int64_t hvm_get_clock(struct vcpu *v) -{ - return hvm_get_guest_time(v); -} #define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency) -/* to hook the ioreq packet to get the PIT initialization info */ -extern void hvm_hooks_assist(struct vcpu *v); -extern void pickup_deactive_ticks(struct periodic_time *vpit); -extern struct periodic_time *create_periodic_time( - u32 period, char irq, char one_shot, time_cb *cb, void *data); -extern void destroy_periodic_time(struct periodic_time *pt); +void pt_freeze_time(struct vcpu *v); +void pt_thaw_time(struct vcpu *v); +void pt_timer_fn(void *data); +void pt_update_irq(struct vcpu *v); +struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type); +void pt_intr_post(struct vcpu *v, int vector, int type); +void pt_reset(struct vcpu *v); +void create_periodic_time(struct periodic_time *pt, u32 period, char irq, + char one_shot, time_cb *cb, void *data); +void destroy_periodic_time(struct periodic_time *pt); + int pv_pit_handler(int port, int data, int write); void pit_init(struct vcpu *v, unsigned long cpu_khz); +void pit_migrate_timers(struct vcpu *v); +void pit_deinit(struct domain *d); void rtc_init(struct vcpu *v, int base, int irq); +void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); -void rtc_freeze(struct vcpu *v); -void rtc_thaw(struct vcpu *v); -void rtc_migrate_timers(struct vcpu *v); +int is_rtc_periodic_irq(void *opaque); void pmtimer_init(struct vcpu *v, int base); +void pmtimer_migrate_timers(struct vcpu *v); void pmtimer_deinit(struct domain *d); -void pt_timer_fn(void *data); -void pit_time_fired(struct vcpu *v, void *priv); #endif /* __ASM_X86_HVM_VPT_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |