aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/vioapic.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-08-19 14:13:52 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-08-19 14:13:52 +0100
commite03ad58f0b8c6f1735cce59dc8d1dfe9437eb419 (patch)
tree190f46fa5c201177573437ef51125cd00fd97546 /xen/arch/x86/hvm/vioapic.c
parent6b55ec407962f865ecfee710d8629ead61d8286b (diff)
downloadxen-e03ad58f0b8c6f1735cce59dc8d1dfe9437eb419.tar.gz
xen-e03ad58f0b8c6f1735cce59dc8d1dfe9437eb419.tar.bz2
xen-e03ad58f0b8c6f1735cce59dc8d1dfe9437eb419.zip
x86 hvm: Clean up vlapic/vioapic/vmsi delivery.
In particular, avoid intermediate delivery bitmaps which restrict number of vcpus supported. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/arch/x86/hvm/vioapic.c')
-rw-r--r--xen/arch/x86/hvm/vioapic.c106
1 files changed, 23 insertions, 83 deletions
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 9afbe75655..89c7f694d7 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -263,46 +263,6 @@ static void ioapic_inj_irq(
vcpu_kick(vlapic_vcpu(target));
}
-static uint32_t ioapic_get_delivery_bitmask(
- struct hvm_hw_vioapic *vioapic, uint16_t dest, uint8_t dest_mode)
-{
- uint32_t mask = 0;
- struct vcpu *v;
-
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "dest %d dest_mode %d",
- dest, dest_mode);
-
- if ( dest_mode == 0 ) /* Physical mode. */
- {
- if ( dest == 0xFF ) /* Broadcast. */
- {
- for_each_vcpu ( vioapic_domain(vioapic), v )
- mask |= 1 << v->vcpu_id;
- goto out;
- }
-
- for_each_vcpu ( vioapic_domain(vioapic), v )
- {
- if ( VLAPIC_ID(vcpu_vlapic(v)) == dest )
- {
- mask = 1 << v->vcpu_id;
- break;
- }
- }
- }
- else if ( dest != 0 ) /* Logical mode, MDA non-zero. */
- {
- for_each_vcpu ( vioapic_domain(vioapic), v )
- if ( vlapic_match_logical_addr(vcpu_vlapic(v), dest) )
- mask |= 1 << v->vcpu_id;
- }
-
- out:
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "mask %x",
- mask);
- return mask;
-}
-
static inline int pit_channel0_enabled(void)
{
PITState *pit = &current->domain->arch.hvm_domain.pl_time.vpit;
@@ -316,24 +276,17 @@ static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq)
uint8_t delivery_mode = vioapic->redirtbl[irq].fields.delivery_mode;
uint8_t vector = vioapic->redirtbl[irq].fields.vector;
uint8_t trig_mode = vioapic->redirtbl[irq].fields.trig_mode;
- uint32_t deliver_bitmask;
+ struct domain *d = vioapic_domain(vioapic);
struct vlapic *target;
struct vcpu *v;
- ASSERT(spin_is_locked(&vioapic_domain(vioapic)->arch.hvm_domain.irq_lock));
+ ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
"dest=%x dest_mode=%x delivery_mode=%x "
"vector=%x trig_mode=%x",
dest, dest_mode, delivery_mode, vector, trig_mode);
- deliver_bitmask = ioapic_get_delivery_bitmask(vioapic, dest, dest_mode);
- if ( !deliver_bitmask )
- {
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "no target on destination");
- return;
- }
-
switch ( delivery_mode )
{
case dest_LowestPrio:
@@ -342,14 +295,12 @@ static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq)
/* Force round-robin to pick VCPU 0 */
if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
{
- v = vioapic_domain(vioapic)->vcpu ?
- vioapic_domain(vioapic)->vcpu[0] : NULL;
+ v = d->vcpu ? d->vcpu[0] : NULL;
target = v ? vcpu_vlapic(v) : NULL;
}
else
#endif
- target = apic_lowest_prio(vioapic_domain(vioapic),
- deliver_bitmask);
+ target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
if ( target != NULL )
{
ioapic_inj_irq(vioapic, target, vector, trig_mode, delivery_mode);
@@ -357,52 +308,41 @@ static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq)
else
{
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
- "mask=%x vector=%x delivery_mode=%x",
- deliver_bitmask, vector, dest_LowestPrio);
+ "vector=%x delivery_mode=%x",
+ vector, dest_LowestPrio);
}
break;
}
case dest_Fixed:
{
- uint8_t bit;
- for ( bit = 0; deliver_bitmask != 0; bit++ )
- {
- if ( !(deliver_bitmask & (1 << bit)) )
- continue;
- deliver_bitmask &= ~(1 << bit);
- if ( vioapic_domain(vioapic)->vcpu == NULL )
- v = NULL;
#ifdef IRQ0_SPECIAL_ROUTING
- /* Do not deliver timer interrupts to VCPU != 0 */
- else if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
- v = vioapic_domain(vioapic)->vcpu[0];
-#endif
- else
- v = vioapic_domain(vioapic)->vcpu[bit];
- if ( v != NULL )
- {
- target = vcpu_vlapic(v);
- ioapic_inj_irq(vioapic, target, vector,
+ /* Do not deliver timer interrupts to VCPU != 0 */
+ if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
+ {
+ if ( (v = d->vcpu ? d->vcpu[0] : NULL) != NULL )
+ ioapic_inj_irq(vioapic, vcpu_vlapic(v), vector,
trig_mode, delivery_mode);
- }
+ }
+ else
+#endif
+ {
+ for_each_vcpu ( d, v )
+ if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
+ 0, dest, dest_mode) )
+ ioapic_inj_irq(vioapic, vcpu_vlapic(v), vector,
+ trig_mode, delivery_mode);
}
break;
}
case dest_NMI:
{
- uint8_t bit;
- for ( bit = 0; deliver_bitmask != 0; bit++ )
- {
- if ( !(deliver_bitmask & (1 << bit)) )
- continue;
- deliver_bitmask &= ~(1 << bit);
- if ( (vioapic_domain(vioapic)->vcpu != NULL) &&
- ((v = vioapic_domain(vioapic)->vcpu[bit]) != NULL) &&
+ for_each_vcpu ( d, v )
+ if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
+ 0, dest, dest_mode) &&
!test_and_set_bool(v->nmi_pending) )
vcpu_kick(v);
- }
break;
}