mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/irq: set accurate cpu_mask for high priority vectors used by external interrupts
Setting the irq descriptor target CPU mask of high priority interrupts to
contain all online CPUs is not accurate. External interrupts are
exclusively delivered using physical destination mode, and hence can only
target a single CPU. Setting the descriptor CPU mask to contain all online
CPUs makes it impossible for Xen to figure out which CPU the interrupt is
really targeting.
Instead handle high priority vectors used by external interrupts similarly
to normal vectors, keeping the target CPU mask accurate. Introduce
specific code in _assign_irq_vector() to deal with moving high priority
vectors across CPUs, this is needed at least for fixup_irqs() to be able to
evacuate those if the target CPU goes offline.
Fixes: fc0c3fa2ad ("x86/IO-APIC: fix setup of Xen internally used IRQs (take 2)")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
c2d6dc7c68
commit
68dda501d9
2 files changed
+26
-7
No files matched your search
+24
-6
@@ -547,6 +547,20 @@ static int _assign_irq_vector(struct irq_desc *desc, const cpumask_t *mask)
|
||||
cpumask_t tmp_mask;
|
||||
|
||||
cpumask_and(&tmp_mask, mask, &cpu_online_map);
|
||||
|
||||
/*
|
||||
* High priority vectors are reserved on all CPUs, hence moving them
|
||||
* just requires changing the target CPU. There's no need for vector
|
||||
* allocation on the destination.
|
||||
*/
|
||||
if ( old_vector >= FIRST_HIPRIORITY_VECTOR &&
|
||||
old_vector <= LAST_HIPRIORITY_VECTOR )
|
||||
{
|
||||
cpumask_copy(desc->arch.cpu_mask,
|
||||
cpumask_of(cpumask_any(&tmp_mask)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cpumask_intersects(&tmp_mask, desc->arch.cpu_mask)) {
|
||||
desc->arch.vector = old_vector;
|
||||
return 0;
|
||||
@@ -756,12 +770,16 @@ void setup_vector_irq(unsigned int cpu)
|
||||
if ( !irq_desc_initialized(desc) )
|
||||
continue;
|
||||
vector = irq_to_vector(irq);
|
||||
if ( vector >= FIRST_HIPRIORITY_VECTOR &&
|
||||
vector <= LAST_HIPRIORITY_VECTOR )
|
||||
cpumask_set_cpu(cpu, desc->arch.cpu_mask);
|
||||
else if ( !cpumask_test_cpu(cpu, desc->arch.cpu_mask) )
|
||||
continue;
|
||||
per_cpu(vector_irq, cpu)[vector] = irq;
|
||||
if ( cpumask_test_cpu(cpu, desc->arch.cpu_mask) ||
|
||||
/*
|
||||
* High-priority vectors are reserved on all CPUs. Set
|
||||
* the vector to IRQ assignment on all CPUs, even if the
|
||||
* interrupt is not targeting this CPU. That makes
|
||||
* shuffling those interrupts around CPUs easier.
|
||||
*/
|
||||
(vector >= FIRST_HIPRIORITY_VECTOR &&
|
||||
vector <= LAST_HIPRIORITY_VECTOR) )
|
||||
per_cpu(vector_irq, cpu)[vector] = irq;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1464,7 +1464,8 @@ void __init smp_intr_init(void)
|
||||
|
||||
desc = irq_to_desc(irq);
|
||||
desc->arch.vector = vector;
|
||||
cpumask_copy(desc->arch.cpu_mask, &cpu_online_map);
|
||||
cpumask_copy(desc->arch.cpu_mask, cpumask_of(cpu));
|
||||
cpumask_setall(desc->affinity);
|
||||
}
|
||||
|
||||
/* Direct IPI vectors. */
|
||||
|
||||