# 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
|