[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Decouple the RTC from the PIT periodic timer
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Node ID 5f7b5e5ca14b6c00d8ac23d1a2ece62fcbaebc03 # Parent 992723a0ceb1b5e474797ca2634a07d1ba3faff6 [HVM] Decouple the RTC from the PIT periodic timer Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/hvm.c | 17 +++++++ xen/arch/x86/hvm/i8259.c | 12 ---- xen/arch/x86/hvm/rtc.c | 92 +++++++++++++++++++++++++------------- xen/arch/x86/hvm/svm/svm.c | 23 +-------- xen/arch/x86/hvm/vioapic.c | 4 - xen/arch/x86/hvm/vmx/vmcs.c | 2 xen/arch/x86/hvm/vmx/vmx.c | 22 ++------- xen/include/asm-x86/hvm/hvm.h | 1 xen/include/asm-x86/hvm/vmx/vmx.h | 1 xen/include/asm-x86/hvm/vpt.h | 8 ++- 10 files changed, 97 insertions(+), 85 deletions(-) diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/arch/x86/hvm/hvm.c Thu Nov 16 17:07:23 2006 +0000 @@ -74,6 +74,20 @@ void hvm_set_guest_time(struct vcpu *v, hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset); } +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); + } + 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; @@ -91,6 +105,9 @@ void hvm_do_resume(struct vcpu *v) } pickup_deactive_ticks(pt); } + + /* Re-enable the RTC timer if needed */ + rtc_thaw(v); /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */ p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/arch/x86/hvm/i8259.c --- a/xen/arch/x86/hvm/i8259.c Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/arch/x86/hvm/i8259.c Thu Nov 16 17:07:23 2006 +0000 @@ -536,8 +536,6 @@ int is_periodic_irq(struct vcpu *v, int int vec; struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - struct RTCState *vrtc = - &(v->domain->arch.hvm_domain.pl_time.vrtc); if (pt->irq == 0) { /* Is it pit irq? */ if (type == APIC_DM_EXTINT) @@ -549,16 +547,6 @@ int is_periodic_irq(struct vcpu *v, int return 1; } - if (pt->irq == 8) { /* Or rtc irq? */ - if (type == APIC_DM_EXTINT) - vec = domain_vpic(v->domain)->pics[1].irq_base; - else - vec = domain_vioapic(v->domain)->redirtbl[8].fields.vector; - - if (irq == vec) - return is_rtc_periodic_irq(vrtc); - } - return 0; } diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/arch/x86/hvm/rtc.c --- a/xen/arch/x86/hvm/rtc.c Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/arch/x86/hvm/rtc.c Thu Nov 16 17:07:23 2006 +0000 @@ -30,40 +30,43 @@ /* #define DEBUG_RTC */ -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); -} - -static void rtc_timer_update(RTCState *s, int64_t current_time) +/* Callback that fires the RTC's periodic interrupt */ +void rtc_pie_callback(void *opaque) +{ + RTCState *s = opaque; + struct hvm_domain *plat = &s->vcpu->domain->arch.hvm_domain; + struct vpic *pic = &plat->vpic; + /* Record that we have fired */ + s->cmos_data[RTC_REG_C] |= (RTC_IRQF|RTC_PF); /* 0xc0 */ + /* Fire */ + pic_set_irq(pic, s->irq, 1); + /* Remember to fire again */ + s->next_pie = NOW() + s->period; + set_timer(&s->pie_timer, s->next_pie); +} + +/* Enable/configure/disable the periodic timer based on the RTC_PIE and + * RTC_RATE_SELECT settings */ +static void rtc_timer_update(RTCState *s) { int period_code; int period; - period_code = s->cmos_data[RTC_REG_A] & 0x0f; + period_code = s->cmos_data[RTC_REG_A] & RTC_RATE_SELECT; if (period_code != 0 && (s->cmos_data[RTC_REG_B] & RTC_PIE)) { if (period_code <= 2) period_code += 7; 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->pt = create_periodic_time(period, RTC_IRQ, 0, rtc_periodic_cb, s); - } else if (s->pt) { - destroy_periodic_time(s->pt); - s->pt = NULL; + s->next_pie = NOW() + s->period; + set_timer(&s->pie_timer, s->next_pie); + } else { + stop_timer(&s->pie_timer); } } @@ -105,7 +108,7 @@ static int rtc_ioport_write(void *opaque /* UIP bit is read only */ s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) | (s->cmos_data[RTC_REG_A] & RTC_UIP); - rtc_timer_update(s, hvm_get_clock(s->vcpu)); + rtc_timer_update(s); break; case RTC_REG_B: if (data & RTC_SET) { @@ -119,14 +122,14 @@ static int rtc_ioport_write(void *opaque } } s->cmos_data[RTC_REG_B] = data; - rtc_timer_update(s, hvm_get_clock(s->vcpu)); + rtc_timer_update(s); break; case RTC_REG_C: case RTC_REG_D: /* cannot write to them */ break; + } return 1; - } } return 0; } @@ -172,7 +175,7 @@ static void rtc_copy_date(RTCState *s) s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec); s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min); - if (s->cmos_data[RTC_REG_B] & 0x02) { + if (s->cmos_data[RTC_REG_B] & RTC_24H) { /* 24 hour format */ s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour); } else { @@ -245,7 +248,7 @@ static void rtc_update_second(void *opaq RTCState *s = opaque; /* if the oscillator is not in normal operation, we do not update */ - if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) { + if ((s->cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ) { s->next_second_time += 1000000000ULL; set_timer(&s->second_timer, s->next_second_time); } else { @@ -361,22 +364,48 @@ 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); +} + void rtc_init(struct vcpu *v, int base, int irq) { RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc; s->vcpu = v; s->irq = irq; - s->cmos_data[RTC_REG_A] = 0x26; - s->cmos_data[RTC_REG_B] = 0x02; - s->cmos_data[RTC_REG_C] = 0x00; - s->cmos_data[RTC_REG_D] = 0x80; + s->cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */ + s->cmos_data[RTC_REG_B] = RTC_24H; + s->cmos_data[RTC_REG_C] = 0; + s->cmos_data[RTC_REG_D] = RTC_VRT; s->current_tm = gmtime(get_localtime(v->domain)); rtc_copy_date(s); 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); @@ -390,4 +419,5 @@ void rtc_deinit(struct domain *d) kill_timer(&s->second_timer); kill_timer(&s->second_timer2); -} + kill_timer(&s->pie_timer); +} diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Nov 16 17:07:23 2006 +0000 @@ -723,7 +723,10 @@ static void svm_freeze_time(struct 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); + } } } @@ -850,24 +853,6 @@ int start_svm(void) } -static void svm_migrate_timers(struct vcpu *v) -{ - struct periodic_time *pt = - &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc; - struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; - - if ( pt->enabled ) - { - migrate_timer(&pt->timer, v->processor); - } - migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor); - migrate_timer(&vrtc->second_timer, v->processor); - migrate_timer(&vrtc->second_timer2, v->processor); - migrate_timer(&vpmt->timer, v->processor); -} - - void arch_svm_do_resume(struct vcpu *v) { /* pinning VCPU to a different core? */ @@ -880,7 +865,7 @@ void arch_svm_do_resume(struct vcpu *v) printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() ); v->arch.hvm_svm.launch_core = smp_processor_id(); - svm_migrate_timers( v ); + hvm_migrate_timers( v ); hvm_do_resume( v ); reset_stack_and_jump( svm_asm_do_resume ); } diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/arch/x86/hvm/vioapic.c Thu Nov 16 17:07:23 2006 +0000 @@ -471,8 +471,8 @@ void vioapic_set_irq(struct domain *d, i struct vioapic *vioapic = domain_vioapic(d); uint32_t bit; - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq " - "irq %x level %x\n", irq, level); + HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq irq %x level %x", + irq, level); if ( (irq < 0) || (irq >= VIOAPIC_NUM_PINS) ) return; diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Thu Nov 16 17:07:23 2006 +0000 @@ -486,7 +486,7 @@ void arch_vmx_do_resume(struct vcpu *v) { vmx_clear_vmcs(v); vmx_load_vmcs(v); - vmx_migrate_timers(v); + hvm_migrate_timers(v); vmx_set_host_env(v); } diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Nov 16 17:07:23 2006 +0000 @@ -376,14 +376,18 @@ static inline void vmx_restore_dr(struct static void vmx_freeze_time(struct vcpu *v) { - struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm; + struct hvm_domain *plat = &v->domain->arch.hvm_domain; + struct periodic_time *pt = &plat->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); + } } } @@ -407,22 +411,6 @@ static void stop_vmx(void) return; __vmxoff(); clear_in_cr4(X86_CR4_VMXE); -} - -void vmx_migrate_timers(struct vcpu *v) -{ - struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; - struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc; - struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; - - if ( pt->enabled ) - { - migrate_timer(&pt->timer, v->processor); - } - migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor); - migrate_timer(&vrtc->second_timer, v->processor); - migrate_timer(&vrtc->second_timer2, v->processor); - migrate_timer(&vpmt->timer, v->processor); } static void vmx_store_cpu_guest_regs( diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/include/asm-x86/hvm/hvm.h Thu Nov 16 17:07:23 2006 +0000 @@ -161,6 +161,7 @@ hvm_get_guest_ctrl_reg(struct vcpu *v, u void hvm_stts(struct vcpu *v); void hvm_set_guest_time(struct vcpu *v, u64 gtime); +void hvm_migrate_timers(struct vcpu *v); void hvm_do_resume(struct vcpu *v); static inline void diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Thu Nov 16 17:07:23 2006 +0000 @@ -29,7 +29,6 @@ extern void vmx_asm_vmexit_handler(struc extern void vmx_asm_vmexit_handler(struct cpu_user_regs); extern void vmx_asm_do_vmentry(void); extern void vmx_intr_assist(void); -extern void vmx_migrate_timers(struct vcpu *v); extern void arch_vmx_do_resume(struct vcpu *); extern void set_guest_time(struct vcpu *v, u64 gtime); diff -r 992723a0ceb1 -r 5f7b5e5ca14b xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Thu Nov 16 15:20:05 2006 +0000 +++ b/xen/include/asm-x86/hvm/vpt.h Thu Nov 16 17:07:23 2006 +0000 @@ -67,8 +67,10 @@ 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 @@ -143,9 +145,11 @@ void pit_init(struct vcpu *v, unsigned l void pit_init(struct vcpu *v, unsigned long cpu_khz); void rtc_init(struct vcpu *v, int base, int irq); 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); void pmtimer_init(struct vcpu *v, int base); void pmtimer_deinit(struct domain *d); -int is_rtc_periodic_irq(void *opaque); void pt_timer_fn(void *data); void pit_time_fired(struct vcpu *v, void *priv); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |