diff options
| -rw-r--r-- | arch/x86/kernel/cpu/addon_cpuid_features.c | 86 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/common_64.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/intel.c | 13 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/intel_64.c | 5 | ||||
| -rw-r--r-- | include/asm-x86/cpufeature.h | 1 | ||||
| -rw-r--r-- | include/asm-x86/processor.h | 1 |
6 files changed, 105 insertions, 4 deletions
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 84a8220a6072..aa9641ae6703 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | #include <asm/pat.h> | 7 | #include <asm/pat.h> |
| 8 | #include <asm/processor.h> | 8 | #include <asm/processor.h> |
| 9 | 9 | ||
| 10 | #include <mach_apic.h> | ||
| 11 | |||
| 10 | struct cpuid_bit { | 12 | struct cpuid_bit { |
| 11 | u16 feature; | 13 | u16 feature; |
| 12 | u8 reg; | 14 | u8 reg; |
| @@ -48,6 +50,90 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
| 48 | } | 50 | } |
| 49 | } | 51 | } |
| 50 | 52 | ||
| 53 | /* leaf 0xb SMT level */ | ||
| 54 | #define SMT_LEVEL 0 | ||
| 55 | |||
| 56 | /* leaf 0xb sub-leaf types */ | ||
| 57 | #define INVALID_TYPE 0 | ||
| 58 | #define SMT_TYPE 1 | ||
| 59 | #define CORE_TYPE 2 | ||
| 60 | |||
| 61 | #define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff) | ||
| 62 | #define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f) | ||
| 63 | #define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff) | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Check for extended topology enumeration cpuid leaf 0xb and if it | ||
| 67 | * exists, use it for populating initial_apicid and cpu topology | ||
| 68 | * detection. | ||
| 69 | */ | ||
| 70 | void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) | ||
| 71 | { | ||
| 72 | unsigned int eax, ebx, ecx, edx, sub_index; | ||
| 73 | unsigned int ht_mask_width, core_plus_mask_width; | ||
| 74 | unsigned int core_select_mask, core_level_siblings; | ||
| 75 | |||
| 76 | if (c->cpuid_level < 0xb) | ||
| 77 | return; | ||
| 78 | |||
| 79 | cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); | ||
| 80 | |||
| 81 | /* | ||
| 82 | * check if the cpuid leaf 0xb is actually implemented. | ||
| 83 | */ | ||
| 84 | if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) | ||
| 85 | return; | ||
| 86 | |||
| 87 | set_cpu_cap(c, X86_FEATURE_XTOPOLOGY); | ||
| 88 | |||
| 89 | /* | ||
| 90 | * initial apic id, which also represents 32-bit extended x2apic id. | ||
| 91 | */ | ||
| 92 | c->initial_apicid = edx; | ||
| 93 | |||
| 94 | /* | ||
| 95 | * Populate HT related information from sub-leaf level 0. | ||
| 96 | */ | ||
| 97 | core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); | ||
| 98 | core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); | ||
| 99 | |||
| 100 | sub_index = 1; | ||
| 101 | do { | ||
| 102 | cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx); | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Check for the Core type in the implemented sub leaves. | ||
| 106 | */ | ||
| 107 | if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) { | ||
| 108 | core_level_siblings = LEVEL_MAX_SIBLINGS(ebx); | ||
| 109 | core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | |||
| 113 | sub_index++; | ||
| 114 | } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE); | ||
| 115 | |||
| 116 | core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; | ||
| 117 | |||
| 118 | #ifdef CONFIG_X86_32 | ||
| 119 | c->cpu_core_id = phys_pkg_id(c->initial_apicid, ht_mask_width) | ||
| 120 | & core_select_mask; | ||
| 121 | c->phys_proc_id = phys_pkg_id(c->initial_apicid, core_plus_mask_width); | ||
| 122 | #else | ||
| 123 | c->cpu_core_id = phys_pkg_id(ht_mask_width) & core_select_mask; | ||
| 124 | c->phys_proc_id = phys_pkg_id(core_plus_mask_width); | ||
| 125 | #endif | ||
| 126 | c->x86_max_cores = (core_level_siblings / smp_num_siblings); | ||
| 127 | |||
| 128 | |||
| 129 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | ||
| 130 | c->phys_proc_id); | ||
| 131 | if (c->x86_max_cores > 1) | ||
| 132 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | ||
| 133 | c->cpu_core_id); | ||
| 134 | return; | ||
| 135 | } | ||
| 136 | |||
| 51 | #ifdef CONFIG_X86_PAT | 137 | #ifdef CONFIG_X86_PAT |
| 52 | void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) | 138 | void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) |
| 53 | { | 139 | { |
diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index af569a964e74..a2888c7b56ac 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c | |||
| @@ -128,6 +128,9 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) | |||
| 128 | u32 eax, ebx, ecx, edx; | 128 | u32 eax, ebx, ecx, edx; |
| 129 | int index_msb, core_bits; | 129 | int index_msb, core_bits; |
| 130 | 130 | ||
| 131 | if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) | ||
| 132 | return; | ||
| 133 | |||
| 131 | cpuid(1, &eax, &ebx, &ecx, &edx); | 134 | cpuid(1, &eax, &ebx, &ecx, &edx); |
| 132 | 135 | ||
| 133 | 136 | ||
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 77618c717d76..58a6f1a0b297 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
| @@ -176,9 +176,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
| 176 | if (p) | 176 | if (p) |
| 177 | strcpy(c->x86_model_id, p); | 177 | strcpy(c->x86_model_id, p); |
| 178 | 178 | ||
| 179 | c->x86_max_cores = num_cpu_cores(c); | 179 | detect_extended_topology(c); |
| 180 | 180 | ||
| 181 | detect_ht(c); | 181 | if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) { |
| 182 | /* | ||
| 183 | * let's use the legacy cpuid vector 0x1 and 0x4 for topology | ||
| 184 | * detection. | ||
| 185 | */ | ||
| 186 | c->x86_max_cores = num_cpu_cores(c); | ||
| 187 | detect_ht(c); | ||
| 188 | } | ||
| 182 | 189 | ||
| 183 | /* Work around errata */ | 190 | /* Work around errata */ |
| 184 | Intel_errata_workarounds(c); | 191 | Intel_errata_workarounds(c); |
diff --git a/arch/x86/kernel/cpu/intel_64.c b/arch/x86/kernel/cpu/intel_64.c index 1019c58d39f0..42d501a8c418 100644 --- a/arch/x86/kernel/cpu/intel_64.c +++ b/arch/x86/kernel/cpu/intel_64.c | |||
| @@ -80,7 +80,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
| 80 | if (c->x86 == 6) | 80 | if (c->x86 == 6) |
| 81 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); | 81 | set_cpu_cap(c, X86_FEATURE_REP_GOOD); |
| 82 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | 82 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); |
| 83 | c->x86_max_cores = intel_num_cpu_cores(c); | 83 | |
| 84 | detect_extended_topology(c); | ||
| 85 | if (!cpu_has(c, X86_FEATURE_XTOPOLOGY)) | ||
| 86 | c->x86_max_cores = intel_num_cpu_cores(c); | ||
| 84 | 87 | ||
| 85 | srat_detect_node(); | 88 | srat_detect_node(); |
| 86 | } | 89 | } |
diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 5fc4d55906d4..8d842af4cf7a 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h | |||
| @@ -81,6 +81,7 @@ | |||
| 81 | #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ | 81 | #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ |
| 82 | #define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ | 82 | #define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ |
| 83 | #define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ | 83 | #define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ |
| 84 | #define X86_FEATURE_XTOPOLOGY (3*32+21) /* cpu topology enum extensions */ | ||
| 84 | 85 | ||
| 85 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ | 86 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ |
| 86 | #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ | 87 | #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ |
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 5f58da401b43..79338fe965d2 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h | |||
| @@ -161,6 +161,7 @@ extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c); | |||
| 161 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); | 161 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); |
| 162 | extern unsigned short num_cache_leaves; | 162 | extern unsigned short num_cache_leaves; |
| 163 | 163 | ||
| 164 | extern void detect_extended_topology(struct cpuinfo_x86 *c); | ||
| 164 | #if defined(CONFIG_X86_HT) || defined(CONFIG_X86_64) | 165 | #if defined(CONFIG_X86_HT) || defined(CONFIG_X86_64) |
| 165 | extern void detect_ht(struct cpuinfo_x86 *c); | 166 | extern void detect_ht(struct cpuinfo_x86 *c); |
| 166 | #else | 167 | #else |
