2546 Support new AMD microcode format, update bundled AMD microcode patch file
Reviewed by: Gordon Ross <
[email protected]>
Reviewed by: Garrett D'Amore <
[email protected]>
Reviewed by: Albert Lee <
[email protected]>
Approved by: Richard Lowe <
[email protected]>
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)) {