110 lines
3.9 KiB
Diff
110 lines
3.9 KiB
Diff
# HG changeset patch
|
|
# User Keir Fraser <keir.fraser@citrix.com>
|
|
# Date 1227006996 0
|
|
# Node ID ae891977a4d3f5d8d8330ed3796881867b4d88a8
|
|
# Parent 2604400f75e318dc9f5201e3626213290a89862a
|
|
x86, hvm: Implement interrupt routing to least priority processor.
|
|
References: bnc#429904
|
|
|
|
Instead of round robin the vcpu with the lowest processor
|
|
priority is selected for the interrupt. If multiple vcpus
|
|
share the same low priority then interrupts are distributed between
|
|
those round robin.
|
|
|
|
Signed-off-by: Juergen Gross <juergen.gross@fujitsu-siemens.com>
|
|
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
|
|
|
|
--- a/xen/arch/x86/hvm/vioapic.c
|
|
+++ b/xen/arch/x86/hvm/vioapic.c
|
|
@@ -344,8 +344,8 @@ static void vioapic_deliver(struct hvm_h
|
|
}
|
|
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);
|
|
--- 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
|
|
}
|
|
|
|
/* 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 @@ static 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);
|
|
--- 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 p
|
|
{
|
|
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
|
|
--- 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 *vlapi
|
|
|
|
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);
|
|
|