Update Intel Microcode on FreeBSD
FreeBSD provides support for updating the microcode of a processor at startup or at runtime. In this article, we use a server running FreeBSD 12.0 to show how to check the Intel Microcode version and how to install newer microcode versions if necessary.
Example Setup
In this example we use the following setup:
- Server using an ASUS P9D-MV Mainboard with BIOS Version 2101 and an Intel Celeron G1820T CPU
- FreeBSD 12.0
The example was carried out on 16.01.2019 with the most current BIOS, microcode and software versions available at that time. It clearly shows how the latest security updates can be installed in security-critical environments, both in terms of microcode and software updates.
Read current microcode version
Information about the CPU (name, CPUID, microcode version) can be queried with the tool x86info after loading the module cpuctl:
kldload cpuctl
x86info -a
In the output the line Microcode version shows the version (in the example 0x000000000000000024), the CPUID can be found in the second line in the eax output (in the example 000306c3):
root@freebsd12:~ # kldload cpuctl root@freebsd12:~ # x86info -a x86info v1.31pre MP Table: # APIC ID Version State Family Model Step Flags # 0 0x15 BSP, usable 6 12 3 0x0381 # 2 0x15 AP, usable 6 12 3 0x0381 Found 2 identical CPUs Extended Family: 0 Extended Model: 3 Family: 6 Model: 60 Stepping: 3 Type: 0 (Original OEM) CPU Model (x86info's best guess): Xeon E3 [Haswell] Processor name string (BIOS programmed): Intel(R) Celeron(R) CPU G1820T @ 2.40GHz [...] Microcode version: 0x0000000000000024 eax in: 0x00000000, eax = 0000000d ebx = 756e6547 ecx = 6c65746e edx = 49656e69 eax in: 0x00000001, eax = 000306c3 ebx = 00100800 ecx = 4ddaebbf edx = bfebfbff
Intel provides information about available microcode versions in the document Microcode Update Guidance (see Intel Microcode - Microcode Versions). This document lists CPUs by their CPUID.
When searching for 306c3 in the document Microcode Update Guidance of 08.08.2018, the column New Production MCU Rev contains the microcode version 0x25. In this case Intel provides a newer microcode version than is currently available through the BIOS on the example system.
Variant 1: Update via devcpu-data
The port devcpu-data contains Intel and AMD CPU microcode updates (binary files). The microcodes of devcpu-data are imported into the CPU via cpuctl(4) / cpucontrol(8). So that the update of the microcode is carried out automatically during the start process, the entries cpu_microcode_load and cpu_microcode_name must be added to /boot/loader.conf.
To install the microcode updates automatically in the future, install the package devcpu-data and enter both options in /boot/loader.conf:
# pkg install devcpu-data # vi /boot/loader.conf # cat /boot/loader.conf cpu_microcode_load="YES" cpu_microcode_name="/boot/firmware/intel-ucode.bin" # reboot
On the example system, the microcode version is updated from 0x24 to 0x25:
root@freebsd12:~ # pkg install devcpu-data [...] Message from devcpu-data-1.20: Installing this port will allow host startup to update the CPU microcode on a FreeBSD system automatically. There are two methods for updating CPU microcode: the first methods loads and applies the update before the kernel begins booting, and the second method loads and applies updates using an rc script. The first method is preferred, but is currently only supported on Intel i386 and amd64 processors running FreeBSD 12.0. It is safe to enable both methods. The first method ensures that any CPU features introduced by a microcode update are visible to the kernel. In other words, the update is loaded before the kernel performs CPU feature detection. To enable updates using the first method, add the following lines to the system's /boot/loader.conf: cpu_microcode_load="YES" cpu_microcode_name="/boot/firmware/intel-ucode.bin" This method will not load the microcode update until the system is rebooted. To enable updates using the second method, add the following line to the system's /etc/rc.conf: microcode_update_enable="YES" Then, to ensure the update is applied, reboot the system or start the microcode update service via: # service microcode_update start If the CPU requires a microcode update, a console message such as the following will appear: Updating CPU Microcode... /usr/local/share/cpucontrol/m32306c3_00000022.fw: updating cpu /dev/cpuctl0 from rev 0x17 to rev 0x22... done. /usr/local/share/cpucontrol/m32306c3_00000022.fw: updating cpu /dev/cpuctl2 from rev 0x17 to rev 0x22... done. /usr/local/share/cpucontrol/m32306c3_00000022.fw: updating cpu /dev/cpuctl4 from rev 0x17 to rev 0x22... done. /usr/local/share/cpucontrol/m32306c3_00000022.fw: updating cpu /dev/cpuctl6 from rev 0x17 to rev 0x22... done. Done. root@freebsd12:~ # ls -lh /boot/firmware/intel-ucode.bin -rw-r--r-- 1 root wheel 1.7M Jan 11 23:18 /boot/firmware/intel-ucode.bin root@freebsd12:~ # vi /boot/loader.conf root@freebsd12:~ # cat /boot/loader.conf cpu_microcode_load="YES" cpu_microcode_name="/boot/firmware/intel-ucode.bin" root@freebsd12:~ # reboot [...]
After the reboot the new microcode is in use:
root@freebsd12:~ # kldload cpuctl root@freebsd12:~ # x86info -a | grep -i microcode Microcode version: 0x0000000000000025
Variant 2: Update via cpupdate
In addition to the variant described above, another port for updating the microcode has been available since 2018: sysutils/cpupdate. This was developed by Stefan Blachmann as an alternative to devcpu-data to avoid bugs and limitations of devcpu-data.[1][2][3] The new tool cpupdate offers additional functions, e.g. the simple query of the current microcode via cpupdate -i.[4]
The developer recommends that you compile the tool yourself.[5]
As an upgrade from self-compiled ports is difficult,[6] the #Variant 1
The installation of cpupdate on a test system can be done as follows:
# portsnap auto # cd /usr/ports/sysutils/cpupdate # make install
Am Beispielsystem ausgeführt:
root@freebsd12:~ # portsnap auto root@freebsd12:~ # cd /usr/ports root@freebsd12:/usr/ports # make search name=cpupdate Port: cpupdate-g20180513_1 Path: /usr/ports/sysutils/cpupdate Info: CPU microcode update utility for x86 Maint: eugen@FreeBSD.org B-deps: R-deps: WWW: https://github.com/kernschmelze/cpupdate root@freebsd12:/usr/ports # cd /usr/ports/sysutils/cpupdate root@freebsd12:/usr/ports/sysutils/cpupdate # make install ===> Building/installing dialog4ports as it is required for the config dialog [...] ┌─────────────────────────── cpupdate-g20180513_1 ─────────────────────────────┐ │ ┌──────────────────────────────────────────────────────────────────────────┐ │ │ │+[x] CPM Download platomav/CPUMicrocodes collection │ │ │ │+[x] INTEL Download Intel microcode pack microcode-20180807.tgz │ │ │ └──────────────────────────────────────────────────────────────────────────┘ │ ├──────────────────────────────────────────────────────────────────────────────┤ │ < OK > <Cancel> │ └──────────────────────────────────────────────────────────────────────────────┘ ===> License BSD2CLAUSE accepted by the user ===> cpupdate-g20180513_1 depends on file: /usr/local/sbin/pkg - found => microcode-20180807.tgz doesn't seem to exist in /usr/ports/distfiles/. => Attempting to fetch https://downloadmirror.intel.com/28039/eng/microcode-20180807.tgz microcode-20180807.tgz 1591 kB 7924 kBps 01s [...] Installing cpupdate-g20180513_1... !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE: The following directories /usr/ports/sysutils/cpupdate/work/CPUMicrocodes-0d88b2e /usr/ports/sysutils/cpupdate/work/intel-ucode contain Intel and/or platomav/CPUMicrocodes collections respectively if you have just built the port with corresponding CPM/INTEL option(s) enabled. In this case you can run "make install-microcodes" to install them to /usr/local/share/cpupdate !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Suspend/resume sequence clears microcode update, so make sure your system runs "service cpupdate start" again on resume. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! root@freebsd12:/usr/ports/sysutils/cpupdate # make install-microcodes /bin/rm -f -rf /usr/local/share/cpupdate/CPUMicrocodes/primary/Intel /bin/mkdir -p /usr/local/share/cpupdate/CPUMicrocodes/primary/Intel [...] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE: you have to manually remove the directory /usr/local/share/cpupdate/CPUMicrocodes/primary/Intel after deinstallation of cpupdate. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE: you have to manually remove the directory /usr/local/share/cpupdate/CPUMicrocodes/secondary/Intel after deinstallation of cpupdate. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! root@freebsd12:/usr/ports/sysutils/cpupdate #
Cpupdate bietet die folgenden Optionen:
# cpupdate Usage: cpupdate [-qwvvuiCXIAVh] [-<f|U> <microcodefile>] [-<cpsST> <datadir>] -i show processor information -u update microcode -U update microcode using file <microcodefile> -w write it: without this option cpupdate only simulates updating -q quiet mode -v verbose mode, -vv very verbose -p use primary repo path <datadir> -s use secondary repo path <datadir> -V print version -h show this help -IAV for the options below: vendor mode must be set [atm only Intel (-I) implemented] -f show version information of microcode file -c Check integrity of microcode files in <datadir> -d As -c, in addition print microcode file statistics -C convert/compact microcode files from legacy to multi-blob intel-ucode file format -X convert (extract) microcode files from multi-blob intel-ucode to legacy file format -S source dir for converting -T target dir for converting
The update of the microcode at runtime looks as follows in the example system:
root@freebsd12:/usr/ports/sysutils/cpupdate # cpupdate -i Found CPU(s) from Intel Core 0 to 1: CPUID: 306c3 Fam 06 Mod 3c Step 03 Flag 02 uCode 00000024 root@freebsd12:/usr/ports/sysutils/cpupdate # cpupdate -u Found CPU(s) from Intel No updating error. Registering CPU features Successfully registered new CPU features ATTENTION NOTICE: -w option missing! No actual update, only dry run done!. root@freebsd12:/usr/ports/sysutils/cpupdate # cpupdate -w -u Found CPU(s) from Intel No updating error. Registering CPU features Successfully registered new CPU features root@freebsd12:/usr/ports/sysutils/cpupdate # cpupdate -i Found CPU(s) from Intel Core 0 to 1: CPUID: 306c3 Fam 06 Mod 3c Step 03 Flag 02 uCode 00000025 root@freebsd12:/usr/ports/sysutils/cpupdate #
To automatically update the microcode at startup, the following steps are required:
- Add in /boot/loader.conf:
cpuctl_load="YES"
- Add in /etc/rc.conf:
cpupdate_enable="YES"
- Do a rebot.
After the reboot cpupdate shows the new microcode version 0x25 on the example system:
root@freebsd12:~ # cpupdate -i Found CPU(s) from Intel Core 0 to 1: CPUID: 306c3 Fam 06 Mod 3c Step 03 Flag 02 uCode 00000025 root@freebsd12:~ #
Differences
When testing the two variants on 16.01.2018, it became apparent that the microcode of #Variant 1: Update via devcpu-data is loaded very early during the boot process.[7] Already at the first initialization of the CPU the four Structured Extended Features3 (IBPB,STIBP,L1DFL,SSBD) are recognized, which are provided by the microcode version 0x25. Here is the excerpt of the dmesg output:
Copyright (c) 1992-2018 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 12.0-RELEASE-p2 GENERIC amd64 FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1) VT(efifb): resolution 800x600 CPU: Intel(R) Celeron(R) CPU G1820T @ 2.40GHz (2394.52-MHz K8-class CPU) Origin="GenuineIntel" Id=0x306c3 Family=0x6 Model=0x3c Stepping=3 [...] Structured Extended Features3=0x9c000000<IBPB,STIBP,L1DFL,SSBD> [...] real memory = 2147483648 (2048 MB) avail memory = 2002632704 (1909 MB) CPU microcode: updated from 0x24 to 0x25
With the #Variant 2: Update via cpupdate two of the four Structured Extended Features 3 are missing at the beginning - therefore the older Microcode Version 0x24 is still in use at the beginning. This can be seen via dmesg:
Copyright (c) 1992-2018 The FreeBSD Project. [...] CPU: Intel(R) Celeron(R) CPU G1820T @ 2.40GHz (2394.52-MHz K8-class CPU) Origin="GenuineIntel" Id=0x306c3 Family=0x6 Model=0x3c Stepping=3 [...] Structured Extended Features3=0xc000000<IBPB,STIBP> [...] real memory = 2147483648 (2048 MB) [...] Trying to mount root from ufs:/dev/ada0p2 [rw]... CPU: Intel(R) Celeron(R) CPU G1820T @ 2.40GHz (2394.52-MHz K8-class CPU) Origin="GenuineIntel" Id=0x306c3 Family=0x6 Model=0x3c Stepping=3 [...] Structured Extended Features3=0x9c000000<IBPB,STIBP,L1DFL,SSBD>
With #Variant 2: Update via cpupdate it is also possible to load the microcode at the beginning. However, the exact microcode file of the CPU must be listed.[8] On the example system this is possible by the following entry in /boot/loader.conf:
cpu_microcode_load="YES" cpu_microcode_name="/usr/local/share/cpupdate/CPUMicrocodes/primary/Intel/06-3c-03"
References
- ↑ Introducing cpupdate, a microcode tool for FreeBSD (forums.freebsd.org, 09.02.2018)
- ↑ cpupdate (github.com)
- ↑ Bug 192487 - cpucontrol uses unsafe procedure to detect current microcode version (bugs.freebsd.org)
- ↑ cpupdate manpage draft (bsd.denkverbot.info, 19.03.2018)
- ↑ cpupdate (github.com) Please do not install via pkg. Please use ports or manually clone it with git.
- ↑ Absolute FreeBSD 3rd Edition Chapter 16, page 371: Ports and Production: I would strongly encourage you to build build your own package repository with poudriere and manage your servers' ports from that repository. Upgrading ports directly installed on a host is annoying and difficult. [...] You have been warned.
- ↑ D16370: Implement early microcode loading for Intel i386 and amd64 platforms (reviews.freebsd.org)
- ↑ Introducing cpupdate, a microcode tool for FreeBSD - Comment #16 (forums.freebsd.org, 16.01.2019)
Author: Werner Fischer Werner Fischer, working in the Knowledge Transfer team at Thomas-Krenn, completed his studies of Computer and Media Security at FH Hagenberg in Austria. He is a regular speaker at many conferences like LinuxTag, OSMC, OSDC, LinuxCon, and author for various IT magazines. In his spare time he enjoys playing the piano and training for a good result at the annual Linz marathon relay.
|