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-3.1-testing] hvm: Fix mistake in timer cleanup.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-3.1-testing] hvm: Fix mistake in timer cleanup.
From: "Xen patchbot-3.1-testing" <patchbot-3.1-testing@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 20 Dec 2007 12:00:24 -0800
Delivery-date: Thu, 20 Dec 2007 12:00:41 -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 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-3.1-testing] hvm: Fix mistake in timer cleanup., Xen patchbot-3.1-testing <=