diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/smpboot.c | 97 |
1 files changed, 50 insertions, 47 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index c5517f332309..09b4ceb832b2 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -66,11 +66,21 @@ int smp_num_siblings = 1; | |||
66 | #ifdef CONFIG_X86_HT | 66 | #ifdef CONFIG_X86_HT |
67 | EXPORT_SYMBOL(smp_num_siblings); | 67 | EXPORT_SYMBOL(smp_num_siblings); |
68 | #endif | 68 | #endif |
69 | int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ | 69 | |
70 | /* Package ID of each logical CPU */ | ||
71 | int phys_proc_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID}; | ||
70 | EXPORT_SYMBOL(phys_proc_id); | 72 | EXPORT_SYMBOL(phys_proc_id); |
71 | int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */ | 73 | |
74 | /* Core ID of each logical CPU */ | ||
75 | int cpu_core_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID}; | ||
72 | EXPORT_SYMBOL(cpu_core_id); | 76 | EXPORT_SYMBOL(cpu_core_id); |
73 | 77 | ||
78 | cpumask_t cpu_sibling_map[NR_CPUS]; | ||
79 | EXPORT_SYMBOL(cpu_sibling_map); | ||
80 | |||
81 | cpumask_t cpu_core_map[NR_CPUS]; | ||
82 | EXPORT_SYMBOL(cpu_core_map); | ||
83 | |||
74 | /* bitmap of online cpus */ | 84 | /* bitmap of online cpus */ |
75 | cpumask_t cpu_online_map; | 85 | cpumask_t cpu_online_map; |
76 | EXPORT_SYMBOL(cpu_online_map); | 86 | EXPORT_SYMBOL(cpu_online_map); |
@@ -423,6 +433,38 @@ static void __init smp_callin(void) | |||
423 | 433 | ||
424 | static int cpucount; | 434 | static int cpucount; |
425 | 435 | ||
436 | static inline void | ||
437 | set_cpu_sibling_map(int cpu) | ||
438 | { | ||
439 | int i; | ||
440 | |||
441 | if (smp_num_siblings > 1) { | ||
442 | for (i = 0; i < NR_CPUS; i++) { | ||
443 | if (!cpu_isset(i, cpu_callout_map)) | ||
444 | continue; | ||
445 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | ||
446 | cpu_set(i, cpu_sibling_map[cpu]); | ||
447 | cpu_set(cpu, cpu_sibling_map[i]); | ||
448 | } | ||
449 | } | ||
450 | } else { | ||
451 | cpu_set(cpu, cpu_sibling_map[cpu]); | ||
452 | } | ||
453 | |||
454 | if (current_cpu_data.x86_num_cores > 1) { | ||
455 | for (i = 0; i < NR_CPUS; i++) { | ||
456 | if (!cpu_isset(i, cpu_callout_map)) | ||
457 | continue; | ||
458 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
459 | cpu_set(i, cpu_core_map[cpu]); | ||
460 | cpu_set(cpu, cpu_core_map[i]); | ||
461 | } | ||
462 | } | ||
463 | } else { | ||
464 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | ||
465 | } | ||
466 | } | ||
467 | |||
426 | /* | 468 | /* |
427 | * Activate a secondary processor. | 469 | * Activate a secondary processor. |
428 | */ | 470 | */ |
@@ -450,6 +492,10 @@ static void __init start_secondary(void *unused) | |||
450 | */ | 492 | */ |
451 | local_flush_tlb(); | 493 | local_flush_tlb(); |
452 | 494 | ||
495 | /* This must be done before setting cpu_online_map */ | ||
496 | set_cpu_sibling_map(raw_smp_processor_id()); | ||
497 | wmb(); | ||
498 | |||
453 | /* | 499 | /* |
454 | * We need to hold call_lock, so there is no inconsistency | 500 | * We need to hold call_lock, so there is no inconsistency |
455 | * between the time smp_call_function() determines number of | 501 | * between the time smp_call_function() determines number of |
@@ -912,13 +958,6 @@ void *xquad_portio; | |||
912 | EXPORT_SYMBOL(xquad_portio); | 958 | EXPORT_SYMBOL(xquad_portio); |
913 | #endif | 959 | #endif |
914 | 960 | ||
915 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; | ||
916 | #ifdef CONFIG_X86_HT | ||
917 | EXPORT_SYMBOL(cpu_sibling_map); | ||
918 | #endif | ||
919 | cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; | ||
920 | EXPORT_SYMBOL(cpu_core_map); | ||
921 | |||
922 | static void __init smp_boot_cpus(unsigned int max_cpus) | 961 | static void __init smp_boot_cpus(unsigned int max_cpus) |
923 | { | 962 | { |
924 | int apicid, cpu, bit, kicked; | 963 | int apicid, cpu, bit, kicked; |
@@ -1082,44 +1121,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1082 | cpus_clear(cpu_core_map[cpu]); | 1121 | cpus_clear(cpu_core_map[cpu]); |
1083 | } | 1122 | } |
1084 | 1123 | ||
1085 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 1124 | cpu_set(0, cpu_sibling_map[0]); |
1086 | struct cpuinfo_x86 *c = cpu_data + cpu; | 1125 | cpu_set(0, cpu_core_map[0]); |
1087 | int siblings = 0; | ||
1088 | int i; | ||
1089 | if (!cpu_isset(cpu, cpu_callout_map)) | ||
1090 | continue; | ||
1091 | |||
1092 | if (smp_num_siblings > 1) { | ||
1093 | for (i = 0; i < NR_CPUS; i++) { | ||
1094 | if (!cpu_isset(i, cpu_callout_map)) | ||
1095 | continue; | ||
1096 | if (cpu_core_id[cpu] == cpu_core_id[i]) { | ||
1097 | siblings++; | ||
1098 | cpu_set(i, cpu_sibling_map[cpu]); | ||
1099 | } | ||
1100 | } | ||
1101 | } else { | ||
1102 | siblings++; | ||
1103 | cpu_set(cpu, cpu_sibling_map[cpu]); | ||
1104 | } | ||
1105 | |||
1106 | if (siblings != smp_num_siblings) { | ||
1107 | printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); | ||
1108 | smp_num_siblings = siblings; | ||
1109 | } | ||
1110 | |||
1111 | if (c->x86_num_cores > 1) { | ||
1112 | for (i = 0; i < NR_CPUS; i++) { | ||
1113 | if (!cpu_isset(i, cpu_callout_map)) | ||
1114 | continue; | ||
1115 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
1116 | cpu_set(i, cpu_core_map[cpu]); | ||
1117 | } | ||
1118 | } | ||
1119 | } else { | ||
1120 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | ||
1121 | } | ||
1122 | } | ||
1123 | 1126 | ||
1124 | smpboot_setup_io_apic(); | 1127 | smpboot_setup_io_apic(); |
1125 | 1128 | ||