# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1250687632 -3600
# Node ID 017762c75beb46eae8996cce9c0761959a793f2b
# Parent 902f4ae65123813aaf660d3b8cf81eb5ba0fa6ff
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@xxxxxxxxxx>
---
xen/arch/x86/hvm/vioapic.c | 106 ++++++++------------------------------
xen/arch/x86/hvm/vlapic.c | 81 +++++++++++------------------
xen/arch/x86/hvm/vmsi.c | 75 +++-----------------------
xen/include/asm-ia64/hvm/vlapic.h | 2
xen/include/asm-x86/hvm/vlapic.h | 12 ++--
5 files changed, 72 insertions(+), 204 deletions(-)
diff -r 902f4ae65123 -r 017762c75beb xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/arch/x86/hvm/vioapic.c Wed Aug 19 14:13:52 2009 +0100
@@ -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 = ¤t->domain->arch.hvm_domain.pl_time.vpit;
@@ -316,24 +276,17 @@ static void vioapic_deliver(struct hvm_h
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_h
/* 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_h
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;
}
diff -r 902f4ae65123 -r 017762c75beb xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Wed Aug 19 14:13:52 2009 +0100
@@ -167,7 +167,7 @@ uint32_t vlapic_get_ppr(struct vlapic *v
return ppr;
}
-int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
+static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
{
int result = 0;
uint8_t logical_id;
@@ -194,12 +194,10 @@ int vlapic_match_logical_addr(struct vla
return result;
}
-static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
- int short_hand, int dest, int dest_mode)
-{
- int result = 0;
- struct vlapic *target = vcpu_vlapic(v);
-
+bool_t vlapic_match_dest(
+ struct vlapic *target, struct vlapic *source,
+ int short_hand, uint8_t dest, uint8_t dest_mode)
+{
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest 0x%x, "
"dest_mode 0x%x, short_hand 0x%x",
target, source, dest, dest_mode, short_hand);
@@ -207,39 +205,25 @@ static int vlapic_match_dest(struct vcpu
switch ( short_hand )
{
case APIC_DEST_NOSHORT:
- if ( dest_mode == 0 )
- {
- /* Physical mode. */
- if ( (dest == 0xFF) || (dest == VLAPIC_ID(target)) )
- result = 1;
- }
- else
- {
- /* Logical mode. */
- result = vlapic_match_logical_addr(target, dest);
- }
- break;
+ if ( dest_mode )
+ return vlapic_match_logical_addr(target, dest);
+ return ((dest == 0xFF) || (dest == VLAPIC_ID(target)));
case APIC_DEST_SELF:
- if ( target == source )
- result = 1;
- break;
+ return (target == source);
case APIC_DEST_ALLINC:
- result = 1;
- break;
+ return 1;
case APIC_DEST_ALLBUT:
- if ( target != source )
- result = 1;
- break;
+ return (target != source);
default:
gdprintk(XENLOG_WARNING, "Bad dest shorthand value %x\n", short_hand);
break;
}
- return result;
+ return 0;
}
static int vlapic_vcpu_pause_async(struct vcpu *v)
@@ -376,8 +360,9 @@ static int vlapic_accept_irq(struct vcpu
return rc;
}
-/* This function is used by both ioapic and lapic.The bitmap is for vcpu_id. */
-struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap)
+struct vlapic *vlapic_lowest_prio(
+ struct domain *d, struct vlapic *source,
+ int short_hand, uint8_t dest, uint8_t dest_mode)
{
int old = d->arch.hvm_domain.irq.round_robin_prev_vcpu;
uint32_t ppr, target_ppr = UINT_MAX;
@@ -390,7 +375,8 @@ struct vlapic *apic_lowest_prio(struct d
do {
v = v->next_in_list ? : d->vcpu[0];
vlapic = vcpu_vlapic(v);
- if ( test_bit(v->vcpu_id, &bitmap) && vlapic_enabled(vlapic) &&
+ if ( vlapic_match_dest(vlapic, source, short_hand, dest, dest_mode) &&
+ vlapic_enabled(vlapic) &&
((ppr = vlapic_get_ppr(vlapic)) < target_ppr) )
{
target = vlapic;
@@ -434,36 +420,33 @@ int vlapic_ipi(
struct vlapic *target;
struct vcpu *v;
- uint32_t lpr_map = 0;
int rc = X86EMUL_OKAY;
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr_high 0x%x, icr_low 0x%x, "
"short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
"dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x",
icr_high, icr_low, short_hand, dest,
- trig_mode, level, dest_mode, delivery_mode, vector);
-
- for_each_vcpu ( vlapic_domain(vlapic), v )
- {
- if ( vlapic_match_dest(v, vlapic, short_hand, dest, dest_mode) )
- {
- if ( delivery_mode == APIC_DM_LOWEST )
- __set_bit(v->vcpu_id, &lpr_map);
- else
- rc = vlapic_accept_irq(v, delivery_mode,
- vector, level, trig_mode);
- }
-
- if ( rc != X86EMUL_OKAY )
- break;
- }
+ trig_mode, level, dest_mode, delivery_mode, vector);
if ( delivery_mode == APIC_DM_LOWEST )
{
- target = apic_lowest_prio(vlapic_domain(vlapic), lpr_map);
+ target = vlapic_lowest_prio(vlapic_domain(vlapic), vlapic,
+ short_hand, dest, dest_mode);
if ( target != NULL )
rc = vlapic_accept_irq(vlapic_vcpu(target), delivery_mode,
vector, level, trig_mode);
+ return rc;
+ }
+
+ for_each_vcpu ( vlapic_domain(vlapic), v )
+ {
+ if ( vlapic_match_dest(vcpu_vlapic(v), vlapic,
+ short_hand, dest, dest_mode) )
+ rc = vlapic_accept_irq(v, delivery_mode,
+ vector, level, trig_mode);
+
+ if ( rc != X86EMUL_OKAY )
+ break;
}
return rc;
diff -r 902f4ae65123 -r 017762c75beb xen/arch/x86/hvm/vmsi.c
--- a/xen/arch/x86/hvm/vmsi.c Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/arch/x86/hvm/vmsi.c Wed Aug 19 14:13:52 2009 +0100
@@ -40,46 +40,6 @@
#include <asm/current.h>
#include <asm/event.h>
-static uint32_t vmsi_get_delivery_bitmask(
- struct domain *d, uint16_t dest, uint8_t dest_mode)
-{
- uint32_t mask = 0;
- struct vcpu *v;
-
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
- "dest %d dest_mode %d\n", dest, dest_mode);
-
- if ( dest_mode == 0 ) /* Physical mode. */
- {
- if ( dest == 0xFF ) /* Broadcast. */
- {
- for_each_vcpu ( d, v )
- mask |= 1 << v->vcpu_id;
- goto out;
- }
-
- for_each_vcpu ( d, 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 ( d, v )
- if ( vlapic_match_logical_addr(vcpu_vlapic(v), dest) )
- mask |= 1 << v->vcpu_id;
- }
-
- out:
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask mask %x\n",
- mask);
- return mask;
-}
-
static void vmsi_inj_irq(
struct domain *d,
struct vlapic *target,
@@ -87,7 +47,7 @@ static void vmsi_inj_irq(
uint8_t trig_mode,
uint8_t delivery_mode)
{
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vmsi_inj_irq "
"irq %d trig %d delive mode %d\n",
vector, trig_mode, delivery_mode);
@@ -125,7 +85,6 @@ int vmsi_deliver(struct domain *d, int p
uint8_t dest_mode = (flags & VMSI_DM_MASK) >> GFLAGS_SHIFT_DM;
uint8_t delivery_mode = (flags & VMSI_DELIV_MASK) >>
GLFAGS_SHIFT_DELIV_MODE;
uint8_t trig_mode = (flags & VMSI_TRIG_MODE) >> GLFAGS_SHIFT_TRG_MODE;
- uint32_t deliver_bitmask;
struct vlapic *target;
struct vcpu *v;
@@ -140,44 +99,28 @@ int vmsi_deliver(struct domain *d, int p
return 0;
}
- deliver_bitmask = vmsi_get_delivery_bitmask(d, dest, dest_mode);
- if ( !deliver_bitmask )
- {
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
- "no target on destination\n");
- return 0;
- }
-
switch ( delivery_mode )
{
case dest_LowestPrio:
{
- target = apic_lowest_prio(d, deliver_bitmask);
+ target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
if ( target != NULL )
vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
else
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
- "mask=%x vector=%x delivery_mode=%x\n",
- deliver_bitmask, vector, dest_LowestPrio);
+ "vector=%x delivery_mode=%x\n",
+ vector, dest_LowestPrio);
break;
}
case dest_Fixed:
case dest_ExtINT:
{
- uint8_t bit;
- for ( bit = 0; deliver_bitmask != 0; bit++ )
- {
- if ( !(deliver_bitmask & (1 << bit)) )
- continue;
- deliver_bitmask &= ~(1 << bit);
- v = d->vcpu[bit];
- if ( v != NULL )
- {
- target = vcpu_vlapic(v);
- vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
- }
- }
+ for_each_vcpu ( d, v )
+ if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
+ 0, dest, dest_mode) )
+ vmsi_inj_irq(d, vcpu_vlapic(v),
+ vector, trig_mode, delivery_mode);
break;
}
diff -r 902f4ae65123 -r 017762c75beb xen/include/asm-ia64/hvm/vlapic.h
--- a/xen/include/asm-ia64/hvm/vlapic.h Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/include/asm-ia64/hvm/vlapic.h Wed Aug 19 14:13:52 2009 +0100
@@ -1,6 +1,4 @@
#ifndef __ASM_IA64_HVM_VLAPIC_H__
#define __ASM_IA64_HVM_VLAPIC_H__
-int vlapic_match_logical_addr(struct vlapic *vlapic, uint16_t dest);
-
#endif /* __ASM_IA64_HVM_VLAPIC_H__ */
diff -r 902f4ae65123 -r 017762c75beb xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h Wed Aug 19 13:17:41 2009 +0100
+++ b/xen/include/asm-x86/hvm/vlapic.h Wed Aug 19 14:13:52 2009 +0100
@@ -94,12 +94,16 @@ int vlapic_accept_pic_intr(struct vcpu *
void vlapic_adjust_i8259_target(struct domain *d);
-struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap);
-
-int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
-
void vlapic_EOI_set(struct vlapic *vlapic);
int vlapic_ipi(struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high);
+struct vlapic *vlapic_lowest_prio(
+ struct domain *d, struct vlapic *source,
+ int short_hand, uint8_t dest, uint8_t dest_mode);
+
+bool_t vlapic_match_dest(
+ struct vlapic *target, struct vlapic *source,
+ int short_hand, uint8_t dest, uint8_t dest_mode);
+
#endif /* __ASM_X86_HVM_VLAPIC_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|