On 08/09/2017 09:06 AM, Michael Ellerman wrote:
> Cédric Le Goater <c...@kaod.org> writes:
>> When called from xive_irq_startup(), the size of the cpumask can be
>> larger than nr_cpu_ids. Most of time, its value is NR_CPUS (2048).
> 
> Ugh, you're right.
> 
>   #define nr_cpumask_bits     ((unsigned int)NR_CPUS)
>   ...
>   /**
>    * cpumask_weight - Count of bits in *srcp
>    * @srcp: the cpumask to count bits (< nr_cpu_ids) in.
>    */
>   static inline unsigned int cpumask_weight(const struct cpumask *srcp)
>   {
>       return bitmap_weight(cpumask_bits(srcp), nr_cpumask_bits);
>   }
> 
> 
> I don't know what the comment on srcp is trying to say. It's not true
> that it only counts nr_cpu_ids worth of bits.
> 
> So it does seem if we're passed a mask with > nr_cpu_ids bits set then
> cpumask_weight() will return > nr_cpu_ids, which is .. unhelpful.
> 
> 
> BUT, I don't see other code handling cpumask_weight() returning >
> nr_cpu_ids - at least I can't find any with some grepping.
> 
> 
> So what is going wrong here that we're being passed a mask with more
> than nr_cpu_ids bits set?
> 
> I think the affinity mask is copied to the desc in desc_smp_init(), and
> the call chain will be:
> 
>   irq_create_mapping()
>     -> irq_domain_alloc_descs()
>        -> __irq_alloc_descs()
>           -> alloc_descs()
>              -> alloc_desc()
>                 -> desc_set_defaults()
>                    -> desc_smp_init()
> 
> irq_create_mapping() is doing:
> 
>   virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL);
> 
> Where the affinity mask is the NULL at the end.
> 
> So presumably we're hitting the irq_default_affinity case here:
> 
>   static void desc_smp_init(struct irq_desc *desc, int node,
>                         const struct cpumask *affinity)
>   {
>       if (!affinity)
>               affinity = irq_default_affinity;
>       cpumask_copy(desc->irq_common_data.affinity, affinity);
> 
> 
> Which comes from:
> 
>   static void __init init_irq_default_affinity(void)
>   {
>   #ifdef CONFIG_CPUMASK_OFFSTACK
>       if (!irq_default_affinity)
>               zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
>   #endif
>       if (cpumask_empty(irq_default_affinity))
>               cpumask_setall(irq_default_affinity);
>   }
> 
> And cpumask_setall() will indeed set NR_CPUs bits.
> 
> 
> So that all seems sane, except that it does mean cpumask_weight() can
> return > nr_cpu_ids which is awkward.
> 
> I guess this patch is a good fix, I'll expand the change log a bit.

Yes. Thanks for the digging. I didn't do as much.

Cheers,

C.

Reply via email to