[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.