Commit 8237eb94 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

* 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86, microcode, AMD: Add microcode revision to /proc/cpuinfo
  x86, microcode: Correct microcode revision format
  coretemp: Get microcode revision from cpu_data
  x86, intel: Use c->microcode for Atom errata check
  x86, intel: Output microcode revision in /proc/cpuinfo
  x86, microcode: Don't request microcode from userspace unnecessarily

Fix up trivial conflicts in arch/x86/kernel/cpu/amd.c (conflict between
moving AMD BSP code to cpu_dev helper function and adding AMD microcode
revision to /proc/cpuinfo code)
parents cc21fe51 bcb80e53
...@@ -111,6 +111,7 @@ struct cpuinfo_x86 { ...@@ -111,6 +111,7 @@ struct cpuinfo_x86 {
/* Index into per_cpu list: */ /* Index into per_cpu list: */
u16 cpu_index; u16 cpu_index;
#endif #endif
u32 microcode;
} __attribute__((__aligned__(SMP_CACHE_BYTES))); } __attribute__((__aligned__(SMP_CACHE_BYTES)));
#define X86_VENDOR_INTEL 0 #define X86_VENDOR_INTEL 0
...@@ -179,7 +180,8 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, ...@@ -179,7 +180,8 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
"=b" (*ebx), "=b" (*ebx),
"=c" (*ecx), "=c" (*ecx),
"=d" (*edx) "=d" (*edx)
: "0" (*eax), "2" (*ecx)); : "0" (*eax), "2" (*ecx)
: "memory");
} }
static inline void load_cr3(pgd_t *pgdir) static inline void load_cr3(pgd_t *pgdir)
......
...@@ -441,6 +441,8 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) ...@@ -441,6 +441,8 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c)
static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
{ {
u32 dummy;
early_init_amd_mc(c); early_init_amd_mc(c);
/* /*
...@@ -470,6 +472,8 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) ...@@ -470,6 +472,8 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_EXTD_APICID); set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
} }
#endif #endif
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
} }
static void __cpuinit init_amd(struct cpuinfo_x86 *c) static void __cpuinit init_amd(struct cpuinfo_x86 *c)
......
...@@ -47,6 +47,15 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) ...@@ -47,6 +47,15 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
(c->x86 == 0x6 && c->x86_model >= 0x0e)) (c->x86 == 0x6 && c->x86_model >= 0x0e))
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
unsigned lower_word;
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* Required by the SDM */
sync_core();
rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
}
/* /*
* Atom erratum AAE44/AAF40/AAG38/AAH41: * Atom erratum AAE44/AAF40/AAG38/AAH41:
* *
...@@ -55,17 +64,10 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) ...@@ -55,17 +64,10 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
* need the microcode to have already been loaded... so if it is * need the microcode to have already been loaded... so if it is
* not, recommend a BIOS update and disable large pages. * not, recommend a BIOS update and disable large pages.
*/ */
if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) { if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 &&
u32 ucode, junk; c->microcode < 0x20e) {
printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
wrmsr(MSR_IA32_UCODE_REV, 0, 0); clear_cpu_cap(c, X86_FEATURE_PSE);
sync_core();
rdmsr(MSR_IA32_UCODE_REV, junk, ucode);
if (ucode < 0x20e) {
printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
clear_cpu_cap(c, X86_FEATURE_PSE);
}
} }
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
......
...@@ -217,8 +217,13 @@ static void print_mce(struct mce *m) ...@@ -217,8 +217,13 @@ static void print_mce(struct mce *m)
pr_cont("MISC %llx ", m->misc); pr_cont("MISC %llx ", m->misc);
pr_cont("\n"); pr_cont("\n");
pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n", /*
m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid); * Note this output is parsed by external tools and old fields
* should not be changed.
*/
pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x microcode %x\n",
m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid,
cpu_data(m->extcpu).microcode);
/* /*
* Print out human-readable details about the MCE error, * Print out human-readable details about the MCE error,
......
...@@ -85,6 +85,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -85,6 +85,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "stepping\t: %d\n", c->x86_mask); seq_printf(m, "stepping\t: %d\n", c->x86_mask);
else else
seq_printf(m, "stepping\t: unknown\n"); seq_printf(m, "stepping\t: unknown\n");
if (c->microcode)
seq_printf(m, "microcode\t: 0x%x\n", c->microcode);
if (cpu_has(c, X86_FEATURE_TSC)) { if (cpu_has(c, X86_FEATURE_TSC)) {
unsigned int freq = cpufreq_quick_get(cpu); unsigned int freq = cpufreq_quick_get(cpu);
......
...@@ -74,14 +74,13 @@ static struct equiv_cpu_entry *equiv_cpu_table; ...@@ -74,14 +74,13 @@ static struct equiv_cpu_entry *equiv_cpu_table;
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
{ {
struct cpuinfo_x86 *c = &cpu_data(cpu); struct cpuinfo_x86 *c = &cpu_data(cpu);
u32 dummy;
if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
return -1; return -1;
} }
rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy); csig->rev = c->microcode;
pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
return 0; return 0;
...@@ -130,6 +129,7 @@ static int apply_microcode_amd(int cpu) ...@@ -130,6 +129,7 @@ static int apply_microcode_amd(int cpu)
int cpu_num = raw_smp_processor_id(); int cpu_num = raw_smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
struct microcode_amd *mc_amd = uci->mc; struct microcode_amd *mc_amd = uci->mc;
struct cpuinfo_x86 *c = &cpu_data(cpu);
/* We should bind the task to the CPU */ /* We should bind the task to the CPU */
BUG_ON(cpu_num != cpu); BUG_ON(cpu_num != cpu);
...@@ -150,6 +150,7 @@ static int apply_microcode_amd(int cpu) ...@@ -150,6 +150,7 @@ static int apply_microcode_amd(int cpu)
pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev); pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
uci->cpu_sig.rev = rev; uci->cpu_sig.rev = rev;
c->microcode = rev;
return 0; return 0;
} }
......
...@@ -483,7 +483,13 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) ...@@ -483,7 +483,13 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
pr_debug("CPU%d removed\n", cpu); pr_debug("CPU%d removed\n", cpu);
break; break;
case CPU_DEAD:
/*
* When a CPU goes offline, don't free up or invalidate the copy of
* the microcode in kernel memory, so that we can reuse it when the
* CPU comes back online without unnecessarily requesting the userspace
* for it again.
*/
case CPU_UP_CANCELED_FROZEN: case CPU_UP_CANCELED_FROZEN:
/* The CPU refused to come up during a system resume */ /* The CPU refused to come up during a system resume */
microcode_fini_cpu(cpu); microcode_fini_cpu(cpu);
......
...@@ -161,12 +161,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) ...@@ -161,12 +161,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
csig->pf = 1 << ((val[1] >> 18) & 7); csig->pf = 1 << ((val[1] >> 18) & 7);
} }
wrmsr(MSR_IA32_UCODE_REV, 0, 0); csig->rev = c->microcode;
/* see notes above for revision 1.07. Apparent chip bug */
sync_core();
/* get the current revision from MSR 0x8B */
rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n",
cpu_num, csig->sig, csig->pf, csig->rev); cpu_num, csig->sig, csig->pf, csig->rev);
...@@ -299,9 +294,9 @@ static int apply_microcode(int cpu) ...@@ -299,9 +294,9 @@ static int apply_microcode(int cpu)
struct microcode_intel *mc_intel; struct microcode_intel *mc_intel;
struct ucode_cpu_info *uci; struct ucode_cpu_info *uci;
unsigned int val[2]; unsigned int val[2];
int cpu_num; int cpu_num = raw_smp_processor_id();
struct cpuinfo_x86 *c = &cpu_data(cpu_num);
cpu_num = raw_smp_processor_id();
uci = ucode_cpu_info + cpu; uci = ucode_cpu_info + cpu;
mc_intel = uci->mc; mc_intel = uci->mc;
...@@ -317,7 +312,7 @@ static int apply_microcode(int cpu) ...@@ -317,7 +312,7 @@ static int apply_microcode(int cpu)
(unsigned long) mc_intel->bits >> 16 >> 16); (unsigned long) mc_intel->bits >> 16 >> 16);
wrmsr(MSR_IA32_UCODE_REV, 0, 0); wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* see notes above for revision 1.07. Apparent chip bug */ /* As documented in the SDM: Do a CPUID 1 here */
sync_core(); sync_core();
/* get the current revision from MSR 0x8B */ /* get the current revision from MSR 0x8B */
...@@ -335,6 +330,7 @@ static int apply_microcode(int cpu) ...@@ -335,6 +330,7 @@ static int apply_microcode(int cpu)
(mc_intel->hdr.date >> 16) & 0xff); (mc_intel->hdr.date >> 16) & 0xff);
uci->cpu_sig.rev = val[1]; uci->cpu_sig.rev = val[1];
c->microcode = val[1];
return 0; return 0;
} }
......
...@@ -325,15 +325,6 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) ...@@ -325,15 +325,6 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
return adjust_tjmax(c, id, dev); return adjust_tjmax(c, id, dev);
} }
static void __devinit get_ucode_rev_on_cpu(void *edx)
{
u32 eax;
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
sync_core();
rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
}
static int create_name_attr(struct platform_data *pdata, struct device *dev) static int create_name_attr(struct platform_data *pdata, struct device *dev)
{ {
sysfs_attr_init(&pdata->name_attr.attr); sysfs_attr_init(&pdata->name_attr.attr);
...@@ -380,27 +371,16 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, ...@@ -380,27 +371,16 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
static int __cpuinit chk_ucode_version(unsigned int cpu) static int __cpuinit chk_ucode_version(unsigned int cpu)
{ {
struct cpuinfo_x86 *c = &cpu_data(cpu); struct cpuinfo_x86 *c = &cpu_data(cpu);
int err;
u32 edx;
/* /*
* Check if we have problem with errata AE18 of Core processors: * Check if we have problem with errata AE18 of Core processors:
* Readings might stop update when processor visited too deep sleep, * Readings might stop update when processor visited too deep sleep,
* fixed for stepping D0 (6EC). * fixed for stepping D0 (6EC).
*/ */
if (c->x86_model == 0xe && c->x86_mask < 0xc) { if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
/* check for microcode update */ pr_err("Errata AE18 not fixed, update BIOS or "
err = smp_call_function_single(cpu, get_ucode_rev_on_cpu, "microcode of the CPU!\n");
&edx, 1); return -ENODEV;
if (err) {
pr_err("Cannot determine microcode revision of "
"CPU#%u (%d)!\n", cpu, err);
return -ENODEV;
} else if (edx < 0x39) {
pr_err("Errata AE18 not fixed, update BIOS or "
"microcode of the CPU!\n");
return -ENODEV;
}
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment