[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-3.1-testing] hvm: Fix mistake in timer cleanup.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1198146352 0
# Node ID 0f3055da442efe4c60f99af4ab67d35f02ca4f63
# Parent  54e15994c5bec5acda7496f70cb22276e464416d
hvm: Fix mistake in timer cleanup.
Spotted by Dexuan Cui <dexuan.cui@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16601:2ebced8f8bafe196b5c6e7097d98d77e93e254af
xen-unstable date:        Thu Dec 13 09:29:21 2007 +0000

hvm: Reduce vpt.c dependencies on external timer details.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16600:4553bc1087d9f73e5c27f5511c1d4c724b4dbccf
xen-unstable date:        Wed Dec 12 15:41:20 2007 +0000

hvm: Fix destroy_periodic_time() to not race destruction of one-shot
timers.

This bug was tracked down by Dexuan Cui <dexuan.cui@xxxxxxxxx>

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16595:f2f7c92bf1c15206aa7072f6a4e470a132d528e2
xen-unstable date:        Wed Dec 12 11:08:21 2007 +0000

hvm: Split no_missed_tick_accounting into two modes:
 * no_missed_ticks_pending ('SYNC')
 * one_missed_tick_pending ('MIXED')

This is based on a patch by Dave Winchell <dwinchell@xxxxxxxxxxxxxxx>

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16545:0f9b5ab59579e8b980e231bfd3fdf5ab8a74e005
xen-unstable date:        Thu Dec 06 11:56:51 2007 +0000

x86, hvm: Clean up periodic timer code a little. This leads naturally
to a no-missed-tick-accounting mode which is a combination of ticks
delivered 'off beat' immediately upon re-scheduling when ticks are
missed, then reverting to delivering ticks 'on beat' as usual.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset:   16341:8ff5bb70136dbb8ae4a725400334f4bff3643ba8
xen-unstable date:        Thu Nov 08 10:33:18 2007 +0000

x86, hvm: Fix typo in no-missed-tick-accounting timer mode.
From: Dave Winchell <dwinchell@xxxxxxxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset:   16334:644e7577f6ee00f746a63a63ca16284cc31f9ee8
xen-unstable date:        Wed Nov 07 14:53:32 2007 +0000

x86, hvm: More fixes to no-missed-tick-accounting mode.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset:   16315:070da619e65e87b69b2d99794840d84998fdf083
xen-unstable date:        Mon Nov 05 10:09:10 2007 +0000

hvm: Timer fixes:
 1. Do not record more than one pending interrupt in
 no-missed-tick-accounting mode. We do not stack up missed interrupts
 in this timer mode.
 2. Always record all missed ticks when we are in a
 missed-tick-accounting mode. Do not have a ceiling for this as it
 simply causes guests to lose track of wall time.
 3. General bits of cleanup and simplification.
From: Dave Winchell <dwinchell@xxxxxxxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset:   16312:838e77a41a3c53a54428e642cb0440a8a6f8912b
xen-unstable date:        Fri Nov 02 16:34:54 2007 +0000

x86, hvm: Fix 'no_missed_tick_accoutning' timer mode.
From: Haitao Shan <haitao.shan@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset:   16277:eaa8014ef7796d267d6b9e9f05a64025b7b16118
xen-unstable date:        Wed Oct 31 09:14:49 2007 +0000

x86, hvm: New timer mode 'no missed-tick accounting'.
From: Haitao Shan <haitao.shan@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset:   16274:44dde35cb2a663aef3fc27cc326766276cb393e8
xen-unstable date:        Tue Oct 30 16:11:47 2007 +0000

hvm, x86: Allow virtual timer mode to be specified.

In HVM config file:
timer_mode=0 # Default: virtual time is delayed when timer ticks are
             # missed dur to preemption
timer_mode=1 # Virtual time always equals wall time, even while missed
             # ticks are pending

