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/es7000 | |
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/es7000')
-rw-r--r-- | arch/x86/include/asm/es7000/apic.h | 40 |
1 files changed, 18 insertions, 22 deletions
diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index ba8423c5363f..51ac1230294e 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h | |||
@@ -214,51 +214,47 @@ static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask) | |||
214 | return apicid; | 214 | return apicid; |
215 | } | 215 | } |
216 | 216 | ||
217 | static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask, | 217 | |
218 | static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask, | ||
218 | const struct cpumask *andmask) | 219 | const struct cpumask *andmask) |
219 | { | 220 | { |
220 | int num_bits_set; | 221 | int num_bits_set; |
221 | int num_bits_set2; | ||
222 | int cpus_found = 0; | 222 | int cpus_found = 0; |
223 | int cpu; | 223 | int cpu; |
224 | int apicid = 0; | 224 | int apicid = cpu_to_logical_apicid(0); |
225 | cpumask_var_t cpumask; | ||
226 | |||
227 | if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) | ||
228 | return apicid; | ||
229 | |||
230 | cpumask_and(cpumask, inmask, andmask); | ||
231 | cpumask_and(cpumask, cpumask, cpu_online_mask); | ||
225 | 232 | ||
226 | num_bits_set = cpumask_weight(cpumask); | 233 | num_bits_set = cpumask_weight(cpumask); |
227 | num_bits_set2 = cpumask_weight(andmask); | ||
228 | num_bits_set = min(num_bits_set, num_bits_set2); | ||
229 | /* Return id to all */ | 234 | /* Return id to all */ |
230 | if (num_bits_set >= nr_cpu_ids) | 235 | if (num_bits_set == NR_CPUS) |
231 | #if defined CONFIG_ES7000_CLUSTERED_APIC | 236 | goto exit; |
232 | return 0xFF; | ||
233 | #else | ||
234 | return cpu_to_logical_apicid(0); | ||
235 | #endif | ||
236 | /* | 237 | /* |
237 | * The cpus in the mask must all be on the apic cluster. If are not | 238 | * The cpus in the mask must all be on the apic cluster. If are not |
238 | * on the same apicid cluster return default value of TARGET_CPUS. | 239 | * on the same apicid cluster return default value of TARGET_CPUS. |
239 | */ | 240 | */ |
240 | cpu = cpumask_first_and(cpumask, andmask); | 241 | cpu = cpumask_first(cpumask); |
241 | apicid = cpu_to_logical_apicid(cpu); | 242 | apicid = cpu_to_logical_apicid(cpu); |
242 | |||
243 | while (cpus_found < num_bits_set) { | 243 | while (cpus_found < num_bits_set) { |
244 | if (cpumask_test_cpu(cpu, cpumask) && | 244 | if (cpumask_test_cpu(cpu, cpumask)) { |
245 | cpumask_test_cpu(cpu, andmask)) { | ||
246 | int new_apicid = cpu_to_logical_apicid(cpu); | 245 | int new_apicid = cpu_to_logical_apicid(cpu); |
247 | if (apicid_cluster(apicid) != | 246 | if (apicid_cluster(apicid) != |
248 | apicid_cluster(new_apicid)) { | 247 | apicid_cluster(new_apicid)){ |
249 | printk(KERN_WARNING | 248 | printk ("%s: Not a valid mask!\n", __func__); |
250 | "%s: Not a valid mask!\n", __func__); | ||
251 | #if defined CONFIG_ES7000_CLUSTERED_APIC | ||
252 | return 0xFF; | ||
253 | #else | ||
254 | return cpu_to_logical_apicid(0); | 249 | return cpu_to_logical_apicid(0); |
255 | #endif | ||
256 | } | 250 | } |
257 | apicid = new_apicid; | 251 | apicid = new_apicid; |
258 | cpus_found++; | 252 | cpus_found++; |
259 | } | 253 | } |
260 | cpu++; | 254 | cpu++; |
261 | } | 255 | } |
256 | exit: | ||
257 | free_cpumask_var(cpumask); | ||
262 | return apicid; | 258 | return apicid; |
263 | } | 259 | } |
264 | 260 | ||