diff options
author | Mike Travis <travis@sgi.com> | 2008-12-17 18:21:39 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-18 05:59:24 -0500 |
commit | a775a38b1353161a6d7af86b667d6523c12c1a37 (patch) | |
tree | 3bb16b2345b1090bacbd06c64ca62298a5fc23d6 /arch/x86/include/asm/summit | |
parent | 9a3d8f735eee90bb5b1351983e946bc637041c01 (diff) |
x86: fix cpu_mask_to_apicid_and to include cpu_online_mask
Impact: fix potential APIC crash
In determining the destination apicid, there are usually three cpumasks
that are considered: the incoming cpumask arg, cfg->domain and the
cpu_online_mask. Since we are just introducing the cpu_mask_to_apicid_and
function, make sure it includes the cpu_online_mask in it's evaluation.
[Added with this patch.]
There are two io_apic.c functions that did not previously use the
cpu_online_mask: setup_IO_APIC_irq and msi_compose_msg. Both of these
simply used cpu_mask_to_apicid(cfg->domain & TARGET_CPUS), and all but
one arch (NUMAQ[*]) returns only online cpus in the TARGET_CPUS mask,
so the behavior is identical for all cases.
[*: NUMAQ bug?]
Note that alloc_cpumask_var is only used for the 32-bit cases where
it's highly likely that the cpumask set size will be small and therefore
CPUMASK_OFFSTACK=n. But if that's not the case, failing the allocate
will cause the same return value as the default.
Signed-off-by: Mike Travis <travis@sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/include/asm/summit')
-rw-r--r-- | arch/x86/include/asm/summit/apic.h | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h index 651a93849341..99327d1be49f 100644 --- a/arch/x86/include/asm/summit/apic.h +++ b/arch/x86/include/asm/summit/apic.h | |||
@@ -170,35 +170,37 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) | |||
170 | return apicid; | 170 | return apicid; |
171 | } | 171 | } |
172 | 172 | ||
173 | static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 173 | static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, |
174 | const struct cpumask *andmask) | 174 | const struct cpumask *andmask) |
175 | { | 175 | { |
176 | int num_bits_set; | 176 | int num_bits_set; |
177 | int num_bits_set2; | ||
178 | int cpus_found = 0; | 177 | int cpus_found = 0; |
179 | int cpu; | 178 | int cpu; |
180 | int apicid = 0; | 179 | int apicid = 0xFF; |
180 | cpumask_var_t cpumask; | ||
181 | |||
182 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) | ||
183 | return (int) 0xFF; | ||
184 | |||
185 | cpumask_and(cpumask, inmask, andmask); | ||
186 | cpumask_and(cpumask, cpumask, cpu_online_mask); | ||
181 | 187 | ||
182 | num_bits_set = cpumask_weight(cpumask); | 188 | num_bits_set = cpumask_weight(cpumask); |
183 | num_bits_set2 = cpumask_weight(andmask); | ||
184 | num_bits_set = min(num_bits_set, num_bits_set2); | ||
185 | /* Return id to all */ | 189 | /* Return id to all */ |
186 | if (num_bits_set >= nr_cpu_ids) | 190 | if (num_bits_set == nr_cpu_ids) |
187 | return 0xFF; | 191 | goto exit; |
188 | /* | 192 | /* |
189 | * The cpus in the mask must all be on the apic cluster. If are not | 193 | * The cpus in the mask must all be on the apic cluster. If are not |
190 | * on the same apicid cluster return default value of TARGET_CPUS. | 194 | * on the same apicid cluster return default value of TARGET_CPUS. |
191 | */ | 195 | */ |
192 | cpu = cpumask_first_and(cpumask, andmask); | 196 | cpu = cpumask_first(cpumask); |
193 | apicid = cpu_to_logical_apicid(cpu); | 197 | apicid = cpu_to_logical_apicid(cpu); |
194 | while (cpus_found < num_bits_set) { | 198 | while (cpus_found < num_bits_set) { |
195 | if (cpumask_test_cpu(cpu, cpumask) | 199 | if (cpumask_test_cpu(cpu, cpumask)) { |
196 | && cpumask_test_cpu(cpu, andmask)) { | ||
197 | int new_apicid = cpu_to_logical_apicid(cpu); | 200 | int new_apicid = cpu_to_logical_apicid(cpu); |
198 | if (apicid_cluster(apicid) != | 201 | if (apicid_cluster(apicid) != |
199 | apicid_cluster(new_apicid)) { | 202 | apicid_cluster(new_apicid)){ |
200 | printk(KERN_WARNING | 203 | printk ("%s: Not a valid mask!\n", __func__); |
201 | "%s: Not a valid mask!\n", __func__); | ||
202 | return 0xFF; | 204 | return 0xFF; |
203 | } | 205 | } |
204 | apicid = apicid | new_apicid; | 206 | apicid = apicid | new_apicid; |
@@ -206,6 +208,8 @@ static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
206 | } | 208 | } |
207 | cpu++; | 209 | cpu++; |
208 | } | 210 | } |
211 | exit: | ||
212 | free_cpumask_var(cpumask); | ||
209 | return apicid; | 213 | return apicid; |
210 | } | 214 | } |
211 | 215 | ||