diff options
Diffstat (limited to 'arch/x86/kernel/cpu/microcode/intel.c')
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 79 | 
1 files changed, 18 insertions, 61 deletions
| diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index b624b54912e1..8325d8a09ab0 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -41,7 +41,7 @@  static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin"; -/* Current microcode patch used in early patching */ +/* Current microcode patch used in early patching on the APs. */  struct microcode_intel *intel_ucode_patch;  static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1, @@ -150,7 +150,7 @@ static struct ucode_patch *__alloc_microcode_buf(void *data, unsigned int size)  {  	struct ucode_patch *p; -	p = kzalloc(size, GFP_KERNEL); +	p = kzalloc(sizeof(struct ucode_patch), GFP_KERNEL);  	if (!p)  		return ERR_PTR(-ENOMEM); @@ -368,26 +368,6 @@ next:  	return patch;  } -static void cpuid_1(void) -{ -	/* -	 * According to the Intel SDM, Volume 3, 9.11.7: -	 * -	 *   CPUID returns a value in a model specific register in -	 *   addition to its usual register return values. The -	 *   semantics of CPUID cause it to deposit an update ID value -	 *   in the 64-bit model-specific register at address 08BH -	 *   (IA32_BIOS_SIGN_ID). If no update is present in the -	 *   processor, the value in the MSR remains unmodified. -	 * -	 * Use native_cpuid -- this code runs very early and we don't -	 * want to mess with paravirt. -	 */ -	unsigned int eax = 1, ebx, ecx = 0, edx; - -	native_cpuid(&eax, &ebx, &ecx, &edx); -} -  static int collect_cpu_info_early(struct ucode_cpu_info *uci)  {  	unsigned int val[2]; @@ -410,15 +390,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)  		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);  		csig.pf = 1 << ((val[1] >> 18) & 7);  	} -	native_wrmsrl(MSR_IA32_UCODE_REV, 0); - -	/* As documented in the SDM: Do a CPUID 1 here */ -	cpuid_1(); - -	/* get the current revision from MSR 0x8B */ -	native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); -	csig.rev = val[1]; +	csig.rev = intel_get_microcode_revision();  	uci->cpu_sig = csig;  	uci->valid = 1; @@ -602,7 +575,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci)  static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)  {  	struct microcode_intel *mc; -	unsigned int val[2]; +	u32 rev;  	mc = uci->mc;  	if (!mc) @@ -610,21 +583,16 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)  	/* write microcode via MSR 0x79 */  	native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); -	native_wrmsrl(MSR_IA32_UCODE_REV, 0); - -	/* As documented in the SDM: Do a CPUID 1 here */ -	cpuid_1(); -	/* get the current revision from MSR 0x8B */ -	native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); -	if (val[1] != mc->hdr.rev) +	rev = intel_get_microcode_revision(); +	if (rev != mc->hdr.rev)  		return -1;  #ifdef CONFIG_X86_64  	/* Flush global tlb. This is precaution. */  	flush_tlb_early();  #endif -	uci->cpu_sig.rev = val[1]; +	uci->cpu_sig.rev = rev;  	if (early)  		print_ucode(uci); @@ -639,12 +607,6 @@ int __init save_microcode_in_initrd_intel(void)  	struct ucode_cpu_info uci;  	struct cpio_data cp; -	/* -	 * AP loading didn't find any microcode patch, no need to save anything. -	 */ -	if (!intel_ucode_patch || IS_ERR(intel_ucode_patch)) -		return 0; -  	if (!load_builtin_intel_microcode(&cp))  		cp = find_microcode_in_initrd(ucode_path, false); @@ -660,7 +622,6 @@ int __init save_microcode_in_initrd_intel(void)  	return 0;  } -  /*   * @res_patch, output: a pointer to the patch we found.   */ @@ -804,8 +765,8 @@ static int apply_microcode_intel(int cpu)  	struct microcode_intel *mc;  	struct ucode_cpu_info *uci;  	struct cpuinfo_x86 *c; -	unsigned int val[2];  	static int prev_rev; +	u32 rev;  	/* We should bind the task to the CPU */  	if (WARN_ON(raw_smp_processor_id() != cpu)) @@ -822,33 +783,28 @@ static int apply_microcode_intel(int cpu)  	/* write microcode via MSR 0x79 */  	wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); -	wrmsrl(MSR_IA32_UCODE_REV, 0); - -	/* As documented in the SDM: Do a CPUID 1 here */ -	cpuid_1(); -	/* get the current revision from MSR 0x8B */ -	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); +	rev = intel_get_microcode_revision(); -	if (val[1] != mc->hdr.rev) { +	if (rev != mc->hdr.rev) {  		pr_err("CPU%d update to revision 0x%x failed\n",  		       cpu, mc->hdr.rev);  		return -1;  	} -	if (val[1] != prev_rev) { +	if (rev != prev_rev) {  		pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n", -			val[1], +			rev,  			mc->hdr.date & 0xffff,  			mc->hdr.date >> 24,  			(mc->hdr.date >> 16) & 0xff); -		prev_rev = val[1]; +		prev_rev = rev;  	}  	c = &cpu_data(cpu); -	uci->cpu_sig.rev = val[1]; -	c->microcode = val[1]; +	uci->cpu_sig.rev = rev; +	c->microcode = rev;  	return 0;  } @@ -860,7 +816,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,  	u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;  	int new_rev = uci->cpu_sig.rev;  	unsigned int leftover = size; -	unsigned int curr_mc_size = 0; +	unsigned int curr_mc_size = 0, new_mc_size = 0;  	unsigned int csig, cpf;  	while (leftover) { @@ -901,6 +857,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,  			vfree(new_mc);  			new_rev = mc_header.rev;  			new_mc  = mc; +			new_mc_size = mc_size;  			mc = NULL;	/* trigger new vmalloc */  		} @@ -926,7 +883,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,  	 * permanent memory. So it will be loaded early when a CPU is hot added  	 * or resumes.  	 */ -	save_mc_for_early(new_mc, curr_mc_size); +	save_mc_for_early(new_mc, new_mc_size);  	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",  		 cpu, new_rev, uci->cpu_sig.rev); |