aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-12-12 15:41:20 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-12-12 15:41:20 +0000
commit77f9359c57fc54bdf92bb35294de573f78814166 (patch)
treed261947ec9c5f017be698090f426e62f20020327
parent2d9284c4a58976f7549729b9e2129151bd8a9bc7 (diff)
downloadxen-77f9359c57fc54bdf92bb35294de573f78814166.tar.gz
xen-77f9359c57fc54bdf92bb35294de573f78814166.tar.bz2
xen-77f9359c57fc54bdf92bb35294de573f78814166.zip
hvm: Reduce vpt.c dependencies on external timer details.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/hvm/i8254.c2
-rw-r--r--xen/arch/x86/hvm/irq.c25
-rw-r--r--xen/arch/x86/hvm/rtc.c10
-rw-r--r--xen/arch/x86/hvm/vlapic.c17
-rw-r--r--xen/arch/x86/hvm/vpt.c90
-rw-r--r--xen/include/asm-x86/hvm/irq.h3
-rw-r--r--xen/include/asm-x86/hvm/vlapic.h3
-rw-r--r--xen/include/asm-x86/hvm/vpt.h11
8 files changed, 77 insertions, 84 deletions
diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c
index 5ca76f1276..8814d4b1e1 100644
--- a/xen/arch/x86/hvm/i8254.c
+++ b/xen/arch/x86/hvm/i8254.c
@@ -501,6 +501,8 @@ void pit_init(struct vcpu *v, unsigned long cpu_khz)
/* 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 --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index 0d737f9eed..dc35eda989 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -347,31 +347,6 @@ struct hvm_intack hvm_vcpu_ack_pending_irq(
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)
{
struct hvm_intack intack;
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index c4b082a322..ece6f29ad9 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -42,14 +42,6 @@ static void rtc_periodic_cb(struct vcpu *v, void *opaque)
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
* RTC_RATE_SELECT settings */
static void rtc_timer_update(RTCState *s)
@@ -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 --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 2bf3745c8b..059b64538d 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -68,9 +68,6 @@ static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
#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 --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c
index d4bc8690c8..45c9350226 100644
--- a/xen/arch/x86/hvm/vpt.c
+++ b/xen/arch/x86/hvm/vpt.c
@@ -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>
@@ -26,6 +25,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)
{
struct vcpu *v;
@@ -144,29 +183,39 @@ static void pt_timer_fn(void *data)
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;
+ int irq, is_lapic;
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 &&
+ 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;
}
}
+ 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_lvtt(v, irq) )
+ 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;
+ 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 hvm_intack intack)
}
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 --git a/xen/include/asm-x86/hvm/irq.h b/xen/include/asm-x86/hvm/irq.h
index d270685caf..5fd0db3b7d 100644
--- a/xen/include/asm-x86/hvm/irq.h
+++ b/xen/include/asm-x86/hvm/irq.h
@@ -160,7 +160,4 @@ struct hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v);
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 --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h
index 856b532637..d20a627882 100644
--- a/xen/include/asm-x86/hvm/vlapic.h
+++ b/xen/include/asm-x86/hvm/vlapic.h
@@ -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 --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h
index 0831d37dcc..df54f66268 100644
--- a/xen/include/asm-x86/hvm/vpt.h
+++ b/xen/include/asm-x86/hvm/vpt.h
@@ -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 pit_deinit(struct domain *d);
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);