WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [HVM] Enable more than one platform timer

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM] Enable more than one platform timer (PIT/RTC/HPET)
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 20 Dec 2006 17:15:11 -0800
Delivery-date: Wed, 20 Dec 2006 17:16:39 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [HVM] Enable more than one platform timer (PIT/RTC/HPET), Xen patchbot-unstable <=