x86/apic: Make cpu_mask_to_apicid() operations check cpu_online_mask

Currently cpu_mask_to_apicid() should not get a offline CPU with
the cpumask. Otherwise some apic drivers might try to access
non-existent per-cpu variables (i.e. x2apic). In that regard
cpu_mask_to_apicid() and cpu_mask_to_apicid_and() operations are
inconsistent.

This fix makes the two operations do not rely on calling
functions and always return the apicid for only online CPUs. As
result, the meaning and implementations of cpu_mask_to_apicid()
and cpu_mask_to_apicid_and() operations become straight.

Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/20120607131624.GG4759@dhcp-26-207.brq.redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Alexander Gordeev 2012-06-07 15:16:25 +02:00 коммит произвёл Ingo Molnar
Родитель ff16432412
Коммит 4988a40c39
6 изменённых файлов: 7 добавлений и 11 удалений

Просмотреть файл

@ -596,7 +596,7 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
static inline int static inline int
__flat_cpu_mask_to_apicid(unsigned long cpu_mask, unsigned int *apicid) __flat_cpu_mask_to_apicid(unsigned long cpu_mask, unsigned int *apicid)
{ {
cpu_mask &= APIC_ALL_CPUS; cpu_mask = cpu_mask & APIC_ALL_CPUS & cpumask_bits(cpu_online_mask)[0];
if (likely(cpu_mask)) { if (likely(cpu_mask)) {
*apicid = (unsigned int)cpu_mask; *apicid = (unsigned int)cpu_mask;
return 0; return 0;
@ -619,9 +619,7 @@ flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
{ {
unsigned long mask1 = cpumask_bits(cpumask)[0]; unsigned long mask1 = cpumask_bits(cpumask)[0];
unsigned long mask2 = cpumask_bits(andmask)[0]; unsigned long mask2 = cpumask_bits(andmask)[0];
unsigned long mask3 = cpumask_bits(cpu_online_mask)[0]; return __flat_cpu_mask_to_apicid(mask1 & mask2, apicid);
return __flat_cpu_mask_to_apicid(mask1 & mask2 & mask3, apicid);
} }
extern int extern int

Просмотреть файл

@ -2136,7 +2136,7 @@ static inline int __default_cpu_to_apicid(int cpu, unsigned int *apicid)
int default_cpu_mask_to_apicid(const struct cpumask *cpumask, int default_cpu_mask_to_apicid(const struct cpumask *cpumask,
unsigned int *apicid) unsigned int *apicid)
{ {
int cpu = cpumask_first(cpumask); int cpu = cpumask_first_and(cpumask, cpu_online_mask);
return __default_cpu_to_apicid(cpu, apicid); return __default_cpu_to_apicid(cpu, apicid);
} }

Просмотреть файл

@ -534,7 +534,7 @@ es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
/* /*
* The cpus in the mask must all be on the apic cluster. * The cpus in the mask must all be on the apic cluster.
*/ */
for_each_cpu(cpu, cpumask) { for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
@ -561,7 +561,6 @@ es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
return 0; return 0;
cpumask_and(cpumask, inmask, andmask); cpumask_and(cpumask, inmask, andmask);
cpumask_and(cpumask, cpumask, cpu_online_mask);
es7000_cpu_mask_to_apicid(cpumask, apicid); es7000_cpu_mask_to_apicid(cpumask, apicid);
free_cpumask_var(cpumask); free_cpumask_var(cpumask);

Просмотреть файл

@ -272,7 +272,7 @@ summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
/* /*
* The cpus in the mask must all be on the apic cluster. * The cpus in the mask must all be on the apic cluster.
*/ */
for_each_cpu(cpu, cpumask) { for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
@ -298,7 +298,6 @@ summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
return 0; return 0;
cpumask_and(cpumask, inmask, andmask); cpumask_and(cpumask, inmask, andmask);
cpumask_and(cpumask, cpumask, cpu_online_mask);
summit_cpu_mask_to_apicid(cpumask, apicid); summit_cpu_mask_to_apicid(cpumask, apicid);
free_cpumask_var(cpumask); free_cpumask_var(cpumask);

Просмотреть файл

@ -99,7 +99,7 @@ static void x2apic_send_IPI_all(int vector)
static int static int
x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid) x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid)
{ {
int cpu = cpumask_first(cpumask); int cpu = cpumask_first_and(cpumask, cpu_online_mask);
int i; int i;
if (cpu >= nr_cpu_ids) if (cpu >= nr_cpu_ids)

Просмотреть файл

@ -286,7 +286,7 @@ uv_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *apicid)
* We're using fixed IRQ delivery, can only return one phys APIC ID. * We're using fixed IRQ delivery, can only return one phys APIC ID.
* May as well be the first. * May as well be the first.
*/ */
int cpu = cpumask_first(cpumask); int cpu = cpumask_first_and(cpumask, cpu_online_mask);
return __uv_cpu_to_apicid(cpu, apicid); return __uv_cpu_to_apicid(cpu, apicid);
} }