aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hvm/vioapic.c4
-rw-r--r--xen/arch/x86/hvm/vlapic.c36
-rw-r--r--xen/arch/x86/hvm/vmsi.c2
-rw-r--r--xen/include/asm-x86/hvm/vlapic.h3
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);