mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/IRQ: deal with move cleanup count state in fixup_irqs()
The cleanup IPI may get sent immediately before a CPU gets removed from the online map. In such a case the IPI would get handled on the CPU being offlined no earlier than in the interrupts disabled window after fixup_irqs()' main loop. This is too late, however, because a possible affinity change may incur the need for vector assignment, which will fail when the IRQ's move cleanup count is still non-zero. To fix this - record the set of CPUs the cleanup IPIs gets actually sent to alongside setting their count, - adjust the count in fixup_irqs(), accounting for all CPUs that the cleanup IPI was sent to, but that are no longer online, - bail early from the cleanup IPI handler when the CPU is no longer online, to prevent double accounting. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
9260609aa9
commit
472e0b74c5
1 file changed
+20
-4
+20
-4
@@ -675,6 +675,9 @@ void irq_move_cleanup_interrupt(struct cpu_user_regs *regs)
|
||||
ack_APIC_irq();
|
||||
|
||||
me = smp_processor_id();
|
||||
if ( !cpu_online(me) )
|
||||
return;
|
||||
|
||||
for ( vector = FIRST_DYNAMIC_VECTOR;
|
||||
vector <= LAST_HIPRIORITY_VECTOR; vector++)
|
||||
{
|
||||
@@ -735,11 +738,14 @@ unlock:
|
||||
|
||||
static void send_cleanup_vector(struct irq_desc *desc)
|
||||
{
|
||||
cpumask_t cleanup_mask;
|
||||
cpumask_and(desc->arch.old_cpu_mask, desc->arch.old_cpu_mask,
|
||||
&cpu_online_map);
|
||||
desc->arch.move_cleanup_count = cpumask_weight(desc->arch.old_cpu_mask);
|
||||
|
||||
cpumask_and(&cleanup_mask, desc->arch.old_cpu_mask, &cpu_online_map);
|
||||
desc->arch.move_cleanup_count = cpumask_weight(&cleanup_mask);
|
||||
send_IPI_mask(&cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
|
||||
if ( desc->arch.move_cleanup_count )
|
||||
send_IPI_mask(desc->arch.old_cpu_mask, IRQ_MOVE_CLEANUP_VECTOR);
|
||||
else
|
||||
release_old_vec(desc);
|
||||
|
||||
desc->arch.move_in_progress = 0;
|
||||
}
|
||||
@@ -2419,6 +2425,16 @@ void fixup_irqs(const cpumask_t *mask, bool verbose)
|
||||
vector <= LAST_HIPRIORITY_VECTOR )
|
||||
cpumask_and(desc->arch.cpu_mask, desc->arch.cpu_mask, mask);
|
||||
|
||||
if ( desc->arch.move_cleanup_count )
|
||||
{
|
||||
/* The cleanup IPI may have got sent while we were still online. */
|
||||
cpumask_andnot(&affinity, desc->arch.old_cpu_mask,
|
||||
&cpu_online_map);
|
||||
desc->arch.move_cleanup_count -= cpumask_weight(&affinity);
|
||||
if ( !desc->arch.move_cleanup_count )
|
||||
release_old_vec(desc);
|
||||
}
|
||||
|
||||
cpumask_copy(&affinity, desc->affinity);
|
||||
if ( !desc->action || cpumask_subset(&affinity, mask) )
|
||||
{
|
||||
|
||||