Index: sys/dev/cpuctl/cpuctl.c =================================================================== --- sys/dev/cpuctl/cpuctl.c +++ sys/dev/cpuctl/cpuctl.c @@ -362,7 +362,7 @@ set_cpu(cpu, td); critical_enter(); - ret = ucode_intel_load(ptr, true); + ret = ucode_intel_load(ptr, true, NULL, NULL); critical_exit(); restore_cpu(oldcpu, is_bound, td); Index: sys/x86/include/ucode.h =================================================================== --- sys/x86/include/ucode.h +++ sys/x86/include/ucode.h @@ -58,7 +58,8 @@ } entries[0]; }; -int ucode_intel_load(void *data, bool unsafe); +int ucode_intel_load(void *data, bool unsafe, + uint64_t *nrevp, uint64_t *orevp); size_t ucode_load_bsp(uintptr_t free); void ucode_load_ap(int cpu); void ucode_reload(void); Index: sys/x86/x86/ucode.c =================================================================== --- sys/x86/x86/ucode.c +++ sys/x86/x86/ucode.c @@ -59,7 +59,7 @@ static struct ucode_ops { const char *vendor; - int (*load)(void *, bool); + int (*load)(void *, bool, uint64_t *, uint64_t *); void *(*match)(uint8_t *, size_t *); } loaders[] = { { @@ -72,35 +72,36 @@ /* Selected microcode update data. */ static void *early_ucode_data; static void *ucode_data; +static struct ucode_ops *ucode_loader; -static char errbuf[128]; +static char msgbuf[128]; static void __printflike(1, 2) -log_err(const char *fmt, ...) +log_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - vsnprintf(errbuf, sizeof(errbuf), fmt, ap); + vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); va_end(ap); } static void -print_err(void *arg __unused) +print_msg(void *arg __unused) { - if (errbuf[0] != '\0') - printf("microcode load error: %s\n", errbuf); + if (msgbuf[0] != '\0') + printf("Microcode: %s\n", msgbuf); } -SYSINIT(ucode_print_err, SI_SUB_CPU, SI_ORDER_FIRST, print_err, NULL); +SYSINIT(ucode_log, SI_SUB_CPU, SI_ORDER_FIRST, print_msg, NULL); int -ucode_intel_load(void *data, bool unsafe) +ucode_intel_load(void *data, bool unsafe, uint64_t *nrevp, uint64_t *orevp) { - uint64_t rev0, rev1; + uint64_t nrev, orev; uint32_t cpuid[4]; - rev0 = rdmsr(MSR_BIOS_SIGN); + orev = rdmsr(MSR_BIOS_SIGN) >> 32; /* * Perform update. Flush caches first to work around seemingly @@ -118,8 +119,15 @@ */ do_cpuid(0, cpuid); - rev1 = rdmsr(MSR_BIOS_SIGN); - if (rev1 <= rev0) + /* + * Verify that the microcode revision changed. + */ + nrev = rdmsr(MSR_BIOS_SIGN) >> 32; + if (nrevp != NULL) + *nrevp = nrev; + if (orevp != NULL) + *orevp = orev; + if (nrev <= orev) return (EEXIST); return (0); } @@ -131,7 +139,7 @@ int i; if (resid < sizeof(struct ucode_intel_header)) { - log_err("truncated update header"); + log_msg("truncated update header"); return (1); } size = hdr->total_size; @@ -140,15 +148,15 @@ sizeof(struct ucode_intel_header); if (hdr->header_version != 1) { - log_err("unexpected header version %u", hdr->header_version); + log_msg("unexpected header version %u", hdr->header_version); return (1); } if (size % 16 != 0) { - log_err("unexpected update size %u", hdr->total_size); + log_msg("unexpected update size %u", hdr->total_size); return (1); } if (resid < size) { - log_err("truncated update"); + log_msg("truncated update"); return (1); } @@ -157,7 +165,7 @@ for (i = 0; i < size / sizeof(uint32_t); i++) cksum += data[i]; if (cksum != 0) { - log_err("checksum failed"); + log_msg("checksum failed"); return (1); } return (0); @@ -264,7 +272,7 @@ #endif if (ucode_data != NULL) - (void)ucode_intel_load(ucode_data, false); + (void)ucode_loader->load(ucode_data, false, NULL, NULL); } static void * @@ -308,11 +316,12 @@ uint32_t regs[4]; char vendor[13]; } cpuid; - struct ucode_ops *loader; uint8_t *addr, *fileaddr, *match; char *type; + uint64_t nrev, orev; caddr_t file; size_t i, len, ucode_len; + int error; KASSERT(free % PAGE_SIZE == 0, ("unaligned boundary %p", (void *)free)); @@ -320,12 +329,12 @@ cpuid.regs[0] = cpuid.regs[1]; cpuid.regs[1] = cpuid.regs[3]; cpuid.vendor[12] = '\0'; - for (i = 0, loader = NULL; i < nitems(loaders); i++) + for (i = 0; i < nitems(loaders); i++) if (strcmp(cpuid.vendor, loaders[i].vendor) == 0) { - loader = &loaders[i]; + ucode_loader = &loaders[i]; break; } - if (loader == NULL) + if (ucode_loader == NULL) return (0); file = 0; @@ -341,7 +350,7 @@ fileaddr = preload_fetch_addr(file); len = preload_fetch_size(file); - match = loader->match(fileaddr, &len); + match = ucode_loader->match(fileaddr, &len); if (match != NULL) { addr = map_ucode(free, len); /* We can't use memcpy() before ifunc resolution. */ @@ -349,7 +358,10 @@ addr[i] = ((volatile uint8_t *)match)[i]; match = addr; - if (loader->load(match, false) == 0) { + error = ucode_loader->load(match, false, &nrev, &orev); + if (error == 0) { + log_msg("updated from revision %#jx to %#jx", + (uintmax_t)orev, (uintmax_t)nrev); ucode_data = match; ucode_len = len; early_ucode_data = ucode_data; @@ -359,7 +371,7 @@ } } if (fileaddr != NULL && ucode_data == NULL) - log_err("no matching update found"); + log_msg("no matching update found"); return (ucode_len); }