Updating Intel CPU microcode from Gentoo Linux
November 6, 2014 3 Comments
Updates to CPU microcode have to be re-applied each time the computer is booted, because the memory updated is volatile (despite the term ‘firmware’ also being used for microcode). Below I describe two methods (there are others) of applying CPU microcode updates in Gentoo Linux. My main laptop has an Intel CPU so I focus here on Intel microcode updates. The procedure is almost the same for AMD CPUs, but the AMD CPU binary update file (‘binary blob’) is installed by the
METHOD 1: Use an initscript in the boot runlevel with a kernel module
Until recently I was using an initscript named
microcode_ctl, which uses a program (also named
microcode_ctl) and a kernel module (
microcode.ko) to update the Intel CPU microcode during boot. This was straightforward to set up in Gentoo Linux:
1. Build the kernel with
This is what I configured in the kernel:
2. Install two packages and add an OpenRC initscript to the boot runlevel:
The initscript will re-update the CPU microcode every time the computer is rebooted.
Installing the package
microcode-data downloads a compressed file (
microcode-yyyymmdd.tgz) from the Intel Download Centre, extracts a text file named
microcode.dat and parses the text in it to create a set of binary ‘blobs’ in the directory
/lib/firmware/intel-ucode/ (one blob for each model of Intel CPU).
Before rebooting, check the revision of microcode in the CPU (the microcode revision is shown for each logical core):
If I use this method of updating the microcode, the initscript runs after the message ‘
Waiting for uevents to be processed ...‘ is displayed on VT1 while booting. After the module has performed the update, the microcode revision in the CPU’s logical cores has changed:
Notice that the microcode update occurred in the period from 15.749533 to 15.840997 seconds after the kernel started running, and the microcode was updated from revision 0x3 to 0x7.
METHOD 2: Use the kernel’s built-in Early Update driver
Although the initscript method works perfectly in my case and the update is complete by the time the laptop has finished booting, I wanted to update the CPU microcode earlier. Updating microcode early can fix CPU issues before they occur during kernel boot time. It is possible to configure the kernel to update microcode early by setting
CONFIG_MICROCODE_INTEL_EARLY in the kernel. See
/usr/src/linux/Documentation/x86/early-microcode.txt for details. That document only refers to initrd files, but, in fact, it also applies to initramfs files.
The Early Update kernel driver will align misaligned microcode data (see Notes on Intel Microcode Updates and [PATCH 7/8] x86, microcode, intel: guard against misaligned microcode data), but you can pre-align the data yourself if you wish by using a
.padding file as explained on the latter page. However I did not bother doing that; I leave the Early Update kernel driver to take care of aligning the microcode, as the time penalty to align it is small compared to the overall update time.
It is possible to download the latest compressed Intel microcode data file yourself from the Intel Download Centre. The latest file released is
microcode-20140913.tgz at the time of writing. It contains only a text file named
microcode.dat, not the required binary blob. Actually,
microcode.dat contains data in text format for several Intel CPU models. The
microcode.dat file should reside in the directory
/lib/firmware/. In the case of Gentoo it is a waste of time manually obtaining the
microcode.dat file this way, as there is no tool in Gentoo specifically for creating a binary blob from the microcode.dat file. Therefore just install the Gentoo package
sys-apps/microcode-data (which you would have done in any case if you were using the
microcode_ctl initscript to load the microcode update to the CPU) and it will automatically download the compressed file from the Intel Web site, unpack it, copy the file
/lib/firmware/ and create the binary blobs in the directory
You may have read of a tool named
intel-microcode2ucode used in other Linux distributions. Gentoo does not build
intel-microcode2ucode (the source code of which is included in the Gentoo package
sys-apps/microcode-data) as a stand-alone tool, but the act of installing
microcode-data creates the required binary files in
/lib/firmware/intel-ucode/. i.e. the following command does the complete job:
Check that the microcode files for the various CPU models were created when
microcode-data was installed:
I looked in
/proc/cpuinfo to confirm the model of CPU in my laptop:
I was able to find the CPUID and other data for that model from the Web site CPU World:
|Family||6 (06 hex)|
|Model||30 (1E hex)|
|Stepping||5 (05 hex)|
Therefore the file
/lib/firmware/intel-ucode/06-1e-05 (Family–Model–Stepping in hexadecimal) is the binary blob for my specific CPU model.
First I used
genkernel to rebuild the current kernel with
This is what I have after rebuilding the kernel:
Then I prepended the cpio file containing the binary blob to the initramfs file (see the instructions in
Use the following commands to check if the CPU microcode has been updated:
There is no point looking in
syslog-ng has not started running when the early microcode update occurs.
Compare the update time in the
dmesg output above with the update time in the
dmesg output for an update done using the initscript (Method 1, further up). With the Early Update driver, the update was complete in 0.278696 seconds. With the initscript and kernel module, the update was complete in 15.840911 seconds. Quite a difference.
I do not know why the
dmesg output does not have a message for Core 0 in the group of messages before 1.000000 second elapsed. The message at 1.888471 shows it was updated, so I assume the kernel ring buffer was not large enough and the message was overwritten. Cores 1, 2 and 3 were updated in the period between 0.252234 and 0.278696 seconds, and then all eight logical cores are listed in the period between 1.888471 and 1.888597 seconds. I’m not sure of the precise messages expected, but they look similar to the results obtained by users in other distributions, such as the following CrunchBang Linux output:
Finally, I deleted the temporary work directory and files:
Of course, you will need to repeat the whole process and create a new concatenated initramfs file in any of the following cases:
a) you build a new version of the kernel;
b) you rebuild the current version of the kernel with different configuration settings;
c) Intel releases a new version of the microcode (which does not happen often).
It seems the Early Update driver still has some bugs, so I expect the message output to change in future kernel releases. See e.g. [PATCH 0/8] x86, microcode, intel: fixes and enhancements, [PATCH 3/8] x86, microcode, intel: clarify log messages, Re: [PATCH 3/8] x86, microcode, intel: clarify log messages and a bunch of other very recent posts in the kernel mailing list regarding the Early Update driver and CPU microcode updates.
UPDATE (September 1, 2015): Since I wrote the above post, the use of a kernel module and initscript to update CPU microcode has been dropped (in Gentoo Linux, at least). This is because updating CPU microcode relatively late in the boot process may cause problems if some processes have started before the update has taken place. The only safe way to update CPU microcode is to use the kernel’s built-in Microcode Early Update driver (METHOD 2 above). New versions of the relevant Gentoo Linux ebuilds (
iucode_tool-1.3) have recently been released (see Gentoo Bug Report No. 528712). If a Gentoo Linux installation does not use an initramfs, the
microcode-data ebuild now includes an ‘
initramfs‘ USE flag which you can set in order to create a minimal initramfs to load the CPU microcode at boot (see my latest post for details).