Author: markj
Date: Fri Sep 14 17:04:36 2018
New Revision: 338687
URL: https://svnweb.freebsd.org/changeset/base/338687

Log:
  Log a message after a successful boot-time microcode update.
  
  Reviewed by:  kib
  Approved by:  re (delphij)
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D17135

Modified:
  head/sys/dev/cpuctl/cpuctl.c
  head/sys/x86/include/ucode.h
  head/sys/x86/x86/ucode.c

Modified: head/sys/dev/cpuctl/cpuctl.c
==============================================================================
--- head/sys/dev/cpuctl/cpuctl.c        Fri Sep 14 16:25:34 2018        
(r338686)
+++ head/sys/dev/cpuctl/cpuctl.c        Fri Sep 14 17:04:36 2018        
(r338687)
@@ -362,7 +362,7 @@ update_intel(int cpu, cpuctl_update_args_t *args, stru
        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);

Modified: head/sys/x86/include/ucode.h
==============================================================================
--- head/sys/x86/include/ucode.h        Fri Sep 14 16:25:34 2018        
(r338686)
+++ head/sys/x86/include/ucode.h        Fri Sep 14 17:04:36 2018        
(r338687)
@@ -58,7 +58,8 @@ struct ucode_intel_extsig_table {
        } 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);

Modified: head/sys/x86/x86/ucode.c
==============================================================================
--- head/sys/x86/x86/ucode.c    Fri Sep 14 16:25:34 2018        (r338686)
+++ head/sys/x86/x86/ucode.c    Fri Sep 14 17:04:36 2018        (r338687)
@@ -59,7 +59,7 @@ static int    ucode_intel_verify(struct ucode_intel_heade
 
 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,46 @@ static struct ucode_ops {
 /* Selected microcode update data. */
 static void *early_ucode_data;
 static void *ucode_data;
+static struct ucode_ops *ucode_loader;
 
-static char errbuf[128];
+/* Variables used for reporting success or failure. */
+enum {
+       NO_ERROR,
+       NO_MATCH,
+       VERIFICATION_FAILED,
+} ucode_error = NO_ERROR;
+static uint64_t ucode_nrev, ucode_orev;
 
-static void __printflike(1, 2)
-log_err(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
-       va_end(ap);
-}
-
 static void
-print_err(void *arg __unused)
+log_msg(void *arg __unused)
 {
 
-       if (errbuf[0] != '\0')
-               printf("microcode load error: %s\n", errbuf);
+       if (ucode_nrev != 0) {
+               printf("CPU microcode: updated from %#jx to %#jx\n",
+                   (uintmax_t)ucode_orev, (uintmax_t)ucode_nrev);
+               return;
+       }
+
+       switch (ucode_error) {
+       case NO_MATCH:
+               printf("CPU microcode: no matching update found\n");
+               break;
+       case VERIFICATION_FAILED:
+               printf("CPU microcode: microcode verification failed\n");
+               break;
+       default:
+               break;
+       }
 }
-SYSINIT(ucode_print_err, SI_SUB_CPU, SI_ORDER_FIRST, print_err, NULL);
+SYSINIT(ucode_log, SI_SUB_CPU, SI_ORDER_FIRST, log_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 +129,15 @@ ucode_intel_load(void *data, bool unsafe)
         */
        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);
 }
@@ -130,36 +148,26 @@ ucode_intel_verify(struct ucode_intel_header *hdr, siz
        uint32_t cksum, *data, size;
        int i;
 
-       if (resid < sizeof(struct ucode_intel_header)) {
-               log_err("truncated update header");
+       if (resid < sizeof(struct ucode_intel_header))
                return (1);
-       }
        size = hdr->total_size;
        if (size == 0)
                size = UCODE_INTEL_DEFAULT_DATA_SIZE +
                    sizeof(struct ucode_intel_header);
 
-       if (hdr->header_version != 1) {
-               log_err("unexpected header version %u", hdr->header_version);
+       if (hdr->header_version != 1)
                return (1);
-       }
-       if (size % 16 != 0) {
-               log_err("unexpected update size %u", hdr->total_size);
+       if (size % 16 != 0)
                return (1);
-       }
-       if (resid < size) {
-               log_err("truncated update");
+       if (resid < size)
                return (1);
-       }
 
        cksum = 0;
        data = (uint32_t *)hdr;
        for (i = 0; i < size / sizeof(uint32_t); i++)
                cksum += data[i];
-       if (cksum != 0) {
-               log_err("checksum failed");
+       if (cksum != 0)
                return (1);
-       }
        return (0);
 }
 
@@ -182,8 +190,10 @@ ucode_intel_match(uint8_t *data, size_t *len)
 
        for (resid = *len; resid > 0; data += total_size, resid -= total_size) {
                hdr = (struct ucode_intel_header *)data;
-               if (ucode_intel_verify(hdr, resid) != 0)
+               if (ucode_intel_verify(hdr, resid) != 0) {
+                       ucode_error = VERIFICATION_FAILED;
                        break;
+               }
 
                data_size = hdr->data_size;
                total_size = hdr->total_size;
@@ -264,7 +274,7 @@ ucode_load_ap(int cpu)
 #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 +318,12 @@ ucode_load_bsp(uintptr_t free)
                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;
+       size_t i, len;
+       int error;
 
        KASSERT(free % PAGE_SIZE == 0, ("unaligned boundary %p", (void *)free));
 
@@ -320,17 +331,16 @@ ucode_load_bsp(uintptr_t free)
        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;
        fileaddr = match = NULL;
-       ucode_len = 0;
        for (;;) {
                file = preload_search_next_name(file);
                if (file == 0)
@@ -341,7 +351,7 @@ ucode_load_bsp(uintptr_t free)
 
                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,18 +359,19 @@ ucode_load_bsp(uintptr_t free)
                                addr[i] = ((volatile uint8_t *)match)[i];
                        match = addr;
 
-                       if (loader->load(match, false) == 0) {
-                               ucode_data = match;
-                               ucode_len = len;
-                               early_ucode_data = ucode_data;
-                               break;
+                       error = ucode_loader->load(match, false, &nrev, &orev);
+                       if (error == 0) {
+                               ucode_data = early_ucode_data = match;
+                               ucode_nrev = nrev;
+                               ucode_orev = orev;
+                               return (len);
                        }
                        unmap_ucode(free, len);
                }
        }
-       if (fileaddr != NULL && ucode_data == NULL)
-               log_err("no matching update found");
-       return (ucode_len);
+       if (fileaddr != NULL && ucode_error == NO_ERROR)
+               ucode_error = NO_MATCH;
+       return (0);
 }
 
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to