[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86 hvm: Clean up vlapic/vioapic/vmsi delivery.
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |