Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86, intel: Output microcode revision in /proc/cpuinfo

I got a request to make it easier to determine the microcode
update level on Intel CPUs. This patch adds a new "microcode"
field to /proc/cpuinfo.

The microcode level is also outputed on fatal machine checks
together with the other CPUID model information.

I removed the respective code from the microcode update driver,
it just reads the field from cpu_data. Also when the microcode
is updated it fills in the new values too.

I had to add a memory barrier to native_cpuid to prevent it
being optimized away when the result is not used.

This turns out to clean up further code which already got this
information manually. This is done in followon patches.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Link: http://lkml.kernel.org/r/1318466795-7393-1-git-send-email-andi@firstfloor.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Andi Kleen and committed by
Ingo Molnar
506ed6b5 70989449

+26 -12
+3 -1
arch/x86/include/asm/processor.h
··· 111 111 /* Index into per_cpu list: */ 112 112 u16 cpu_index; 113 113 #endif 114 + u32 microcode; 114 115 } __attribute__((__aligned__(SMP_CACHE_BYTES))); 115 116 116 117 #define X86_VENDOR_INTEL 0 ··· 180 179 "=b" (*ebx), 181 180 "=c" (*ecx), 182 181 "=d" (*edx) 183 - : "0" (*eax), "2" (*ecx)); 182 + : "0" (*eax), "2" (*ecx) 183 + : "memory"); 184 184 } 185 185 186 186 static inline void load_cr3(pgd_t *pgdir)
+9
arch/x86/kernel/cpu/intel.c
··· 47 47 (c->x86 == 0x6 && c->x86_model >= 0x0e)) 48 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 60 * Atom erratum AAE44/AAF40/AAG38/AAH41: 52 61 *
+7 -2
arch/x86/kernel/cpu/mcheck/mce.c
··· 217 217 pr_cont("MISC %llx ", m->misc); 218 218 219 219 pr_cont("\n"); 220 - pr_emerg(HW_ERR "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n", 221 - m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid); 220 + /* 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 %u\n", 225 + m->cpuvendor, m->cpuid, m->time, m->socketid, m->apicid, 226 + cpu_data(m->extcpu).microcode); 222 227 223 228 /* 224 229 * Print out human-readable details about the MCE error,
+2
arch/x86/kernel/cpu/proc.c
··· 85 85 seq_printf(m, "stepping\t: %d\n", c->x86_mask); 86 86 else 87 87 seq_printf(m, "stepping\t: unknown\n"); 88 + if (c->microcode) 89 + seq_printf(m, "microcode\t: %u\n", c->microcode); 88 90 89 91 if (cpu_has(c, X86_FEATURE_TSC)) { 90 92 unsigned int freq = cpufreq_quick_get(cpu);
+5 -9
arch/x86/kernel/microcode_intel.c
··· 161 161 csig->pf = 1 << ((val[1] >> 18) & 7); 162 162 } 163 163 164 - wrmsr(MSR_IA32_UCODE_REV, 0, 0); 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 - 164 + csig->rev = c->microcode; 170 165 pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", 171 166 cpu_num, csig->sig, csig->pf, csig->rev); 172 167 ··· 294 299 struct microcode_intel *mc_intel; 295 300 struct ucode_cpu_info *uci; 296 301 unsigned int val[2]; 297 - int cpu_num; 302 + int cpu_num = raw_smp_processor_id(); 303 + struct cpuinfo_x86 *c = &cpu_data(cpu_num); 298 304 299 - cpu_num = raw_smp_processor_id(); 300 305 uci = ucode_cpu_info + cpu; 301 306 mc_intel = uci->mc; 302 307 ··· 312 317 (unsigned long) mc_intel->bits >> 16 >> 16); 313 318 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 314 319 315 - /* see notes above for revision 1.07. Apparent chip bug */ 320 + /* As documented in the SDM: Do a CPUID 1 here */ 316 321 sync_core(); 317 322 318 323 /* get the current revision from MSR 0x8B */ ··· 330 335 (mc_intel->hdr.date >> 16) & 0xff); 331 336 332 337 uci->cpu_sig.rev = val[1]; 338 + c->microcode = val[1]; 333 339 334 340 return 0; 335 341 }