diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-08-19 14:13:52 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-08-19 14:13:52 +0100 |
commit | e03ad58f0b8c6f1735cce59dc8d1dfe9437eb419 (patch) | |
tree | 190f46fa5c201177573437ef51125cd00fd97546 /xen/arch/x86/hvm/vlapic.c | |
parent | 6b55ec407962f865ecfee710d8629ead61d8286b (diff) | |
download | xen-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/vlapic.c')
-rw-r--r-- | xen/arch/x86/hvm/vlapic.c | 75 |
1 files changed, 29 insertions, 46 deletions
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 7b5b033534..cc50cbca41 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -167,7 +167,7 @@ uint32_t vlapic_get_ppr(struct vlapic *vlapic) 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 vlapic *vlapic, uint8_t mda) return result; } -static int vlapic_match_dest(struct vcpu *v, struct vlapic *source, - int short_hand, int dest, int dest_mode) +bool_t vlapic_match_dest( + struct vlapic *target, struct vlapic *source, + int short_hand, uint8_t dest, uint8_t dest_mode) { - int result = 0; - struct vlapic *target = vcpu_vlapic(v); - 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 *v, struct vlapic *source, 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 *v, int delivery_mode, 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 domain *d, uint32_t bitmap) 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,38 +420,35 @@ 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); + trig_mode, level, dest_mode, delivery_mode, vector); + + if ( delivery_mode == APIC_DM_LOWEST ) + { + 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(v, vlapic, short_hand, dest, dest_mode) ) - { - if ( delivery_mode == APIC_DM_LOWEST ) - __set_bit(v->vcpu_id, &lpr_map); - else + 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; } - if ( delivery_mode == APIC_DM_LOWEST ) - { - target = apic_lowest_prio(vlapic_domain(vlapic), lpr_map); - if ( target != NULL ) - rc = vlapic_accept_irq(vlapic_vcpu(target), delivery_mode, - vector, level, trig_mode); - } - return rc; } |