From: Haitao Shan <haitao.shan@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset:   16237:b5a2cbca39308bc28c0c27cc9fd5375e3b41ad13
xen-unstable date:        Fri Oct 26 09:56:54 2007 +0100
---
 tools/python/xen/xend/XendConfig.py     |    2 
 tools/python/xen/xend/XendConstants.py  |    1 
 tools/python/xen/xend/XendDomainInfo.py |    5 
 tools/python/xen/xm/create.py           |    7 -
 tools/python/xen/xm/xenapi_create.py    |    2 
 xen/arch/x86/domain.c                   |    2 
 xen/arch/x86/hvm/hvm.c                  |   13 +
 xen/arch/x86/hvm/i8254.c                |    1 
 xen/arch/x86/hvm/irq.c                  |   24 ---
 xen/arch/x86/hvm/rtc.c                  |   10 -
 xen/arch/x86/hvm/vlapic.c               |   30 +---
 xen/arch/x86/hvm/vpt.c                  |  222 ++++++++++++++++++++------------
 xen/include/asm-x86/hvm/hvm.h           |    6 
 xen/include/asm-x86/hvm/irq.h           |    2 
 xen/include/asm-x86/hvm/vlapic.h        |    3 
 xen/include/asm-x86/hvm/vpt.h           |   16 +-
 xen/include/public/hvm/params.h         |   30 +++-
 17 files changed, 223 insertions(+), 153 deletions(-)

diff -r 54e15994c5be -r 0f3055da442e tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Wed Dec 19 15:58:28 2007 +0000
+++ b/tools/python/xen/xend/XendConfig.py       Thu Dec 20 10:25:52 2007 +0000
@@ -125,7 +125,7 @@ XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 
                         'fda', 'fdb', 'keymap', 'isa', 'localtime', 'monitor', 
                         'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
                         'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
-                        'vncconsole', 'vncdisplay', 'vnclisten',
+                        'vncconsole', 'vncdisplay', 'vnclisten', 'timer_mode',
                         'vncpasswd', 'vncunused', 'xauthority']
 
 # List of XendConfig configuration keys that have no direct equivalent
diff -r 54e15994c5be -r 0f3055da442e tools/python/xen/xend/XendConstants.py
--- a/tools/python/xen/xend/XendConstants.py    Wed Dec 19 15:58:28 2007 +0000
+++ b/tools/python/xen/xend/XendConstants.py    Thu Dec 20 10:25:52 2007 +0000
@@ -43,6 +43,7 @@ HVM_PARAM_PAE_ENABLED  = 4
 HVM_PARAM_PAE_ENABLED  = 4
 HVM_PARAM_IOREQ_PFN    = 5
 HVM_PARAM_BUFIOREQ_PFN = 6
+HVM_PARAM_TIMER_MODE   = 10
 
 restart_modes = [
     "restart",
diff -r 54e15994c5be -r 0f3055da442e tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Wed Dec 19 15:58:28 2007 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Dec 20 10:25:52 2007 +0000
@@ -1536,6 +1536,11 @@ class XendDomainInfo:
 
         self._recreateDom()
 
+        # Set timer configration of domain
+        if hvm:
+            xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE,
+                long(self.info["platform"].get("timer_mode")))
+
         # Set maximum number of vcpus in domain
         xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max']))
 
diff -r 54e15994c5be -r 0f3055da442e tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Wed Dec 19 15:58:28 2007 +0000
+++ b/tools/python/xen/xm/create.py     Thu Dec 20 10:25:52 2007 +0000
@@ -193,6 +193,11 @@ gopts.var('pae', val='PAE',
 gopts.var('pae', val='PAE',
           fn=set_int, default=1,
           use="Disable or enable PAE of HVM domain.")
+
+gopts.var('timer_mode', val='TIMER_MODE',
+          fn=set_int, default=0,
+          use="""Timer mode (0=delay virtual time when ticks are missed;
+          1=virtual time is always wallclock time.""")
 
 gopts.var('acpi', val='ACPI',
           fn=set_int, default=1,
@@ -722,7 +727,7 @@ def configure_hvm(config_image, vals):
 def configure_hvm(config_image, vals):
     """Create the config for HVM devices.
     """
-    args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
+    args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 
'timer_mode',
              'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
              'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
              'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
diff -r 54e15994c5be -r 0f3055da442e tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py      Wed Dec 19 15:58:28 2007 +0000
+++ b/tools/python/xen/xm/xenapi_create.py      Thu Dec 20 10:25:52 2007 +0000
@@ -755,7 +755,7 @@ class sxp2xml:
 
 
     def extract_platform(self, image, document):
-        platform_keys = ['acpi', 'apic', 'pae']
+        platform_keys = ['acpi', 'apic', 'pae', 'timer_mode']
 
         def extract_platform_key(key):
             platform = document.createElement("platform")
diff -r 54e15994c5be -r 0f3055da442e xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/arch/x86/domain.c     Thu Dec 20 10:25:52 2007 +0000
@@ -1249,7 +1249,7 @@ void context_switch(struct vcpu *prev, s
     local_irq_disable();
 
     if ( is_hvm_vcpu(prev) && !list_empty(&prev->arch.hvm_vcpu.tm_list) )
-        pt_freeze_time(prev);
+        pt_save_timer(prev);
 
     set_current(next);
 
diff -r 54e15994c5be -r 0f3055da442e xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Thu Dec 20 10:25:52 2007 +0000
@@ -89,17 +89,17 @@ void hvm_stts(struct vcpu *v)
         hvm_funcs.stts(v);
 }
 
-void hvm_set_guest_time(struct vcpu *v, u64 gtime)
+void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc)
 {
     u64 host_tsc;
 
     rdtscll(host_tsc);
 
-    v->arch.hvm_vcpu.cache_tsc_offset = gtime - host_tsc;
+    v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - host_tsc;
     hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
 }
 
-u64 hvm_get_guest_time(struct vcpu *v)
+u64 hvm_get_guest_tsc(struct vcpu *v)
 {
     u64 host_tsc;
 
@@ -120,7 +120,7 @@ void hvm_do_resume(struct vcpu *v)
 
     hvm_stts(v);
 
-    pt_thaw_time(v);
+    pt_restore_timer(v);
 
     /* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
     p = &get_ioreq(v)->vp_ioreq;
@@ -1103,6 +1103,11 @@ long do_hvm_op(unsigned long op, XEN_GUE
                 hvm_set_callback_via(d, a.value);
                 hvm_latch_shinfo_size(d);
                 break;
+            case HVM_PARAM_TIMER_MODE:
+                rc = -EINVAL;
+                if ( a.value > HVMPTM_one_missed_tick_pending )
+                    goto param_fail;
+                break;
             }
             d->arch.hvm_domain.params[a.index] = a.value;
             rc = 0;
diff -r 54e15994c5be -r 0f3055da442e xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/arch/x86/hvm/i8254.c  Thu Dec 20 10:25:52 2007 +0000
@@ -517,6 +517,7 @@ void pit_init(struct vcpu *v, unsigned l
         s->mode = 0xff; /* the init mode */
         s->gate = (i != 2);
         pit_load_count(pit, i, 0);
+        pit->pt[i].source = PTSRC_isa;
     }
 
     spin_unlock(&pit->lock);
diff -r 54e15994c5be -r 0f3055da442e xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/arch/x86/hvm/irq.c    Thu Dec 20 10:25:52 2007 +0000
@@ -312,30 +312,6 @@ int cpu_get_interrupt(struct vcpu *v, in
         return vector;
 
     return -1;
-}
-
-int get_isa_irq_vector(struct vcpu *v, int isa_irq, int type)
-{
-    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
-
-    if ( type == APIC_DM_EXTINT )
-        return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
-                + (isa_irq & 7));
-
-    return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
-}
-
-int is_isa_irq_masked(struct vcpu *v, int isa_irq)
-{
-    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
-    uint8_t pic_imr;
-
-    if ( is_lvtt(v, isa_irq) )
-        return !is_lvtt_enabled(v);
-
-    pic_imr = v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr;
-    return (((pic_imr & (1 << (isa_irq & 7))) || !vlapic_accept_pic_intr(v)) &&
-            domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
 }
 
 /*
diff -r 54e15994c5be -r 0f3055da442e xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/arch/x86/hvm/rtc.c    Thu Dec 20 10:25:52 2007 +0000
@@ -40,14 +40,6 @@ static void rtc_periodic_cb(struct vcpu 
     spin_lock(&s->lock);
     s->hw.cmos_data[RTC_REG_C] |= 0xc0;
     spin_unlock(&s->lock);
-}
-
-int is_rtc_periodic_irq(void *opaque)
-{
-    RTCState *s = opaque;
-
-    return !(s->hw.cmos_data[RTC_REG_C] & RTC_AF || 
-             s->hw.cmos_data[RTC_REG_C] & RTC_UF);
 }
 
 /* Enable/configure/disable the periodic timer based on the RTC_PIE and
@@ -488,6 +480,8 @@ void rtc_init(struct vcpu *v, int base)
 
     spin_lock_init(&s->lock);
 
+    s->pt.source = PTSRC_isa;
+
     s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
     s->hw.cmos_data[RTC_REG_B] = RTC_24H;
     s->hw.cmos_data[RTC_REG_C] = 0;
diff -r 54e15994c5be -r 0f3055da442e xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Thu Dec 20 10:25:52 2007 +0000
@@ -67,9 +67,6 @@ static unsigned int vlapic_lvt_mask[VLAP
 #define APIC_DEST_NOSHORT                0x0
 #define APIC_DEST_MASK                   0x800
 
-#define vlapic_lvt_enabled(vlapic, lvt_type)                    \
-    (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
-
 #define vlapic_lvt_vector(vlapic, lvt_type)                     \
     (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
 
@@ -418,7 +415,7 @@ static uint32_t vlapic_get_tmcct(struct 
     uint32_t tmcct, tmict = vlapic_get_reg(vlapic, APIC_TMICT);
     uint64_t counter_passed;
 
-    counter_passed = (hvm_get_guest_time(v) - vlapic->pt.last_plt_gtime) // TSC
+    counter_passed = (hvm_get_guest_time(v) - vlapic->timer_last_update) // TSC
                      * 1000000000ULL / ticks_per_sec(v) // NS
                      / APIC_BUS_CYCLE_NS / vlapic->hw.timer_divisor;
     tmcct = tmict - counter_passed;
@@ -514,6 +511,11 @@ static unsigned long vlapic_read(struct 
  exit_and_crash:
     domain_crash(v->domain);
     return 0;
+}
+
+void vlapic_pt_cb(struct vcpu *v, void *data)
+{
+    *(s_time_t *)data = hvm_get_guest_time(v);
 }
 
 static void vlapic_write(struct vcpu *v, unsigned long address,
@@ -645,7 +647,8 @@ static void vlapic_write(struct vcpu *v,
 
         vlapic_set_reg(vlapic, APIC_TMICT, val);
         create_periodic_time(current, &vlapic->pt, period, vlapic->pt.irq,
-                             !vlapic_lvtt_period(vlapic), NULL, vlapic);
+                             !vlapic_lvtt_period(vlapic), vlapic_pt_cb,
+                             &vlapic->timer_last_update);
         vlapic->timer_last_update = vlapic->pt.last_plt_gtime;
 
         HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
@@ -807,7 +810,8 @@ static void lapic_rearm(struct vlapic *s
 
         s->pt.irq = lvtt & APIC_VECTOR_MASK;
         create_periodic_time(vlapic_vcpu(s), &s->pt, period, s->pt.irq,
-                             !vlapic_lvtt_period(s), NULL, s);
+                             !vlapic_lvtt_period(s), vlapic_pt_cb,
+                             &s->timer_last_update);
         s->timer_last_update = s->pt.last_plt_gtime;
 
         printk("lapic_load to rearm the actimer:"
@@ -904,6 +908,8 @@ int vlapic_init(struct vcpu *v)
 
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "%d", v->vcpu_id);
 
+    vlapic->pt.source = PTSRC_lapic;
+
     vlapic->regs_page = alloc_domheap_page(NULL);
     if ( vlapic->regs_page == NULL )
     {
@@ -940,15 +946,3 @@ void vlapic_destroy(struct vcpu *v)
     unmap_domain_page_global(vlapic->regs);
     free_domheap_page(vlapic->regs_page);
 }
-
-int is_lvtt(struct vcpu *v, int vector)
-{
-    return (pt_active(&vcpu_vlapic(v)->pt) &&
-            (vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT)));
-}
-
-int is_lvtt_enabled(struct vcpu *v)
-{
-    return (vlapic_enabled(vcpu_vlapic(v)) &&
-            vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT));
-}
diff -r 54e15994c5be -r 0f3055da442e xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c    Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/arch/x86/hvm/vpt.c    Thu Dec 20 10:25:52 2007 +0000
@@ -15,13 +15,54 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
  */
 
 #include <xen/time.h>
 #include <asm/hvm/support.h>
 #include <asm/hvm/vpt.h>
 #include <asm/event.h>
+
+#define mode_is(d, name) \
+    ((d)->arch.hvm_domain.params[HVM_PARAM_TIMER_MODE] == HVMPTM_##name)
+
+static int pt_irq_vector(struct periodic_time *pt, int type)
+{
+    struct vcpu *v = pt->vcpu;
+    unsigned int gsi, isa_irq;
+
+    if ( pt->source == PTSRC_lapic )
+        return pt->irq;
+
+    isa_irq = pt->irq;
+    gsi = hvm_isa_irq_to_gsi(isa_irq);
+
+    if ( type == APIC_DM_EXTINT )
+        return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
+                + (isa_irq & 7));
+
+    return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
+}
+
+static int pt_irq_masked(struct periodic_time *pt)
+{
+    struct vcpu *v = pt->vcpu;
+    unsigned int gsi, isa_irq;
+    uint8_t pic_imr;
+
+    if ( pt->source == PTSRC_lapic )
+    {
+        struct vlapic *vlapic = vcpu_vlapic(v);
+        return (!vlapic_enabled(vlapic) ||
+                (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_MASKED));
+    }
+
+    isa_irq = pt->irq;
+    gsi = hvm_isa_irq_to_gsi(isa_irq);
+    pic_imr = v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr;
+
+    return (((pic_imr & (1 << (isa_irq & 7))) || !vlapic_accept_pic_intr(v)) &&
+            domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
+}
 
 static void pt_lock(struct periodic_time *pt)
 {
@@ -42,32 +83,46 @@ static void pt_unlock(struct periodic_ti
     spin_unlock(&pt->vcpu->arch.hvm_vcpu.tm_lock);
 }
 
-static void missed_ticks(struct periodic_time *pt)
-{
-    s_time_t missed_ticks;
+static void pt_process_missed_ticks(struct periodic_time *pt)
+{
+    s_time_t missed_ticks, now = NOW();
 
     if ( pt->one_shot )
         return;
 
-    missed_ticks = NOW() - pt->scheduled;
+    missed_ticks = now - pt->scheduled;
     if ( missed_ticks <= 0 )
         return;
 
     missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
-    if ( missed_ticks > 1000 )
-    {
-        /* TODO: Adjust guest time together */
-        pt->pending_intr_nr++;
-    }
+    if ( mode_is(pt->vcpu->domain, no_missed_ticks_pending) )
+        pt->do_not_freeze = !pt->pending_intr_nr;
     else
-    {
         pt->pending_intr_nr += missed_ticks;
-    }
-
     pt->scheduled += missed_ticks * pt->period;
 }
 
-void pt_freeze_time(struct vcpu *v)
+static void pt_freeze_time(struct vcpu *v)
+{
+    if ( !mode_is(v->domain, delay_for_missed_ticks) )
+        return;
+
+    v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
+}
+
+static void pt_thaw_time(struct vcpu *v)
+{
+    if ( !mode_is(v->domain, delay_for_missed_ticks) )
+        return;
+
+    if ( v->arch.hvm_vcpu.guest_time == 0 )
+        return;
+
+    hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
+    v->arch.hvm_vcpu.guest_time = 0;
+}
+
+void pt_save_timer(struct vcpu *v)
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
     struct periodic_time *pt;
@@ -77,32 +132,29 @@ void pt_freeze_time(struct vcpu *v)
 
     spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
-    v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
-
-    list_for_each_entry ( pt, head, list )
-        stop_timer(&pt->timer);
-
-    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
-}
-
-void pt_thaw_time(struct vcpu *v)
-{
-    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
-    struct periodic_time *pt;
-
-    spin_lock(&v->arch.hvm_vcpu.tm_lock);
-
-    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;
-
-        list_for_each_entry ( pt, head, list )
-        {
-            missed_ticks(pt);
-            set_timer(&pt->timer, pt->scheduled);
-        }
-    }
+    list_for_each_entry ( pt, head, list )
+        if ( !pt->do_not_freeze )
+            stop_timer(&pt->timer);
+
+    pt_freeze_time(v);
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+}
+
+void pt_restore_timer(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct periodic_time *pt;
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
+
+    list_for_each_entry ( pt, head, list )
+    {
+        pt_process_missed_ticks(pt);
+        set_timer(&pt->timer, pt->scheduled);
+    }
+
+    pt_thaw_time(v);
 
     spin_unlock(&v->arch.hvm_vcpu.tm_lock);
 }
@@ -118,7 +170,7 @@ static void pt_timer_fn(void *data)
     if ( !pt->one_shot )
     {
         pt->scheduled += pt->period;
-        missed_ticks(pt);
+        pt_process_missed_ticks(pt);
         set_timer(&pt->timer, pt->scheduled);
     }
 
@@ -130,29 +182,39 @@ void pt_update_irq(struct vcpu *v)
 void pt_update_irq(struct vcpu *v)
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
-    struct periodic_time *pt;
+    struct periodic_time *pt, *earliest_pt = NULL;
     uint64_t max_lag = -1ULL;
-    int irq = -1;
-
-    spin_lock(&v->arch.hvm_vcpu.tm_lock);
-
-    list_for_each_entry ( pt, head, list )
-    {
-        if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr &&
+    int irq, is_lapic;
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
+
+    list_for_each_entry ( pt, head, list )
+    {
+        if ( !pt_irq_masked(pt) && pt->pending_intr_nr &&
              ((pt->last_plt_gtime + pt->period_cycles) < max_lag) )
         {
             max_lag = pt->last_plt_gtime + pt->period_cycles;
-            irq = pt->irq;
+            earliest_pt = pt;
         }
     }
 
-    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
-
-    if ( is_lvtt(v, irq) )
+    if ( earliest_pt == NULL )
+    {
+        spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+        return;
+    }
+
+    earliest_pt->irq_issued = 1;
+    irq = earliest_pt->irq;
+    is_lapic = (earliest_pt->source == PTSRC_lapic);
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+
+    if ( is_lapic )
     {
         vlapic_set_irq(vcpu_vlapic(v), irq, 0);
     }
-    else if ( irq >= 0 )
+    else
     {
         hvm_isa_irq_deassert(v->domain, irq);
         hvm_isa_irq_assert(v->domain, irq);
@@ -163,28 +225,12 @@ static struct periodic_time *is_pt_irq(s
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
     struct periodic_time *pt;
-    struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
-    int vec;
-
-    list_for_each_entry ( pt, head, list )
-    {
-        if ( !pt->pending_intr_nr )
-            continue;
-
-        if ( is_lvtt(v, pt->irq) )
-        {
-            if ( pt->irq != vector )
-                continue;
+
+    list_for_each_entry ( pt, head, list )
+    {
+        if ( pt->pending_intr_nr && pt->irq_issued &&
+             (vector == pt_irq_vector(pt, type)) )
             return pt;
-        }
-
-        vec = get_isa_irq_vector(v, pt->irq, type);
-
-        /* RTC irq need special care */
-        if ( (vector != vec) || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) )
-            continue;
-
-        return pt;
     }
 
     return NULL;
@@ -204,6 +250,9 @@ void pt_intr_post(struct vcpu *v, int ve
         spin_unlock(&v->arch.hvm_vcpu.tm_lock);
         return;
     }
+
+    pt->do_not_freeze = 0;
+    pt->irq_issued = 0;
 
     if ( pt->one_shot )
     {
@@ -213,11 +262,20 @@ void pt_intr_post(struct vcpu *v, int ve
     }
     else
     {
-        pt->pending_intr_nr--;
-        pt->last_plt_gtime += pt->period_cycles;
-    }
-
-    if ( hvm_get_guest_time(v) < pt->last_plt_gtime )
+        if ( mode_is(v->domain, one_missed_tick_pending) )
+        {
+            pt->last_plt_gtime = hvm_get_guest_time(v);
+            pt->pending_intr_nr = 0; /* 'collapse' all missed ticks */
+        }
+        else
+        {
+            pt->last_plt_gtime += pt->period_cycles;
+            pt->pending_intr_nr--;
+        }
+    }
+
+    if ( mode_is(v->domain, delay_for_missed_ticks) &&
+         (hvm_get_guest_time(v) < pt->last_plt_gtime) )
         hvm_set_guest_time(v, pt->last_plt_gtime);
 
     cb = pt->cb;
@@ -264,11 +322,15 @@ void create_periodic_time(
     struct vcpu *v, struct periodic_time *pt, uint64_t period,
     uint8_t irq, char one_shot, time_cb *cb, void *data)
 {
+    ASSERT(pt->source != 0);
+
     destroy_periodic_time(pt);
 
     spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
     pt->pending_intr_nr = 0;
+    pt->do_not_freeze = 0;
+    pt->irq_issued = 0;
 
     /* Periodic timer must be at least 0.9ms. */
     if ( (period < 900000) && !one_shot )
diff -r 54e15994c5be -r 0f3055da442e xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/include/asm-x86/hvm/hvm.h     Thu Dec 20 10:25:52 2007 +0000
@@ -173,8 +173,10 @@ hvm_load_cpu_guest_regs(struct vcpu *v, 
     hvm_funcs.load_cpu_guest_regs(v, r);
 }
 
-void hvm_set_guest_time(struct vcpu *v, u64 gtime);
-u64 hvm_get_guest_time(struct vcpu *v);
+void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc);
+u64 hvm_get_guest_tsc(struct vcpu *v);
+#define hvm_set_guest_time(vcpu, gtime) hvm_set_guest_tsc(vcpu, gtime)
+#define hvm_get_guest_time(vcpu)        hvm_get_guest_tsc(vcpu)
 
 static inline int
 hvm_paging_enabled(struct vcpu *v)
diff -r 54e15994c5be -r 0f3055da442e xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h     Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/include/asm-x86/hvm/irq.h     Thu Dec 20 10:25:52 2007 +0000
@@ -117,7 +117,5 @@ void hvm_set_callback_via(struct domain 
 
 int cpu_get_interrupt(struct vcpu *v, int *type);
 int cpu_has_pending_irq(struct vcpu *v);
-int get_isa_irq_vector(struct vcpu *vcpu, int irq, int type);
-int is_isa_irq_masked(struct vcpu *v, int isa_irq);
 
 #endif /* __ASM_X86_HVM_IRQ_H__ */
diff -r 54e15994c5be -r 0f3055da442e xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/include/asm-x86/hvm/vlapic.h  Thu Dec 20 10:25:52 2007 +0000
@@ -94,7 +94,4 @@ struct vlapic *apic_round_robin(
 
 int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
 
-int is_lvtt(struct vcpu *v, int vector);
-int is_lvtt_enabled(struct vcpu *v);
-
 #endif /* __ASM_X86_HVM_VLAPIC_H__ */
diff -r 54e15994c5be -r 0f3055da442e xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h     Thu Dec 20 10:25:52 2007 +0000
@@ -57,6 +57,11 @@ struct periodic_time {
     struct list_head list;
     bool_t on_list;
     bool_t one_shot;
+    bool_t do_not_freeze;
+    bool_t irq_issued;
+#define PTSRC_isa    1 /* ISA time source */
+#define PTSRC_lapic  2 /* LAPIC time source */
+    u8 source;                  /* PTSRC_ */
     u8 irq;
     struct vcpu *vcpu;          /* vcpu timer interrupt delivers to */
     u32 pending_intr_nr;        /* pending timer interrupts */
@@ -116,8 +121,8 @@ struct pl_time {    /* platform time */
 
 #define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
 
-void pt_freeze_time(struct vcpu *v);
-void pt_thaw_time(struct vcpu *v);
+void pt_save_timer(struct vcpu *v);
+void pt_restore_timer(struct vcpu *v);
 void pt_update_irq(struct vcpu *v);
 void pt_intr_post(struct vcpu *v, int vector, int type);
 void pt_reset(struct vcpu *v);
@@ -128,8 +133,10 @@ void pt_migrate(struct vcpu *v);
 
 /*
  * Create/destroy a periodic (or one-shot!) timer.
- * The given periodic timer structure must be initialised with zero bytes or
- * have been initialised by a previous invocation of create_periodic_time().
+ * The given periodic timer structure must be initialised with zero bytes,
+ * except for the 'source' field which must be initialised with the
+ * correct PTSRC_ value. The initialised timer structure can then be passed
+ * to {create,destroy}_periodic_time() and number of times and in any order.
  * Note that, for a given periodic timer, invocations of these functions MUST
  * be serialised.
  */
@@ -145,7 +152,6 @@ void rtc_init(struct vcpu *v, int base);
 void rtc_init(struct vcpu *v, int base);
 void rtc_migrate_timers(struct vcpu *v);
 void rtc_deinit(struct domain *d);
-int is_rtc_periodic_irq(void *opaque);
 void pmtimer_init(struct vcpu *v);
 void pmtimer_deinit(struct domain *d);
 
diff -r 54e15994c5be -r 0f3055da442e xen/include/public/hvm/params.h
--- a/xen/include/public/hvm/params.h   Wed Dec 19 15:58:28 2007 +0000
+++ b/xen/include/public/hvm/params.h   Thu Dec 20 10:25:52 2007 +0000
@@ -52,9 +52,33 @@
 
 #ifdef __ia64__
 #define HVM_PARAM_NVRAM_FD     7
-#define HVM_NR_PARAMS          8
-#else
-#define HVM_NR_PARAMS          7
 #endif
 
+/*
+ * Set mode for virtual timers (currently x86 only):
+ *  delay_for_missed_ticks (default):
+ *   Do not advance a vcpu's time beyond the correct delivery time for
+ *   interrupts that have been missed due to preemption. Deliver missed
+ *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
+ *   time stepwise for each one.
+ *  no_delay_for_missed_ticks:
+ *   As above, missed interrupts are delivered, but guest time always tracks
+ *   wallclock (i.e., real) time while doing so.
+ *  no_missed_ticks_pending:
+ *   No missed interrupts are held pending. Instead, to ensure ticks are
+ *   delivered at some non-zero rate, if we detect missed ticks then the
+ *   internal tick alarm is not disabled if the VCPU is preempted during the
+ *   next tick period.
+ *  one_missed_tick_pending:
+ *   Missed interrupts are collapsed together and delivered as one 'late tick'.
+ *   Guest time always tracks wallclock (i.e., real) time.
+ */
+#define HVM_PARAM_TIMER_MODE   10
+#define HVMPTM_delay_for_missed_ticks    0
+#define HVMPTM_no_delay_for_missed_ticks 1
+#define HVMPTM_no_missed_ticks_pending   2
+#define HVMPTM_one_missed_tick_pending   3
+
+#define HVM_NR_PARAMS          11
+
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */

_______________________________________________
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®.