# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1197474080 0
# Node ID 4553bc1087d9f73e5c27f5511c1d4c724b4dbccf
# Parent 20898120c8f9b56902ceedb8deaf977175445f2f
hvm: Reduce vpt.c dependencies on external timer details.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/hvm/i8254.c | 2
xen/arch/x86/hvm/irq.c | 25 --------
xen/arch/x86/hvm/rtc.c | 10 ---
xen/arch/x86/hvm/vlapic.c | 17 ------
xen/arch/x86/hvm/vpt.c | 110 +++++++++++++++++++++++++--------------
xen/include/asm-x86/hvm/irq.h | 3 -
xen/include/asm-x86/hvm/vlapic.h | 3 -
xen/include/asm-x86/hvm/vpt.h | 11 ++-
8 files changed, 87 insertions(+), 94 deletions(-)
diff -r 20898120c8f9 -r 4553bc1087d9 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/arch/x86/hvm/i8254.c Wed Dec 12 15:41:20 2007 +0000
@@ -501,6 +501,8 @@ void pit_init(struct vcpu *v, unsigned l
/* Some sub-functions assert that they are called with the lock held. */
spin_lock(&pit->lock);
+ pit->pt0.source = PTSRC_isa;
+
register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
ticks_per_sec(v) = cpu_khz * (int64_t)1000;
diff -r 20898120c8f9 -r 4553bc1087d9 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/arch/x86/hvm/irq.c Wed Dec 12 15:41:20 2007 +0000
@@ -345,31 +345,6 @@ struct hvm_intack hvm_vcpu_ack_pending_i
}
return intack;
-}
-
-int get_isa_irq_vector(struct vcpu *v, int isa_irq, enum hvm_intsrc src)
-{
- unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
-
- if ( src == hvm_intsrc_pic )
- return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
- + (isa_irq & 7));
-
- ASSERT(src == hvm_intsrc_lapic);
- 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);
}
int hvm_local_events_need_delivery(struct vcpu *v)
diff -r 20898120c8f9 -r 4553bc1087d9 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/arch/x86/hvm/rtc.c Wed Dec 12 15:41:20 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 20898120c8f9 -r 4553bc1087d9 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Wed Dec 12 15:41:20 2007 +0000
@@ -68,9 +68,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)
@@ -932,6 +929,8 @@ int vlapic_init(struct vcpu *v)
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "%d", v->vcpu_id);
+ vlapic->pt.source = PTSRC_lapic;
+
#ifdef __i386__
/* 32-bit VMX may be limited to 32-bit physical addresses. */
if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
@@ -974,15 +973,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 20898120c8f9 -r 4553bc1087d9 xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/arch/x86/hvm/vpt.c Wed Dec 12 15:41:20 2007 +0000
@@ -15,7 +15,6 @@
* 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>
@@ -25,6 +24,46 @@
#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, enum hvm_intsrc src)
+{
+ 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 ( src == hvm_intsrc_pic )
+ return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
+ + (isa_irq & 7));
+
+ ASSERT(src == hvm_intsrc_lapic);
+ 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)
{
@@ -144,29 +183,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);
@@ -178,29 +227,12 @@ static struct periodic_time *is_pt_irq(
{
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 vector;
-
- list_for_each_entry ( pt, head, list )
- {
- if ( !pt->pending_intr_nr )
- continue;
-
- if ( is_lvtt(v, pt->irq) )
- {
- if ( pt->irq != intack.vector )
- continue;
+
+ list_for_each_entry ( pt, head, list )
+ {
+ if ( pt->pending_intr_nr && pt->irq_issued &&
+ (intack.vector == pt_irq_vector(pt, intack.source)) )
return pt;
- }
-
- vector = get_isa_irq_vector(v, pt->irq, intack.source);
-
- /* RTC irq need special care */
- if ( (intack.vector != vector) ||
- ((pt->irq == 8) && !is_rtc_periodic_irq(rtc)) )
- continue;
-
- return pt;
}
return NULL;
@@ -222,6 +254,7 @@ void pt_intr_post(struct vcpu *v, struct
}
pt->do_not_freeze = 0;
+ pt->irq_issued = 0;
if ( pt->one_shot )
{
@@ -291,12 +324,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 )
@@ -319,7 +355,7 @@ void create_periodic_time(
* LAPIC ticks for process accounting can see long sequences of process
* ticks incorrectly accounted to interrupt processing.
*/
- if ( is_lvtt(v, irq) )
+ if ( pt->source == PTSRC_lapic )
pt->scheduled += period >> 1;
pt->cb = cb;
pt->priv = data;
diff -r 20898120c8f9 -r 4553bc1087d9 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/include/asm-x86/hvm/irq.h Wed Dec 12 15:41:20 2007 +0000
@@ -160,7 +160,4 @@ struct hvm_intack hvm_vcpu_ack_pending_i
struct hvm_intack hvm_vcpu_ack_pending_irq(struct vcpu *v,
struct hvm_intack intack);
-int get_isa_irq_vector(struct vcpu *vcpu, int irq, enum hvm_intsrc src);
-int is_isa_irq_masked(struct vcpu *v, int isa_irq);
-
#endif /* __ASM_X86_HVM_IRQ_H__ */
diff -r 20898120c8f9 -r 4553bc1087d9 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/include/asm-x86/hvm/vlapic.h Wed Dec 12 15:41:20 2007 +0000
@@ -92,7 +92,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 20898120c8f9 -r 4553bc1087d9 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Wed Dec 12 12:02:01 2007 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h Wed Dec 12 15:41:20 2007 +0000
@@ -75,6 +75,10 @@ struct periodic_time {
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 */
@@ -146,8 +150,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.
*/
@@ -163,7 +169,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);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|