xref: /freebsd/sys/x86/x86/ucode.c (revision d9f03a43f2fec917c31d48b05d751e547c8775c7)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2018 The FreeBSD Foundation
5  *
6  * This software was developed by Mark Johnston under sponsorship from
7  * the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/cpuset.h>
33 #include <sys/kernel.h>
34 #include <sys/linker.h>
35 #include <sys/malloc.h>
36 #include <sys/pcpu.h>
37 #include <sys/smp.h>
38 #include <sys/stdarg.h>
39 #include <sys/systm.h>
40 
41 #include <machine/atomic.h>
42 #include <machine/cpufunc.h>
43 #include <machine/md_var.h>
44 #include <x86/specialreg.h>
45 #include <x86/ucode.h>
46 #include <x86/x86_smp.h>
47 
48 #include <vm/vm.h>
49 #include <vm/pmap.h>
50 #include <vm/vm_extern.h>
51 #include <vm/vm_kern.h>
52 #include <vm/vm_param.h>
53 
54 static const void	*ucode_intel_match(const uint8_t *data, size_t *len);
55 static int	ucode_intel_verify(const struct ucode_intel_header *hdr,
56 		    size_t resid);
57 
58 static const void	*ucode_amd_match(const uint8_t *data, size_t *len);
59 
60 static struct ucode_ops {
61 	const char *vendor;
62 	int (*load)(const void *, ucode_load_how how, uint64_t *, uint64_t *);
63 	const void *(*match)(const uint8_t *, size_t *);
64 } loaders[] = {
65 	{
66 		.vendor = INTEL_VENDOR_ID,
67 		.load = ucode_intel_load,
68 		.match = ucode_intel_match,
69 	},
70 	{
71 		.vendor = AMD_VENDOR_ID,
72 		.load = ucode_amd_load,
73 		.match = ucode_amd_match,
74 	},
75 };
76 
77 /* Selected microcode update data. */
78 static const void *early_ucode_data;
79 static const void *ucode_data;
80 static struct ucode_ops *ucode_loader;
81 
82 /* Variables used for reporting success or failure. */
83 enum {
84 	NO_ERROR,
85 	NO_MATCH,
86 	VERIFICATION_FAILED,
87 	LOAD_FAILED,
88 } ucode_error = NO_ERROR;
89 static uint64_t ucode_nrev, ucode_orev;
90 
91 static void
log_msg(void * arg __unused)92 log_msg(void *arg __unused)
93 {
94 
95 	if (ucode_nrev != 0) {
96 		printf("CPU microcode: updated from %#jx to %#jx\n",
97 		    (uintmax_t)ucode_orev, (uintmax_t)ucode_nrev);
98 		return;
99 	}
100 
101 	switch (ucode_error) {
102 	case NO_MATCH:
103 		printf("CPU microcode: no matching update found\n");
104 		break;
105 	case VERIFICATION_FAILED:
106 		printf("CPU microcode: microcode verification failed\n");
107 		break;
108 	case LOAD_FAILED:
109 		printf("CPU microcode load failed. BIOS update advised\n");
110 		break;
111 	default:
112 		break;
113 	}
114 }
115 SYSINIT(ucode_log, SI_SUB_CPU, SI_ORDER_FIRST, log_msg, NULL);
116 
117 int
ucode_intel_load(const void * data,ucode_load_how how,uint64_t * nrevp,uint64_t * orevp)118 ucode_intel_load(const void *data, ucode_load_how how, uint64_t *nrevp,
119     uint64_t *orevp)
120 {
121 	uint64_t nrev, orev;
122 	uint32_t cpuid[4];
123 
124 	orev = rdmsr(MSR_BIOS_SIGN) >> 32;
125 
126 	/*
127 	 * Perform update.  Flush caches first to work around seemingly
128 	 * undocumented errata applying to some Broadwell CPUs.
129 	 */
130 	wbinvd();
131 	switch (how) {
132 	case SAFE:
133 		wrmsr_safe(MSR_BIOS_UPDT_TRIG, (uint64_t)(uintptr_t)data);
134 		break;
135 	case EARLY:
136 #ifdef __amd64__
137 		wrmsr_early_safe_start();
138 		if (wrmsr_early_safe(MSR_BIOS_UPDT_TRIG,
139 		    (uint64_t)(uintptr_t)data) != 0)
140 			ucode_error = LOAD_FAILED;
141 		wrmsr_early_safe_end();
142 		break;
143 #endif
144 	case UNSAFE:
145 		wrmsr(MSR_BIOS_UPDT_TRIG, (uint64_t)(uintptr_t)data);
146 		break;
147 	}
148 	wrmsr(MSR_BIOS_SIGN, 0);
149 
150 	/*
151 	 * Serialize instruction flow.
152 	 */
153 	do_cpuid(0, cpuid);
154 
155 	/*
156 	 * Verify that the microcode revision changed.
157 	 */
158 	nrev = rdmsr(MSR_BIOS_SIGN) >> 32;
159 	if (nrevp != NULL)
160 		*nrevp = nrev;
161 	if (orevp != NULL)
162 		*orevp = orev;
163 	if (nrev <= orev)
164 		return (EEXIST);
165 	return (0);
166 }
167 
168 static int
ucode_intel_verify(const struct ucode_intel_header * hdr,size_t resid)169 ucode_intel_verify(const struct ucode_intel_header *hdr, size_t resid)
170 {
171 	const uint32_t *data;
172 	uint32_t cksum, size;
173 	int i;
174 
175 	if (resid < sizeof(struct ucode_intel_header))
176 		return (1);
177 	size = hdr->total_size;
178 	if (size == 0)
179 		size = UCODE_INTEL_DEFAULT_DATA_SIZE +
180 		    sizeof(struct ucode_intel_header);
181 
182 	if (hdr->header_version != 1)
183 		return (1);
184 	if (size % 16 != 0)
185 		return (1);
186 	if (resid < size)
187 		return (1);
188 
189 	cksum = 0;
190 	data = (const uint32_t *)hdr;
191 	for (i = 0; i < size / sizeof(uint32_t); i++)
192 		cksum += data[i];
193 	if (cksum != 0)
194 		return (1);
195 	return (0);
196 }
197 
198 static const void *
ucode_intel_match(const uint8_t * data,size_t * len)199 ucode_intel_match(const uint8_t *data, size_t *len)
200 {
201 	const struct ucode_intel_header *hdr;
202 	const struct ucode_intel_extsig_table *table;
203 	const struct ucode_intel_extsig *entry;
204 	uint64_t platformid;
205 	size_t resid;
206 	uint32_t data_size, flags, regs[4], sig, total_size;
207 	int i;
208 
209 	do_cpuid(1, regs);
210 	sig = regs[0];
211 
212 	platformid = rdmsr(MSR_IA32_PLATFORM_ID);
213 	flags = 1 << ((platformid >> 50) & 0x7);
214 
215 	for (resid = *len; resid > 0; data += total_size, resid -= total_size) {
216 		hdr = (const struct ucode_intel_header *)data;
217 		if (ucode_intel_verify(hdr, resid) != 0) {
218 			ucode_error = VERIFICATION_FAILED;
219 			break;
220 		}
221 
222 		data_size = hdr->data_size;
223 		total_size = hdr->total_size;
224 		if (data_size == 0)
225 			data_size = UCODE_INTEL_DEFAULT_DATA_SIZE;
226 		if (total_size == 0)
227 			total_size = UCODE_INTEL_DEFAULT_DATA_SIZE +
228 			    sizeof(struct ucode_intel_header);
229 		if (data_size > total_size + sizeof(struct ucode_intel_header))
230 			table = (const struct ucode_intel_extsig_table *)
231 			    ((const uint8_t *)(hdr + 1) + data_size);
232 		else
233 			table = NULL;
234 
235 		if (hdr->processor_signature == sig) {
236 			if ((hdr->processor_flags & flags) != 0) {
237 				*len = data_size;
238 				return (hdr + 1);
239 			}
240 		} else if (table != NULL) {
241 			for (i = 0; i < table->signature_count; i++) {
242 				entry = &table->entries[i];
243 				if (entry->processor_signature == sig &&
244 				    (entry->processor_flags & flags) != 0) {
245 					*len = data_size;
246 					return (hdr + 1);
247 				}
248 			}
249 		}
250 	}
251 	return (NULL);
252 }
253 
254 int
ucode_amd_load(const void * data,ucode_load_how how,uint64_t * nrevp,uint64_t * orevp)255 ucode_amd_load(const void *data, ucode_load_how how, uint64_t *nrevp,
256     uint64_t *orevp)
257 {
258 	uint64_t nrev, orev;
259 	uint32_t cpuid[4];
260 
261 	orev = rdmsr(MSR_BIOS_SIGN);
262 
263 	switch (how) {
264 	case SAFE:
265 		wrmsr_safe(MSR_K8_UCODE_UPDATE, (uint64_t)(uintptr_t)data);
266 		break;
267 	case EARLY:
268 #ifdef __amd64__
269 		wrmsr_early_safe_start();
270 		if (wrmsr_early_safe(MSR_K8_UCODE_UPDATE,
271 		    (uint64_t)(uintptr_t)data) != 0)
272 			ucode_error = LOAD_FAILED;
273 		wrmsr_early_safe_end();
274 		break;
275 #endif
276 	case UNSAFE:
277 		wrmsr(MSR_K8_UCODE_UPDATE, (uint64_t)(uintptr_t)data);
278 		break;
279 	}
280 
281 	/*
282 	 * Serialize instruction flow.
283 	 */
284 	do_cpuid(0, cpuid);
285 
286 	/*
287 	 * Verify that the microcode revision changed.
288 	 */
289 	nrev = rdmsr(MSR_BIOS_SIGN);
290 	if (nrevp != NULL)
291 		*nrevp = nrev;
292 	if (orevp != NULL)
293 		*orevp = orev;
294 	if (nrev <= orev)
295 		return (EEXIST);
296 	return (0);
297 
298 }
299 
300 static const void *
ucode_amd_match(const uint8_t * data,size_t * len)301 ucode_amd_match(const uint8_t *data, size_t *len)
302 {
303 	uint32_t signature, revision;
304 	uint32_t regs[4];
305 
306 	do_cpuid(1, regs);
307 	signature = regs[0];
308 	revision = rdmsr(MSR_BIOS_SIGN);
309 
310 	return (ucode_amd_find("loader blob", signature, &revision, data, *len,
311 	    len));
312 }
313 
314 /*
315  * Release any memory backing unused microcode blobs back to the system.
316  * We copy the selected update and free the entire microcode file.
317  */
318 static void
ucode_release(void * arg __unused)319 ucode_release(void *arg __unused)
320 {
321 	char *name, *type;
322 	caddr_t file;
323 	int release;
324 
325 	if (early_ucode_data == NULL)
326 		return;
327 	release = 1;
328 	TUNABLE_INT_FETCH("debug.ucode.release", &release);
329 	if (!release)
330 		return;
331 
332 restart:
333 	file = 0;
334 	for (;;) {
335 		file = preload_search_next_name(file);
336 		if (file == 0)
337 			break;
338 		type = (char *)preload_search_info(file, MODINFO_TYPE);
339 		if (type == NULL || strcmp(type, "cpu_microcode") != 0)
340 			continue;
341 
342 		name = preload_search_info(file, MODINFO_NAME);
343 		preload_delete_name(name);
344 		goto restart;
345 	}
346 }
347 SYSINIT(ucode_release, SI_SUB_SMP + 1, SI_ORDER_ANY, ucode_release, NULL);
348 
349 void
ucode_load_ap(int cpu)350 ucode_load_ap(int cpu)
351 {
352 #ifdef SMP
353 	KASSERT(cpu_info[cpu_apic_ids[cpu]].cpu_present,
354 	    ("cpu %d not present", cpu));
355 
356 	if (cpu_info[cpu_apic_ids[cpu]].cpu_hyperthread)
357 		return;
358 #endif
359 
360 	if (ucode_data != NULL && ucode_error != LOAD_FAILED)
361 		(void)ucode_loader->load(ucode_data, UNSAFE, NULL, NULL);
362 }
363 
364 static void *
map_ucode(uintptr_t free,size_t len)365 map_ucode(uintptr_t free, size_t len)
366 {
367 #ifdef __i386__
368 	uintptr_t va;
369 
370 	for (va = free; va < free + len; va += PAGE_SIZE)
371 		pmap_kenter(va, (vm_paddr_t)va);
372 #else
373 	(void)len;
374 #endif
375 	return ((void *)free);
376 }
377 
378 static void
unmap_ucode(uintptr_t free,size_t len)379 unmap_ucode(uintptr_t free, size_t len)
380 {
381 #ifdef __i386__
382 	uintptr_t va;
383 
384 	for (va = free; va < free + len; va += PAGE_SIZE)
385 		pmap_kremove(va);
386 #else
387 	(void)free;
388 	(void)len;
389 #endif
390 }
391 
392 /*
393  * Search for an applicable microcode update, and load it.  APs will load the
394  * selected update once they come online.
395  *
396  * "free" is the address of the next free physical page.  If a microcode update
397  * is selected, it will be copied to this region prior to loading in order to
398  * satisfy alignment requirements.
399  */
400 size_t
ucode_load_bsp(uintptr_t free)401 ucode_load_bsp(uintptr_t free)
402 {
403 	union {
404 		uint32_t regs[4];
405 		char vendor[13];
406 	} cpuid;
407 	const uint8_t *fileaddr, *match;
408 	uint8_t *addr;
409 	char *type;
410 	uint64_t nrev, orev;
411 	caddr_t file;
412 	size_t i, len;
413 	int error;
414 
415 	KASSERT(free % PAGE_SIZE == 0, ("unaligned boundary %p", (void *)free));
416 
417 	do_cpuid(0, cpuid.regs);
418 	cpuid.regs[0] = cpuid.regs[1];
419 	cpuid.regs[1] = cpuid.regs[3];
420 	cpuid.vendor[12] = '\0';
421 	for (i = 0; i < nitems(loaders); i++)
422 		if (strcmp(cpuid.vendor, loaders[i].vendor) == 0) {
423 			ucode_loader = &loaders[i];
424 			break;
425 		}
426 	if (ucode_loader == NULL)
427 		return (0);
428 
429 	file = 0;
430 	fileaddr = match = NULL;
431 	for (;;) {
432 		file = preload_search_next_name(file);
433 		if (file == 0)
434 			break;
435 		type = (char *)preload_search_info(file, MODINFO_TYPE);
436 		if (type == NULL || strcmp(type, "cpu_microcode") != 0)
437 			continue;
438 
439 		fileaddr = preload_fetch_addr(file);
440 		len = preload_fetch_size(file);
441 		match = ucode_loader->match(fileaddr, &len);
442 		if (match != NULL) {
443 			addr = map_ucode(free, len);
444 			/* We can't use memcpy() before ifunc resolution. */
445 			memcpy_early(addr, match, len);
446 			match = addr;
447 
448 			error = ucode_loader->load(match, EARLY, &nrev, &orev);
449 			if (error == 0) {
450 				ucode_data = early_ucode_data = match;
451 				ucode_nrev = nrev;
452 				ucode_orev = orev;
453 				return (len);
454 			}
455 			unmap_ucode(free, len);
456 		}
457 	}
458 	if (fileaddr != NULL && ucode_error == NO_ERROR)
459 		ucode_error = NO_MATCH;
460 	return (0);
461 }
462 
463 /*
464  * Reload microcode following an ACPI resume.
465  */
466 void
ucode_reload(void)467 ucode_reload(void)
468 {
469 
470 	ucode_load_ap(PCPU_GET(cpuid));
471 }
472 
473 /*
474  * Replace an existing microcode update.
475  */
476 void *
ucode_update(void * newdata)477 ucode_update(void *newdata)
478 {
479 
480 	newdata = (void *)atomic_swap_ptr((void *)&ucode_data,
481 	    (uintptr_t)newdata);
482 	if (newdata == early_ucode_data)
483 		newdata = NULL;
484 	return (newdata);
485 }
486