diff options
| -rw-r--r-- | arch/x86/include/asm/processor.h | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/intel.c | 24 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/proc.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/microcode_amd.c | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/microcode_core.c | 8 | ||||
| -rw-r--r-- | arch/x86/kernel/microcode_intel.c | 14 | ||||
| -rw-r--r-- | drivers/hwmon/coretemp.c | 28 |
9 files changed, 48 insertions, 50 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 0d1171c97729..b650435ffb53 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
| @@ -111,6 +111,7 @@ struct cpuinfo_x86 { | |||
| 111 | /* Index into per_cpu list: */ | 111 | /* Index into per_cpu list: */ |
| 112 | u16 cpu_index; | 112 | u16 cpu_index; |
| 113 | #endif | 113 | #endif |
| 114 | u32 microcode; | ||
| 114 | } __attribute__((__aligned__(SMP_CACHE_BYTES))); | 115 | } __attribute__((__aligned__(SMP_CACHE_BYTES))); |
| 115 | 116 | ||
| 116 | #define X86_VENDOR_INTEL 0 | 117 | #define X86_VENDOR_INTEL 0 |
| @@ -179,7 +180,8 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, | |||
| 179 | "=b" (*ebx), | 180 | "=b" (*ebx), |
| 180 | "=c" (*ecx), | 181 | "=c" (*ecx), |
| 181 | "=d" (*edx) | 182 | "=d" (*edx) |
| 182 | : "0" (*eax), "2" (*ecx)); | 183 | : "0" (*eax), "2" (*ecx) |
| 184 | : "memory"); | ||
| 183 | } | 185 | } |
| 184 | 186 | ||
| 185 | static inline void load_cr3(pgd_t *pgdir) | 187 | static inline void load_cr3(pgd_t *pgdir) |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 13c6ec812545..46ae4f65fc7f 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
| @@ -441,6 +441,8 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) | |||
| 441 | 441 | ||
| 442 | static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) | 442 | static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) |
| 443 | { | 443 | { |
| 444 | u32 dummy; | ||
| 445 | |||
| 444 | early_init_amd_mc(c); | 446 | early_init_amd_mc(c); |
| 445 | 447 | ||
| 446 | /* | 448 | /* |
| @@ -470,6 +472,8 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) | |||
| 470 | set_cpu_cap(c, X86_FEATURE_EXTD_APICID); | 472 | set_cpu_cap(c, X86_FEATURE_EXTD_APICID); |
| 471 | } | 473 | } |
| 472 | #endif | 474 | #endif |
| 475 | |||
| 476 | rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); | ||
| 473 | } | 477 | } |
| 474 | 478 | ||
| 475 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) | 479 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index ed6086eedf1d..523131213f08 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
| @@ -47,6 +47,15 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) | |||
| 47 | (c->x86 == 0x6 && c->x86_model >= 0x0e)) | 47 | (c->x86 == 0x6 && c->x86_model >= 0x0e)) |
| 48 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 48 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
| 49 | 49 | ||
| 50 | if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) { | ||
| 51 | unsigned lower_word; | ||
| 52 | |||
| 53 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 54 | /* Required by the SDM */ | ||
| 55 | sync_core(); | ||
| 56 | rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode); | ||
| 57 | } | ||
| 58 | |||
| 50 | /* | 59 | /* |
| 51 | * Atom erratum AAE44/AAF40/AAG38/AAH41: | 60 | * Atom erratum AAE44/AAF40/AAG38/AAH41: |
| 52 | * | 61 | * |
| @@ -55,17 +64,10 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) | |||
| 55 | * need the microcode to have already been loaded... so if it is | 64 | * need the microcode to have already been loaded... so if it is |
| 56 | * not, recommend a BIOS update and disable large pages. | 65 | * not, recommend a BIOS update and disable large pages. |
| 57 | */ | 66 | */ |
| 58 | if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) { | 67 | if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 && |
| 59 | u32 ucode, junk; | 68 | c->microcode < 0x20e) { |
| 60 | 69 | printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n"); | |
| 61 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 70 | clear_cpu_cap(c, X86_FEATURE_PSE); |
| 62 | sync_core(); | ||
| 63 | rdmsr(MSR_IA32_UCODE_REV, junk, ucode); | ||
| 64 | |||
| 65 | if (ucode < 0x20e) { | ||
| 66 | printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n"); | ||
| 67 | clear_cpu_cap(c, X86_FEATURE_PSE); | ||
| 68 | } | ||
| 69 | } | 71 | } |
| 70 | 72 | ||
| 71 | #ifdef CONFIG_X86_64 | 73 | #ifdef CONFIG_X86_64 |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index fce51ad1f362..7b5063a6ad42 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
| @@ -217,8 +217,13 @@ static void print_mce(struct mce *m) | |||
| 217 | pr_cont("MISC %llx ", m->misc); | 217 | pr_cont("MISC %llx ", m->misc); |
| 218 | 218 | ||
| 219 | pr_cont("\n"); | 219 | pr_cont("\n"); |
| 220 | pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n", | 220 | /* |
| 221 | m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid); | 221 | * Note this output is parsed by external tools and old fields |
| 222 | * should not be changed. | ||
| 223 | */ | ||
| 224 | pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x microcode %x\n", | ||
| 225 | m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid, | ||
| 226 | cpu_data(m->extcpu).microcode); | ||
| 222 | 227 | ||
| 223 | /* | 228 | /* |
| 224 | * Print out human-readable details about the MCE error, | 229 | * Print out human-readable details about the MCE error, |
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 62ac8cb6ba27..14b23140e81f 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c | |||
| @@ -85,6 +85,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 85 | seq_printf(m, "stepping\t: %d\n", c->x86_mask); | 85 | seq_printf(m, "stepping\t: %d\n", c->x86_mask); |
| 86 | else | 86 | else |
| 87 | seq_printf(m, "stepping\t: unknown\n"); | 87 | seq_printf(m, "stepping\t: unknown\n"); |
| 88 | if (c->microcode) | ||
| 89 | seq_printf(m, "microcode\t: 0x%x\n", c->microcode); | ||
| 88 | 90 | ||
| 89 | if (cpu_has(c, X86_FEATURE_TSC)) { | 91 | if (cpu_has(c, X86_FEATURE_TSC)) { |
| 90 | unsigned int freq = cpufreq_quick_get(cpu); | 92 | unsigned int freq = cpufreq_quick_get(cpu); |
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 591be0ee1934..d494799aafcd 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
| @@ -74,14 +74,13 @@ static struct equiv_cpu_entry *equiv_cpu_table; | |||
| 74 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | 74 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) |
| 75 | { | 75 | { |
| 76 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 76 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 77 | u32 dummy; | ||
| 78 | 77 | ||
| 79 | if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { | 78 | if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { |
| 80 | pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); | 79 | pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); |
| 81 | return -1; | 80 | return -1; |
| 82 | } | 81 | } |
| 83 | 82 | ||
| 84 | rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy); | 83 | csig->rev = c->microcode; |
| 85 | pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); | 84 | pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); |
| 86 | 85 | ||
| 87 | return 0; | 86 | return 0; |
| @@ -130,6 +129,7 @@ static int apply_microcode_amd(int cpu) | |||
| 130 | int cpu_num = raw_smp_processor_id(); | 129 | int cpu_num = raw_smp_processor_id(); |
| 131 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | 130 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; |
| 132 | struct microcode_amd *mc_amd = uci->mc; | 131 | struct microcode_amd *mc_amd = uci->mc; |
| 132 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 133 | 133 | ||
| 134 | /* We should bind the task to the CPU */ | 134 | /* We should bind the task to the CPU */ |
| 135 | BUG_ON(cpu_num != cpu); | 135 | BUG_ON(cpu_num != cpu); |
| @@ -150,6 +150,7 @@ static int apply_microcode_amd(int cpu) | |||
| 150 | 150 | ||
| 151 | pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev); | 151 | pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev); |
| 152 | uci->cpu_sig.rev = rev; | 152 | uci->cpu_sig.rev = rev; |
| 153 | c->microcode = rev; | ||
| 153 | 154 | ||
| 154 | return 0; | 155 | return 0; |
| 155 | } | 156 | } |
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index f9242800bc84..f2d2a664e797 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c | |||
| @@ -483,7 +483,13 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | |||
| 483 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | 483 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); |
| 484 | pr_debug("CPU%d removed\n", cpu); | 484 | pr_debug("CPU%d removed\n", cpu); |
| 485 | break; | 485 | break; |
| 486 | case CPU_DEAD: | 486 | |
| 487 | /* | ||
| 488 | * When a CPU goes offline, don't free up or invalidate the copy of | ||
| 489 | * the microcode in kernel memory, so that we can reuse it when the | ||
| 490 | * CPU comes back online without unnecessarily requesting the userspace | ||
| 491 | * for it again. | ||
| 492 | */ | ||
| 487 | case CPU_UP_CANCELED_FROZEN: | 493 | case CPU_UP_CANCELED_FROZEN: |
| 488 | /* The CPU refused to come up during a system resume */ | 494 | /* The CPU refused to come up during a system resume */ |
| 489 | microcode_fini_cpu(cpu); | 495 | microcode_fini_cpu(cpu); |
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 1a1b606d3e92..3ca42d0e43a2 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
| @@ -161,12 +161,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | |||
| 161 | csig->pf = 1 << ((val[1] >> 18) & 7); | 161 | csig->pf = 1 << ((val[1] >> 18) & 7); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 164 | csig->rev = c->microcode; |
| 165 | /* see notes above for revision 1.07. Apparent chip bug */ | ||
| 166 | sync_core(); | ||
| 167 | /* get the current revision from MSR 0x8B */ | ||
| 168 | rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); | ||
| 169 | |||
| 170 | pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", | 165 | pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", |
| 171 | cpu_num, csig->sig, csig->pf, csig->rev); | 166 | cpu_num, csig->sig, csig->pf, csig->rev); |
| 172 | 167 | ||
| @@ -299,9 +294,9 @@ static int apply_microcode(int cpu) | |||
| 299 | struct microcode_intel *mc_intel; | 294 | struct microcode_intel *mc_intel; |
| 300 | struct ucode_cpu_info *uci; | 295 | struct ucode_cpu_info *uci; |
| 301 | unsigned int val[2]; | 296 | unsigned int val[2]; |
| 302 | int cpu_num; | 297 | int cpu_num = raw_smp_processor_id(); |
| 298 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | ||
| 303 | 299 | ||
| 304 | cpu_num = raw_smp_processor_id(); | ||
| 305 | uci = ucode_cpu_info + cpu; | 300 | uci = ucode_cpu_info + cpu; |
| 306 | mc_intel = uci->mc; | 301 | mc_intel = uci->mc; |
| 307 | 302 | ||
| @@ -317,7 +312,7 @@ static int apply_microcode(int cpu) | |||
| 317 | (unsigned long) mc_intel->bits >> 16 >> 16); | 312 | (unsigned long) mc_intel->bits >> 16 >> 16); |
| 318 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 313 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); |
| 319 | 314 | ||
| 320 | /* see notes above for revision 1.07. Apparent chip bug */ | 315 | /* As documented in the SDM: Do a CPUID 1 here */ |
| 321 | sync_core(); | 316 | sync_core(); |
| 322 | 317 | ||
| 323 | /* get the current revision from MSR 0x8B */ | 318 | /* get the current revision from MSR 0x8B */ |
| @@ -335,6 +330,7 @@ static int apply_microcode(int cpu) | |||
| 335 | (mc_intel->hdr.date >> 16) & 0xff); | 330 | (mc_intel->hdr.date >> 16) & 0xff); |
| 336 | 331 | ||
| 337 | uci->cpu_sig.rev = val[1]; | 332 | uci->cpu_sig.rev = val[1]; |
| 333 | c->microcode = val[1]; | ||
| 338 | 334 | ||
| 339 | return 0; | 335 | return 0; |
| 340 | } | 336 | } |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 932383786642..ce18c046f728 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
| @@ -325,15 +325,6 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) | |||
| 325 | return adjust_tjmax(c, id, dev); | 325 | return adjust_tjmax(c, id, dev); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | static void __devinit get_ucode_rev_on_cpu(void *edx) | ||
| 329 | { | ||
| 330 | u32 eax; | ||
| 331 | |||
| 332 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 333 | sync_core(); | ||
| 334 | rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx); | ||
| 335 | } | ||
| 336 | |||
| 337 | static int create_name_attr(struct platform_data *pdata, struct device *dev) | 328 | static int create_name_attr(struct platform_data *pdata, struct device *dev) |
| 338 | { | 329 | { |
| 339 | sysfs_attr_init(&pdata->name_attr.attr); | 330 | sysfs_attr_init(&pdata->name_attr.attr); |
| @@ -380,27 +371,16 @@ exit_free: | |||
| 380 | static int __cpuinit chk_ucode_version(unsigned int cpu) | 371 | static int __cpuinit chk_ucode_version(unsigned int cpu) |
| 381 | { | 372 | { |
| 382 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 373 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 383 | int err; | ||
| 384 | u32 edx; | ||
| 385 | 374 | ||
| 386 | /* | 375 | /* |
| 387 | * Check if we have problem with errata AE18 of Core processors: | 376 | * Check if we have problem with errata AE18 of Core processors: |
| 388 | * Readings might stop update when processor visited too deep sleep, | 377 | * Readings might stop update when processor visited too deep sleep, |
| 389 | * fixed for stepping D0 (6EC). | 378 | * fixed for stepping D0 (6EC). |
| 390 | */ | 379 | */ |
| 391 | if (c->x86_model == 0xe && c->x86_mask < 0xc) { | 380 | if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) { |
| 392 | /* check for microcode update */ | 381 | pr_err("Errata AE18 not fixed, update BIOS or " |
| 393 | err = smp_call_function_single(cpu, get_ucode_rev_on_cpu, | 382 | "microcode of the CPU!\n"); |
| 394 | &edx, 1); | 383 | return -ENODEV; |
| 395 | if (err) { | ||
| 396 | pr_err("Cannot determine microcode revision of " | ||
| 397 | "CPU#%u (%d)!\n", cpu, err); | ||
| 398 | return -ENODEV; | ||
| 399 | } else if (edx < 0x39) { | ||
| 400 | pr_err("Errata AE18 not fixed, update BIOS or " | ||
| 401 | "microcode of the CPU!\n"); | ||
| 402 | return -ENODEV; | ||
| 403 | } | ||
| 404 | } | 384 | } |
| 405 | return 0; | 385 | return 0; |
| 406 | } | 386 | } |
