# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1166611293 0
# Node ID 516e4faac066437af4b41014da831d2ad8ae0493
# Parent 2a1edeedf28d9c72492255fba638fbca61da7ee3
[HVM] Sync per vcpu LAPIC timer with its TSC:
- benefits LAPIC calibration
- makes scheduling policy based on LAPIC more precise
- makes LAPIC timer code becomes simpler and cleaner after using
periodic time layer
Signed-off-by: Xiaowei Yang <xiaowei.yang@xxxxxxxxx>
---
xen/arch/x86/hvm/hvm.c | 3
xen/arch/x86/hvm/io.c | 15 --
xen/arch/x86/hvm/irq.c | 6 -
xen/arch/x86/hvm/svm/intr.c | 2
xen/arch/x86/hvm/vlapic.c | 199 +++++++++------------------------
xen/arch/x86/hvm/vmx/intr.c | 4
xen/arch/x86/hvm/vpt.c | 231 +++++++++++++++++++++++++++++++++++++++
xen/include/asm-x86/hvm/vlapic.h | 24 ++--
xen/include/asm-x86/hvm/vpt.h | 8 -
9 files changed, 314 insertions(+), 178 deletions(-)
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/hvm.c Wed Dec 20 10:41:33 2006 +0000
@@ -87,7 +87,8 @@ void hvm_migrate_timers(struct vcpu *v)
pit_migrate_timers(v);
rtc_migrate_timers(v);
pmtimer_migrate_timers(v);
- migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor);
+ if ( vcpu_vlapic(v)->pt.enabled )
+ migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor);
}
void hvm_do_resume(struct vcpu *v)
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/io.c Wed Dec 20 10:41:33 2006 +0000
@@ -689,21 +689,6 @@ static void hvm_mmio_assist(struct cpu_u
}
}
-void hvm_interrupt_post(struct vcpu *v, int vector, int type)
-{
- pt_intr_post(v, vector, type);
-
- switch(type) {
- case APIC_DM_EXTINT:
- break;
-
- default:
- vlapic_post_injection(v, vector, type);
- break;
- }
-}
-
-
void hvm_io_assist(struct vcpu *v)
{
vcpu_iodata_t *vio;
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/irq.c Wed Dec 20 10:41:33 2006 +0000
@@ -229,10 +229,9 @@ int cpu_has_pending_irq(struct vcpu *v)
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 )
+ if ( vlapic_has_interrupt(v) != -1 )
return 1;
/* PIC */
@@ -267,6 +266,9 @@ int get_intr_vector(struct vcpu* v, int
int is_irq_masked(struct vcpu *v, int irq)
{
+ if ( is_lvtt(v, irq) )
+ return !is_lvtt_enabled(v);
+
if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7))
&& domain_vioapic(v->domain)->redirtbl[irq].fields.mask )
return 1;
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/svm/intr.c Wed Dec 20 10:41:33 2006 +0000
@@ -141,7 +141,7 @@ asmlinkage void svm_intr_assist(void)
break;
}
- hvm_interrupt_post(v, intr_vector, intr_type);
+ pt_intr_post(v, intr_vector, intr_type);
}
/*
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Wed Dec 20 10:41:33 2006 +0000
@@ -39,9 +39,8 @@
#define VLAPIC_VERSION 0x00050014
#define VLAPIC_LVT_NUM 6
-extern u32 get_apic_bus_cycle(void);
-
-#define APIC_BUS_CYCLE_NS (((s_time_t)get_apic_bus_cycle()) / 1000)
+/* vlapic's frequence is 100 MHz */
+#define APIC_BUS_CYCLE_NS 10
#define LVT_MASK \
APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
@@ -122,11 +121,6 @@ static int vlapic_test_and_set_irr(int v
return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
}
-static void vlapic_set_irr(int vector, struct vlapic *vlapic)
-{
- vlapic_set_vector(vector, vlapic->regs + APIC_IRR);
-}
-
static void vlapic_clear_irr(int vector, struct vlapic *vlapic)
{
vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
@@ -433,46 +427,19 @@ static void vlapic_ipi(struct vlapic *vl
static uint32_t vlapic_get_tmcct(struct vlapic *vlapic)
{
- uint32_t counter_passed;
- s_time_t passed, now = NOW();
- uint32_t tmcct = vlapic_get_reg(vlapic, APIC_TMCCT);
-
- if ( unlikely(now <= vlapic->timer_last_update) )
- {
- passed = ~0x0LL - vlapic->timer_last_update + now;
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "time elapsed.");
- }
- else
- passed = now - vlapic->timer_last_update;
-
- counter_passed = passed / (APIC_BUS_CYCLE_NS * vlapic->timer_divisor);
-
- tmcct -= counter_passed;
-
- if ( tmcct <= 0 )
- {
- if ( unlikely(!vlapic_lvtt_period(vlapic)) )
- {
- tmcct = 0;
- /* FIXME: should we add interrupt here? */
- }
- else
- {
- do {
- tmcct += vlapic_get_reg(vlapic, APIC_TMICT);
- } while ( tmcct <= 0 );
- }
- }
-
- vlapic->timer_last_update = now;
- vlapic_set_reg(vlapic, APIC_TMCCT, tmcct);
+ struct vcpu *v = current;
+ 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
+ * 1000000000ULL / ticks_per_sec(v) // NS
+ / APIC_BUS_CYCLE_NS / vlapic->timer_divisor;
+ tmcct = tmict - counter_passed;
HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
- "timer initial count 0x%x, timer current count 0x%x, "
- "update 0x%016"PRIx64", now 0x%016"PRIx64", offset 0x%x.",
- vlapic_get_reg(vlapic, APIC_TMICT),
- vlapic_get_reg(vlapic, APIC_TMCCT),
- vlapic->timer_last_update, now, counter_passed);
+ "timer initial count %d, timer current count %d, "
+ "offset %"PRId64".",
+ tmict, tmcct, counter_passed);
return tmcct;
}
@@ -486,6 +453,9 @@ static void vlapic_set_tdcr(struct vlapi
/* Update the demangled timer_divisor. */
val = ((val & 3) | ((val & 8) >> 1)) + 1;
vlapic->timer_divisor = 1 << (val & 7);
+
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ "vlapic_set_tdcr timer_divisor: %d.", vlapic->timer_divisor);
}
static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
@@ -577,6 +547,7 @@ static void vlapic_write(struct vcpu *v,
* According to the IA32 Manual, all accesses should be 32 bits.
* Some OSes do 8- or 16-byte accesses, however.
*/
+ val &= 0xffffffff;
if ( len != 4 )
{
unsigned int tmp;
@@ -671,6 +642,7 @@ static void vlapic_write(struct vcpu *v,
break;
case APIC_LVTT: /* LVT Timer Reg */
+ vlapic->pt.irq = val & APIC_VECTOR_MASK;
case APIC_LVTTHMR: /* LVT Thermal Monitor */
case APIC_LVTPC: /* LVT Performance Counter */
case APIC_LVT0: /* LVT LINT0 Reg */
@@ -684,25 +656,16 @@ static void vlapic_write(struct vcpu *v,
case APIC_TMICT:
{
- s_time_t now = NOW(), offset;
-
- stop_timer(&vlapic->vlapic_timer);
+ uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val *
vlapic->timer_divisor;
vlapic_set_reg(vlapic, APIC_TMICT, val);
- vlapic_set_reg(vlapic, APIC_TMCCT, val);
- vlapic->timer_last_update = now;
-
- offset = APIC_BUS_CYCLE_NS * vlapic->timer_divisor * val;
-
- set_timer(&vlapic->vlapic_timer, now + offset);
+ create_periodic_time(&vlapic->pt, period, vlapic->pt.irq,
+ vlapic_lvtt_period(vlapic), NULL, vlapic);
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
- "bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
- "timer initial count 0x%x, offset 0x%016"PRIx64", "
- "expire @ 0x%016"PRIx64".",
- APIC_BUS_CYCLE_NS, now,
- vlapic_get_reg(vlapic, APIC_TMICT),
- offset, now + offset);
+ "bus cycle is %uns, "
+ "initial count %lu, period %"PRIu64"ns",
+ APIC_BUS_CYCLE_NS, val, period);
}
break;
@@ -751,48 +714,6 @@ void vlapic_msr_set(struct vlapic *vlapi
HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"apic base msr is 0x%016"PRIx64".", vlapic->apic_base_msr);
-}
-
-void vlapic_timer_fn(void *data)
-{
- struct vlapic *vlapic = data;
- uint32_t timer_vector;
- s_time_t now;
-
- if ( unlikely(!vlapic_enabled(vlapic) ||
- !vlapic_lvt_enabled(vlapic, APIC_LVTT)) )
- return;
-
- timer_vector = vlapic_lvt_vector(vlapic, APIC_LVTT);
- now = NOW();
-
- vlapic->timer_last_update = now;
-
- if ( vlapic_test_and_set_irr(timer_vector, vlapic) )
- vlapic->timer_pending_count++;
-
- if ( vlapic_lvtt_period(vlapic) )
- {
- s_time_t offset;
- uint32_t tmict = vlapic_get_reg(vlapic, APIC_TMICT);
-
- vlapic_set_reg(vlapic, APIC_TMCCT, tmict);
-
- offset = APIC_BUS_CYCLE_NS * vlapic->timer_divisor * tmict;
-
- set_timer(&vlapic->vlapic_timer, now + offset);
- }
- else
- vlapic_set_reg(vlapic, APIC_TMCCT, 0);
-
- vcpu_kick(vlapic_vcpu(vlapic));
-
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
- "now 0x%016"PRIx64", expire @ 0x%016"PRIx64", "
- "timer initial count 0x%x, timer current count 0x%x.",
- now, vlapic->vlapic_timer.expires,
- vlapic_get_reg(vlapic, APIC_TMICT),
- vlapic_get_reg(vlapic, APIC_TMCCT));
}
int vlapic_accept_pic_intr(struct vcpu *v)
@@ -809,7 +730,7 @@ int vlapic_accept_pic_intr(struct vcpu *
vlapic_hw_disabled(vlapic)));
}
-int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
+int vlapic_has_interrupt(struct vcpu *v)
{
struct vlapic *vlapic = vcpu_vlapic(v);
int highest_irr;
@@ -822,42 +743,22 @@ int cpu_get_apic_interrupt(struct vcpu *
((highest_irr & 0xF0) <= vlapic_get_ppr(vlapic)) )
return -1;
+ return highest_irr;
+}
+
+int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
+{
+ int vector = vlapic_has_interrupt(v);
+ struct vlapic *vlapic = vcpu_vlapic(v);
+
+ if ( vector == -1 )
+ return -1;
+
+ vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
+ vlapic_clear_irr(vector, vlapic);
+
*mode = APIC_DM_FIXED;
- return highest_irr;
-}
-
-void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
-{
- struct vlapic *vlapic = vcpu_vlapic(v);
-
- switch ( deliver_mode )
- {
- case APIC_DM_FIXED:
- case APIC_DM_LOWEST:
- vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
- vlapic_clear_irr(vector, vlapic);
- if ( (vector == vlapic_lvt_vector(vlapic, APIC_LVTT)) &&
- (vlapic->timer_pending_count != 0) )
- {
- vlapic->timer_pending_count--;
- vlapic_set_irr(vector, vlapic);
- }
- break;
-
- case APIC_DM_REMRD:
- gdprintk(XENLOG_WARNING, "Ignoring delivery mode 3.\n");
- break;
-
- case APIC_DM_SMI:
- case APIC_DM_NMI:
- case APIC_DM_INIT:
- case APIC_DM_STARTUP:
- break;
-
- default:
- gdprintk(XENLOG_WARNING, "Invalid delivery mode\n");
- break;
- }
+ return vector;
}
/* Reset the VLPAIC back to its power-on/reset state. */
@@ -918,8 +819,7 @@ int vlapic_init(struct vcpu *v)
if ( v->vcpu_id == 0 )
vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
- init_timer(&vlapic->vlapic_timer,
- vlapic_timer_fn, vlapic, v->processor);
+ init_timer(&vlapic->pt.timer, pt_timer_fn, &vlapic->pt, v->processor);
return 0;
}
@@ -928,7 +828,22 @@ void vlapic_destroy(struct vcpu *v)
{
struct vlapic *vlapic = vcpu_vlapic(v);
- kill_timer(&vlapic->vlapic_timer);
+ kill_timer(&vlapic->pt.timer);
unmap_domain_page_global(vlapic->regs);
free_domheap_page(vlapic->regs_page);
}
+
+int is_lvtt(struct vcpu *v, int vector)
+{
+ return vcpu_vlapic(v)->pt.enabled &&
+ vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT);
+}
+
+int is_lvtt_enabled(struct vcpu *v)
+{
+ if ( unlikely(!vlapic_enabled(vcpu_vlapic(v))) ||
+ !vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT))
+ return 0;
+
+ return 1;
+}
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/intr.c Wed Dec 20 10:41:33 2006 +0000
@@ -175,8 +175,8 @@ asmlinkage void vmx_intr_assist(void)
BUG();
break;
}
-
- hvm_interrupt_post(v, highest_vector, intr_type);
+
+ pt_intr_post(v, highest_vector, intr_type);
}
/*
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/vpt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/vpt.c Wed Dec 20 10:41:33 2006 +0000
@@ -0,0 +1,231 @@
+/*
+ * vpt.c: Virtual Platform Timer
+ *
+ * Copyright (c) 2006, Xiaowei Yang, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * 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>
+
+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 together */
+ pt->pending_intr_nr++;
+ }
+ else
+ {
+ pt->pending_intr_nr += missed_ticks;
+ }
+ pt->scheduled += missed_ticks * pt->period;
+ }
+}
+
+void pt_freeze_time(struct vcpu *v)
+{
+ struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+ struct list_head *list;
+ struct periodic_time *pt;
+
+ if ( test_bit(_VCPUF_blocked, &v->vcpu_flags) )
+ return;
+
+ v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
+
+ list_for_each( list, head )
+ {
+ pt = list_entry(list, struct periodic_time, list);
+ stop_timer(&pt->timer);
+ }
+}
+
+void pt_thaw_time(struct vcpu *v)
+{
+ struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+ struct list_head *list;
+ struct periodic_time *pt;
+
+ 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( list, head )
+ {
+ pt = list_entry(list, struct periodic_time, list);
+ missed_ticks(pt);
+ set_timer(&pt->timer, pt->scheduled);
+ }
+ }
+}
+
+/* Hook function for the platform periodic time */
+void pt_timer_fn(void *data)
+{
+ struct periodic_time *pt = data;
+
+ pt->pending_intr_nr++;
+ pt->scheduled += pt->period;
+
+ missed_ticks(pt);
+
+ if ( !pt->one_shot )
+ set_timer(&pt->timer, pt->scheduled);
+
+ vcpu_kick(pt->vcpu);
+}
+
+void pt_update_irq(struct vcpu *v)
+{
+ struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+ struct list_head *list;
+ struct periodic_time *pt;
+ uint64_t max_lag = -1ULL;
+ int irq = -1;
+
+ list_for_each( list, head )
+ {
+ pt = list_entry(list, struct periodic_time, list);
+ if ( !is_irq_masked(v, pt->irq) && pt->pending_intr_nr
+ && pt->last_plt_gtime + pt->period < max_lag )
+ {
+ max_lag = pt->last_plt_gtime + pt->period;
+ irq = pt->irq;
+ }
+ }
+
+ if ( is_lvtt(v, irq) )
+ vlapic_set_irq(vcpu_vlapic(v), irq, 0);
+ else if ( irq >= 0 )
+ {
+ hvm_isa_irq_deassert(v->domain, irq);
+ hvm_isa_irq_assert(v->domain, irq);
+ }
+}
+
+struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
+{
+ struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+ struct list_head *list;
+ struct periodic_time *pt;
+ struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+ int vec;
+
+ list_for_each( list, head )
+ {
+ pt = list_entry(list, struct periodic_time, list);
+ if ( !pt->pending_intr_nr )
+ continue;
+
+ if ( is_lvtt(v, pt->irq) )
+ {
+ if (pt->irq == vector)
+ return pt;
+ else
+ continue;
+ }
+
+ vec = get_intr_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;
+}
+
+void pt_intr_post(struct vcpu *v, int vector, int type)
+{
+ struct periodic_time *pt = is_pt_irq(v, vector, type);
+
+ if (pt == NULL)
+ return;
+
+ pt->pending_intr_nr--;
+ pt->last_plt_gtime += pt->period_cycles;
+ hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime);
+
+ if (pt->cb)
+ pt->cb(pt->vcpu, pt->priv);
+}
+
+/* If pt is enabled, discard pending intr */
+void pt_reset(struct vcpu *v)
+{
+ struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+ struct list_head *list;
+ struct periodic_time *pt;
+
+ list_for_each( list, head )
+ {
+ pt = list_entry(list, struct periodic_time, list);
+ if ( pt->enabled )
+ {
+ pt->pending_intr_nr = 0;
+ pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
+ pt->scheduled = NOW() + pt->period;
+ set_timer(&pt->timer, pt->scheduled);
+ }
+ }
+}
+
+void create_periodic_time(struct periodic_time *pt, uint64_t period,
+ uint8_t irq, char one_shot, time_cb *cb, void *data)
+{
+ destroy_periodic_time(pt);
+
+ pt->enabled = 1;
+ if (period < 900000) /* < 0.9 ms */
+ {
+ printk("HVM_PlatformTime: program too small period %"PRIu64"\n",
period);
+ period = 900000; /* force to 0.9ms */
+ }
+ pt->period = period;
+ pt->vcpu = current;
+ pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
+ pt->irq = irq;
+ pt->period_cycles = (u64)period * cpu_khz / 1000000L;
+ pt->one_shot = one_shot;
+ pt->scheduled = NOW() + period;
+ pt->cb = cb;
+ pt->priv = data;
+
+ list_add(&pt->list, ¤t->arch.hvm_vcpu.tm_list);
+ set_timer(&pt->timer, pt->scheduled);
+}
+
+void destroy_periodic_time(struct periodic_time *pt)
+{
+ if ( pt->enabled )
+ {
+ pt->enabled = 0;
+ pt->pending_intr_nr = 0;
+ list_del(&pt->list);
+ stop_timer(&pt->timer);
+ }
+}
diff -r 2a1edeedf28d -r 516e4faac066 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/include/asm-x86/hvm/vlapic.h Wed Dec 20 10:41:33 2006 +0000
@@ -23,6 +23,7 @@
#include <asm/msr.h>
#include <public/hvm/ioreq.h>
+#include <asm/hvm/vpt.h>
#define MAX_VECTOR 256
@@ -49,14 +50,14 @@
#define vlapic_enabled(vlapic) (!vlapic_disabled(vlapic))
struct vlapic {
- uint64_t apic_base_msr;
- uint32_t disabled; /* VLAPIC_xx_DISABLED */
- uint32_t timer_divisor;
- struct timer vlapic_timer;
- int timer_pending_count;
- s_time_t timer_last_update;
- struct page_info *regs_page;
- void *regs;
+ uint64_t apic_base_msr;
+ uint32_t disabled; /* VLAPIC_xx_DISABLED */
+ uint32_t timer_divisor;
+ struct periodic_time pt;
+ int timer_pending_count;
+ s_time_t timer_last_update;
+ struct page_info *regs_page;
+ void *regs;
};
static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
@@ -70,13 +71,11 @@ static inline void vlapic_set_reg(
*((uint32_t *)(vlapic->regs + reg)) = val;
}
-
int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig);
-
-void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode);
int vlapic_find_highest_irr(struct vlapic *vlapic);
+int vlapic_has_interrupt(struct vcpu *v);
int cpu_get_apic_interrupt(struct vcpu *v, int *mode);
int vlapic_init(struct vcpu *v);
@@ -91,4 +90,7 @@ 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 2a1edeedf28d -r 516e4faac066 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h Wed Dec 20 10:41:33 2006 +0000
@@ -42,10 +42,10 @@ struct periodic_time {
struct list_head list;
char enabled;
char one_shot; /* one shot time */
- int irq;
+ u8 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; /* 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 */
@@ -115,8 +115,8 @@ struct periodic_time *is_pt_irq(struct 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 create_periodic_time(struct periodic_time *pt, uint64_t period,
+ uint8_t 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);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|