diff options
-rw-r--r-- | xen/arch/x86/hvm/vioapic.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vlapic.c | 36 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmsi.c | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vlapic.h | 3 |
4 files changed, 24 insertions, 21 deletions
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 7250de3a7d..7f63699ab2 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -344,8 +344,8 @@ static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq) } else #endif - target = apic_round_robin(vioapic_domain(vioapic), - vector, deliver_bitmask); + target = apic_lowest_prio(vioapic_domain(vioapic), + deliver_bitmask); if ( target != NULL ) { ioapic_inj_irq(vioapic, target, vector, trig_mode, delivery_mode); diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index d201af2848..68e9b27632 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -377,26 +377,30 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode, } /* This function is used by both ioapic and lapic.The bitmap is for vcpu_id. */ -struct vlapic *apic_round_robin( - struct domain *d, uint8_t vector, uint32_t bitmap) +struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap) { - int next, old; - struct vlapic *target = NULL; + int old = d->arch.hvm_domain.irq.round_robin_prev_vcpu; + uint32_t ppr, target_ppr = UINT_MAX; + struct vlapic *vlapic, *target = NULL; + struct vcpu *v; - old = next = d->arch.hvm_domain.irq.round_robin_prev_vcpu; + if ( unlikely((v = d->vcpu[old]) == NULL) ) + return NULL; do { - if ( ++next == MAX_VIRT_CPUS ) - next = 0; - if ( (d->vcpu[next] == NULL) || !test_bit(next, &bitmap) ) - continue; - target = vcpu_vlapic(d->vcpu[next]); - if ( vlapic_enabled(target) ) - break; - target = NULL; - } while ( next != old ); + v = v->next_in_list ? : d->vcpu[0]; + vlapic = vcpu_vlapic(v); + if ( test_bit(v->vcpu_id, &bitmap) && vlapic_enabled(vlapic) && + ((ppr = vlapic_get_ppr(vlapic)) < target_ppr) ) + { + target = vlapic; + target_ppr = ppr; + } + } while ( v->vcpu_id != old ); - d->arch.hvm_domain.irq.round_robin_prev_vcpu = next; + if ( target != NULL ) + d->arch.hvm_domain.irq.round_robin_prev_vcpu = + vlapic_vcpu(target)->vcpu_id; return target; } @@ -456,7 +460,7 @@ int vlapic_ipi( if ( delivery_mode == APIC_DM_LOWEST ) { - target = apic_round_robin(vlapic_domain(v), vector, lpr_map); + target = apic_lowest_prio(vlapic_domain(v), lpr_map); if ( target != NULL ) rc = vlapic_accept_irq(vlapic_vcpu(target), delivery_mode, vector, level, trig_mode); diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c index 6eefb61bfa..cc9e9adde5 100644 --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -152,7 +152,7 @@ int vmsi_deliver(struct domain *d, int pirq) { case dest_LowestPrio: { - target = apic_round_robin(d, vector, deliver_bitmask); + target = apic_lowest_prio(d, deliver_bitmask); if ( target != NULL ) vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode); else diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h index 3f34e47950..8c36ed5a00 100644 --- a/xen/include/asm-x86/hvm/vlapic.h +++ b/xen/include/asm-x86/hvm/vlapic.h @@ -93,8 +93,7 @@ void vlapic_msr_set(struct vlapic *vlapic, uint64_t value); int vlapic_accept_pic_intr(struct vcpu *v); -struct vlapic *apic_round_robin( - struct domain *d, uint8_t vector, uint32_t bitmap); +struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap); int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda); |