changeset 13650:8f838b3f28d2

2546 Support new AMD microcode format, update bundled AMD microcode patch file Reviewed by: Gordon Ross <gordon.w.ross@gmail.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Albert Lee <trisk@nexenta.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
date Tue, 27 Mar 2012 13:56:18 -0500
parents 049724836164
children af464d8d3a31
files usr/src/cmd/ucodeadm/amd-ucode.bin usr/src/common/ucode/ucode_utils.c usr/src/uts/common/sys/ucode.h usr/src/uts/i86pc/os/microcode.c
diffstat 4 files changed, 27 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
Binary file usr/src/cmd/ucodeadm/amd-ucode.bin has changed
--- a/usr/src/common/ucode/ucode_utils.c	Tue Jun 21 03:21:18 2011 -0700
+++ b/usr/src/common/ucode/ucode_utils.c	Tue Mar 27 13:56:18 2012 -0500
@@ -142,21 +142,14 @@
 	ptr = (uint32_t *)(((uint8_t *)ptr) + count);
 	size -= count;
 
-	/*
-	 * minimum valid size:
-	 * - type and size fields (8 bytes)
-	 * - patch header (64 bytes)
-	 * - one patch triad (28 bytes)
-	 */
-	while (size >= 100) {
+	while (size > 8) {
 		/* microcode patch */
 		size -= 4;
 		if (*ptr++ != 1)
 			return (EM_FILEFORMAT);
 
 		size -= 4;
-		if (((count = *ptr++) > size) ||
-		    ((count - sizeof (ucode_header_amd_t)) % 28))
+		if (((count = *ptr++) > size))
 			return (EM_FILEFORMAT);
 
 		/* LINTED: pointer alignment */
--- a/usr/src/uts/common/sys/ucode.h	Tue Jun 21 03:21:18 2011 -0700
+++ b/usr/src/uts/common/sys/ucode.h	Tue Mar 27 13:56:18 2012 -0500
@@ -116,6 +116,7 @@
 	uint8_t uf_resv[896];
 	uint8_t uf_code_present;
 	uint8_t uf_code[191];
+	uint8_t uf_encr[2048];
 #else
 	uint8_t *ucodep;
 	uint32_t usize;
--- a/usr/src/uts/i86pc/os/microcode.c	Tue Jun 21 03:21:18 2011 -0700
+++ b/usr/src/uts/i86pc/os/microcode.c	Tue Mar 27 13:56:18 2012 -0500
@@ -33,6 +33,7 @@
 #include <sys/kobj.h>
 #include <sys/kobj_impl.h>
 #include <sys/machsystm.h>
+#include <sys/ontrap.h>
 #include <sys/param.h>
 #include <sys/machparam.h>
 #include <sys/promif.h>
@@ -646,16 +647,17 @@
 	if (ucodefp == NULL || size < sizeof (ucode_header_amd_t))
 		return (EM_NOMATCH);
 
+	uh = &ucodefp->uf_header;
+
 	/*
 	 * Don't even think about loading patches that would require code
-	 * execution.
+	 * execution. Does not apply to patches for family 0x14 and beyond.
 	 */
-	if (size > offsetof(ucode_file_amd_t, uf_code_present) &&
+	if (uh->uh_cpu_rev < 0x5000 &&
+	    size > offsetof(ucode_file_amd_t, uf_code_present) &&
 	    ucodefp->uf_code_present)
 		return (EM_NOMATCH);
 
-	uh = &ucodefp->uf_header;
-
 	if (eq_sig != uh->uh_cpu_rev)
 		return (EM_NOMATCH);
 
@@ -671,7 +673,7 @@
 		return (EM_NOMATCH);
 	}
 
-	if (uh->uh_patch_id <= uinfop->cui_rev)
+	if (uh->uh_patch_id <= uinfop->cui_rev && !ucode_force_update)
 		return (EM_HIGHERREV);
 
 	return (EM_OK);
@@ -726,6 +728,9 @@
 {
 	ucode_update_t *uusp = (ucode_update_t *)arg1;
 	cpu_ucode_info_t *uinfop = CPU->cpu_m.mcpu_ucode_info;
+#ifndef __xpv
+	on_trap_data_t otd;
+#endif
 
 	ASSERT(ucode);
 	ASSERT(uusp->ucodep);
@@ -743,7 +748,10 @@
 			return (0);
 	}
 
-	wrmsr(ucode->write_msr, (uintptr_t)uusp->ucodep);
+	if (!on_trap(&otd, OT_DATA_ACCESS))
+		wrmsr(ucode->write_msr, (uintptr_t)uusp->ucodep);
+
+	no_trap();
 #endif
 	ucode->read_rev(uinfop);
 	uusp->new_rev = uinfop->cui_rev;
@@ -758,6 +766,8 @@
 	ucode_file_amd_t *ucodefp = ufp->amd;
 #ifdef	__xpv
 	ucode_update_t uus;
+#else
+	on_trap_data_t otd;
 #endif
 
 	ASSERT(ucode);
@@ -765,7 +775,13 @@
 
 #ifndef	__xpv
 	kpreempt_disable();
+	if (on_trap(&otd, OT_DATA_ACCESS)) {
+		no_trap();
+		kpreempt_enable();
+		return (0);
+	}
 	wrmsr(ucode->write_msr, (uintptr_t)ucodefp);
+	no_trap();
 	ucode->read_rev(uinfop);
 	kpreempt_enable();
 
@@ -1093,7 +1109,8 @@
 		kpreempt_enable();
 		CPUSET_DEL(cpuset, id);
 
-		if (uusp->new_rev != 0 && uusp->info.cui_rev == uusp->new_rev) {
+		if (uusp->new_rev != 0 && uusp->info.cui_rev == uusp->new_rev &&
+		    !ucode_force_update) {
 			rc = EM_HIGHERREV;
 		} else if ((uusp->new_rev == 0) || (uusp->expected_rev != 0 &&
 		    uusp->expected_rev != uusp->new_rev)) {