|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] x86/irq: do not release irq until all cleanup is done
On 15.11.2022 13:35, Roger Pau Monne wrote:
> --- a/xen/arch/x86/irq.c
> +++ b/xen/arch/x86/irq.c
> @@ -220,27 +220,27 @@ static void _clear_irq_vector(struct irq_desc *desc)
> clear_bit(vector, desc->arch.used_vectors);
> }
>
> - desc->arch.used = IRQ_UNUSED;
> -
> - trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, tmp_mask);
The use of tmp_mask here was ...
> + if ( unlikely(desc->arch.move_in_progress) )
> + {
> + /* If we were in motion, also clear desc->arch.old_vector */
> + old_vector = desc->arch.old_vector;
> + cpumask_and(tmp_mask, desc->arch.old_cpu_mask, &cpu_online_map);
.. before the variable was updated here. Now you move it past this
update (to the very end of the function). I wonder whether, to keep
things simple in this change, it would be tolerable to leave the
trace_irq_mask() invocation where it was, despite cleanup not having
completed yet at that point. (The alternative would look to be to
act directly on desc->arch.old_cpu_mask in the code you re-indent,
leaving tmp_mask alone. I think that ought to be okay since nothing
else should access that mask anymore. We could even avoid altering
the field, by going from cpumask_and() to a cpu_online() check in
the for_each_cpu() body.)
>
> - if ( likely(!desc->arch.move_in_progress) )
> - return;
> + for_each_cpu(cpu, tmp_mask)
> + {
> + ASSERT(per_cpu(vector_irq, cpu)[old_vector] == irq);
> + TRACE_3D(TRC_HW_IRQ_MOVE_FINISH, irq, old_vector, cpu);
> + per_cpu(vector_irq, cpu)[old_vector] = ~irq;
> + }
>
> - /* If we were in motion, also clear desc->arch.old_vector */
> - old_vector = desc->arch.old_vector;
> - cpumask_and(tmp_mask, desc->arch.old_cpu_mask, &cpu_online_map);
> + release_old_vec(desc);
>
> - for_each_cpu(cpu, tmp_mask)
> - {
> - ASSERT(per_cpu(vector_irq, cpu)[old_vector] == irq);
> - TRACE_3D(TRC_HW_IRQ_MOVE_FINISH, irq, old_vector, cpu);
> - per_cpu(vector_irq, cpu)[old_vector] = ~irq;
> + desc->arch.move_in_progress = 0;
> }
>
> - release_old_vec(desc);
> + write_atomic(&desc->arch.used, IRQ_UNUSED);
Now that there is an ordering requirement between these last two writes,
I think you want to add smp_wmb() after the first one (still inside the
inner scope). write_atomic() is only a volatile asm() (which the compiler
may move under certain conditions) and an access through a volatile
pointer (which isn't ordered with non-volatile memory accesses), but it
is specifically not a memory barrier.
Jan
> - desc->arch.move_in_progress = 0;
> + trace_irq_mask(TRC_HW_IRQ_CLEAR_VECTOR, irq, vector, tmp_mask);
> }
>
> void __init clear_irq_vector(int irq)
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |