Mercurial > illumos > illumos-gate
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
--- 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)) {