xref: /openbmc/linux/arch/x86/kernel/cpu/microcode/intel.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
1 /*
2  * Intel CPU Microcode Update Driver for Linux
3  *
4  * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
5  *		 2006 Shaohua Li <shaohua.li@intel.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  */
12 
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 
15 #include <linux/firmware.h>
16 #include <linux/uaccess.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/vmalloc.h>
20 
21 #include <asm/microcode_intel.h>
22 #include <asm/processor.h>
23 #include <asm/msr.h>
24 
25 MODULE_DESCRIPTION("Microcode Update Driver");
26 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
27 MODULE_LICENSE("GPL");
28 
29 static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
30 {
31 	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
32 	unsigned int val[2];
33 
34 	memset(csig, 0, sizeof(*csig));
35 
36 	csig->sig = cpuid_eax(0x00000001);
37 
38 	if ((c->x86_model >= 5) || (c->x86 > 6)) {
39 		/* get processor flags from MSR 0x17 */
40 		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
41 		csig->pf = 1 << ((val[1] >> 18) & 7);
42 	}
43 
44 	csig->rev = c->microcode;
45 	pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n",
46 		cpu_num, csig->sig, csig->pf, csig->rev);
47 
48 	return 0;
49 }
50 
51 /*
52  * return 0 - no update found
53  * return 1 - found update
54  */
55 static int get_matching_mc(struct microcode_intel *mc_intel, int cpu)
56 {
57 	struct cpu_signature cpu_sig;
58 	unsigned int csig, cpf, crev;
59 
60 	collect_cpu_info(cpu, &cpu_sig);
61 
62 	csig = cpu_sig.sig;
63 	cpf = cpu_sig.pf;
64 	crev = cpu_sig.rev;
65 
66 	return has_newer_microcode(mc_intel, csig, cpf, crev);
67 }
68 
69 static int apply_microcode_intel(int cpu)
70 {
71 	struct microcode_intel *mc_intel;
72 	struct ucode_cpu_info *uci;
73 	unsigned int val[2];
74 	int cpu_num = raw_smp_processor_id();
75 	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
76 
77 	uci = ucode_cpu_info + cpu;
78 	mc_intel = uci->mc;
79 
80 	/* We should bind the task to the CPU */
81 	BUG_ON(cpu_num != cpu);
82 
83 	if (mc_intel == NULL)
84 		return 0;
85 
86 	/*
87 	 * Microcode on this CPU could be updated earlier. Only apply the
88 	 * microcode patch in mc_intel when it is newer than the one on this
89 	 * CPU.
90 	 */
91 	if (get_matching_mc(mc_intel, cpu) == 0)
92 		return 0;
93 
94 	/* write microcode via MSR 0x79 */
95 	wrmsr(MSR_IA32_UCODE_WRITE,
96 	      (unsigned long) mc_intel->bits,
97 	      (unsigned long) mc_intel->bits >> 16 >> 16);
98 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
99 
100 	/* As documented in the SDM: Do a CPUID 1 here */
101 	sync_core();
102 
103 	/* get the current revision from MSR 0x8B */
104 	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
105 
106 	if (val[1] != mc_intel->hdr.rev) {
107 		pr_err("CPU%d update to revision 0x%x failed\n",
108 		       cpu_num, mc_intel->hdr.rev);
109 		return -1;
110 	}
111 	pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n",
112 		cpu_num, val[1],
113 		mc_intel->hdr.date & 0xffff,
114 		mc_intel->hdr.date >> 24,
115 		(mc_intel->hdr.date >> 16) & 0xff);
116 
117 	uci->cpu_sig.rev = val[1];
118 	c->microcode = val[1];
119 
120 	return 0;
121 }
122 
123 static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
124 				int (*get_ucode_data)(void *, const void *, size_t))
125 {
126 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
127 	u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
128 	int new_rev = uci->cpu_sig.rev;
129 	unsigned int leftover = size;
130 	enum ucode_state state = UCODE_OK;
131 	unsigned int curr_mc_size = 0;
132 	unsigned int csig, cpf;
133 
134 	while (leftover) {
135 		struct microcode_header_intel mc_header;
136 		unsigned int mc_size;
137 
138 		if (leftover < sizeof(mc_header)) {
139 			pr_err("error! Truncated header in microcode data file\n");
140 			break;
141 		}
142 
143 		if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header)))
144 			break;
145 
146 		mc_size = get_totalsize(&mc_header);
147 		if (!mc_size || mc_size > leftover) {
148 			pr_err("error! Bad data in microcode data file\n");
149 			break;
150 		}
151 
152 		/* For performance reasons, reuse mc area when possible */
153 		if (!mc || mc_size > curr_mc_size) {
154 			vfree(mc);
155 			mc = vmalloc(mc_size);
156 			if (!mc)
157 				break;
158 			curr_mc_size = mc_size;
159 		}
160 
161 		if (get_ucode_data(mc, ucode_ptr, mc_size) ||
162 		    microcode_sanity_check(mc, 1) < 0) {
163 			break;
164 		}
165 
166 		csig = uci->cpu_sig.sig;
167 		cpf = uci->cpu_sig.pf;
168 		if (has_newer_microcode(mc, csig, cpf, new_rev)) {
169 			vfree(new_mc);
170 			new_rev = mc_header.rev;
171 			new_mc  = mc;
172 			mc = NULL;	/* trigger new vmalloc */
173 		}
174 
175 		ucode_ptr += mc_size;
176 		leftover  -= mc_size;
177 	}
178 
179 	vfree(mc);
180 
181 	if (leftover) {
182 		vfree(new_mc);
183 		state = UCODE_ERROR;
184 		goto out;
185 	}
186 
187 	if (!new_mc) {
188 		state = UCODE_NFOUND;
189 		goto out;
190 	}
191 
192 	vfree(uci->mc);
193 	uci->mc = (struct microcode_intel *)new_mc;
194 
195 	/*
196 	 * If early loading microcode is supported, save this mc into
197 	 * permanent memory. So it will be loaded early when a CPU is hot added
198 	 * or resumes.
199 	 */
200 	save_mc_for_early(new_mc);
201 
202 	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
203 		 cpu, new_rev, uci->cpu_sig.rev);
204 out:
205 	return state;
206 }
207 
208 static int get_ucode_fw(void *to, const void *from, size_t n)
209 {
210 	memcpy(to, from, n);
211 	return 0;
212 }
213 
214 static enum ucode_state request_microcode_fw(int cpu, struct device *device,
215 					     bool refresh_fw)
216 {
217 	char name[30];
218 	struct cpuinfo_x86 *c = &cpu_data(cpu);
219 	const struct firmware *firmware;
220 	enum ucode_state ret;
221 
222 	sprintf(name, "intel-ucode/%02x-%02x-%02x",
223 		c->x86, c->x86_model, c->x86_mask);
224 
225 	if (request_firmware_direct(&firmware, name, device)) {
226 		pr_debug("data file %s load failed\n", name);
227 		return UCODE_NFOUND;
228 	}
229 
230 	ret = generic_load_microcode(cpu, (void *)firmware->data,
231 				     firmware->size, &get_ucode_fw);
232 
233 	release_firmware(firmware);
234 
235 	return ret;
236 }
237 
238 static int get_ucode_user(void *to, const void *from, size_t n)
239 {
240 	return copy_from_user(to, from, n);
241 }
242 
243 static enum ucode_state
244 request_microcode_user(int cpu, const void __user *buf, size_t size)
245 {
246 	return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
247 }
248 
249 static void microcode_fini_cpu(int cpu)
250 {
251 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
252 
253 	vfree(uci->mc);
254 	uci->mc = NULL;
255 }
256 
257 static struct microcode_ops microcode_intel_ops = {
258 	.request_microcode_user		  = request_microcode_user,
259 	.request_microcode_fw             = request_microcode_fw,
260 	.collect_cpu_info                 = collect_cpu_info,
261 	.apply_microcode                  = apply_microcode_intel,
262 	.microcode_fini_cpu               = microcode_fini_cpu,
263 };
264 
265 struct microcode_ops * __init init_intel_microcode(void)
266 {
267 	struct cpuinfo_x86 *c = &cpu_data(0);
268 
269 	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
270 	    cpu_has(c, X86_FEATURE_IA64)) {
271 		pr_err("Intel CPU family 0x%x not supported\n", c->x86);
272 		return NULL;
273 	}
274 
275 	return &microcode_intel_ops;
276 }
277 
278