Loading Microcode from the OS

ID 758406
Updated 5/21/2020
Version Latest
Public

author-image

By

Linux* administrators have several different options and methods to update their Intel systems’ microcode. We discuss details about these methods and provide multiple examples to help you choose the best option for your environment.

The Linux command line examples in this article start with either the $ (dollar symbol) to indicate the command can be run as a normal, non-privileged user, or the # (hash symbol) to indicate that the command must be run as a privileged user (root). Comments next to the example commands will start with a // (double forward slash symbol).

The Importance of Updating Microcode

Some of the uses of microcode updates (MCUs) are to mitigate potential CPU security vulnerabilities and improve system security. Many operating system (OS) vendors provide automatic MCUs. OS vendors distribute microcode update in a form of packages. The packages are signed with OS vendor identity to help ensure integrity and authority of origin of the MCU. You should follow the instructions provided by your OS vendor to install MCUs. To learn more, refer to the Guidance for System Administrators to Mitigate Transient Execution Side Channel Issues.

Before installing critical files from the internet, such files should pass checksum match and identity verification. Instructions provided here should not be used in a production setup, as use in a production setup could result in a system being unmaintainable at scale and more vulnerable than before.

Microcode Loading Points

The system can load MCUs from multiple points. Refer to the Microcode Update Guidance for more details on the following loading points:

  1. FIT (Firmware Interface Table) Microcode Update. FIT is a data structure placed in the platform BIOS SPI flash that can hold pointers to MCUs. If a suitable update is found (an MCU that matches the CPU’s processor signature and platform ID), then the processor loads the MCU before the first instruction of the BIOS firmware is fetched. FIT MCU is the preferred method to load MCUs for Intel platforms, because it helps to ensure the update components are loaded at the earliest point in the boot process.
  2. Early BIOS Microcode Update. Early BIOS MCU occurs when a microcode update is loaded by the BIOS before memory initialization. If an update has already been loaded via the FIT, BIOS may skip this microcode update.
  3. Late BIOS Microcode Update. Sometimes, enabling certain architectural components require a late BIOS microcode update. To enable these architectural features, all logical processors must execute a late BIOS MCU, even if the same microcode has already been loaded from the FIT or during early BIOS. If that happens, late BIOS must reload the same update that was loaded previously. If the reload fails, the architectural features enabled by the late BIOS MCU might not be available on the system.
  4. Early OS Microcode Update. The OS will check the /lib/firmware/intel-ucode folder for a more recent microcode (higher update revision) than the microcode used by the BIOS. If a higher update revision exists in that folder, the OS should load that MCU right after BIOS hands off control to the operation system. This can be done by UEFI driver, a bootloader, the OS, or an early startup script.
  5. Runtime Microcode Update. Runtime microcode update refers to loading an update while the system is fully operational and running workloads, possibly including user-space applications and virtual machines. The same update should be loaded on all cores.

By updating the BIOS to include a newer (or older) MCU, the system administrator can upgrade (or downgrade) the MCU that is loaded when the system boots. Loading the microcode package as early as possible during boot time (via FIT or Early BIOS) increases the potential to effectively apply the mitigations implemented in the microcode and helps prevent later BIOS issues (for example, BIOS Memory Reference Code). However, a BIOS update requires a reboot. Updating microcode through BIOS might be the only approach on certain systems. Check with your vendor for options available on your system.

Intel Microcode Repository

Intel regularly publishes new microcode for its products to the Intel Microcode Repository in GitHub* so any user can download it. Usually these updates are located under /lib/firmware directory. This directory contains microcodes for all available Intel CPUs, listed by CPU signature (Family-Model-Stepping). During boot, the OS looks into /lib/firmware/intel-ucode for a microcode associated with a given system CPU. To find which CPU signature is associated with your processor, follow the steps in the next sections.

Decoding CPU Family-Model-Stepping

Family-Model-Stepping is a processor signature that identifies the model and version of the processor, and is needed during the microcode installation process. The CPU signature has three fields (family, model, and stepping) separated by dashes (-) and is represented in a hexadecimal form. There are multiple ways you can determine a given processor’s Family-Model-Stepping in Linux:

  • The cpuid command
  • The lscpu command
  • From /proc/cpuinfo

The following example demystifies Family-Model-Stepping by using the lscpu instruction.

  1. $ lscpu // look for Family/Model/Stepping
    CPU family:            6
    Model:                 85
    Stepping:              4
  2. Convert decimal to hex:
    $ printf "%x\n" 6      // output: 6
    $ printf "%x\n" 85    // output: 55
    $ printf "%x\n" 4      // output:4
  3. Concatenate those three values into a single signature.

In the above example, the system has the 06-55-04 (Family-Model-Stepping) CPUID signature.

Installing Microcode on Linux

There are multiple methods to load microcode. Some of them require system reboot, others don’t. Some of them can only be applied to upgrade the microcode, while others allow you to both downgrade and upgrade your current microcode. Some of them will work regardless of your Linux distribution, and some are distribution specific.

Early OS Microcode Update

Early OS MCU requires a reboot for all features to go into effect. Early OS MCU allows you to both upgrade and downgrade your microcode as needed. However, the CPU may prevent loading an MCU with a Revision ID lower than what was loaded by BIOS. This section describes the steps for Early OS MCU in some popular distributions. Different distributions will follow different methods, so you should check with your OS vendor before proceeding.

Before going forward, we need to explain the role initramfs plays during microcode installation. In a nutshell, initramfs is a files archive. The main job of the initramfs is to mount the root filesystem during kernel boot. During boot time, the boot loader loads the initramfs image and kernel into ramfs memory. After that, the boot loader initiates the kernel, and the kernel looks for initramfs. If found, the kernel will mount it as / and initiate the init program (first process of the computer system).

Ubuntu*

  1. Check if the /lib/firmware/intel-ucode directory exists. Create it if it doesn’t: 
    # mkdir -p /lib/firmware/intel-ucode
  2. If exists, backup the old microcode: 
    # rsync -av /lib/firmware/intel-ucode /lib/firmware/intel-ucode.bak
  3. Download the microcode for your CPU from the Intel microcode repository in GitHub.
    You can do this either by clicking on the Download button as shown in Figure 1 below, or right clicking on the Download button, selecting Copy link address, and then running: 
    # wget <copied_link>:
    # wget https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/raw/main/intel-ucode/06-03-02

    Intel Microcode Repository

    Figure 1. Intel Microcode Repository

  4. Move copied CPU microcode to /lib/firmware directory.
    # mv 06-03-02 /lib/firmware/intel-ucode  
    # cd /lib/firmware/intel-ucode
  5. Put the new microcode in /lib/firmware/intel-ucode.
    1. If a microcode with the same CPU Family-Model-Stepping already exists in /lib/firmware/intel-ucode, you must remove the old, existing microcode before adding the new microcode to the directory. In the example below we remove the 06-55-04 microcode signature. 
      # rm -fr /lib/firmware/intel-ucode/family-model-stepping // e.g. rm -fr 06-55-04
    2. Then copy the microcode you previously downloaded to the folder.
      # cp family-model-stepping /lib/firmware/intel-ucode/    
      // e.g. cp 06-55-04 /lib/firmware/intel-ucode/
    3. An alternative to step 5 is update-initramfs (assuming the desired microcode is already under /lib/firmware/intel-ucode).
      # update-initramfs -c -k $(uname -r) 
      # reboot
  6. Remove the existing kernel, the one you want to update the microcode with. You cannot update the kernel you are currently using. If not needed, you can skip this step.
    1. List all of the kernels that are currently installed on the system: 
      # dpkg --list | grep linux-image
    2. Uninstall the kernel that you want microcode to operate on. Substitute linux-image-<kernel version> with one from the above list of currently installed kernels. 
      # sudo apt-get remove linux-image-
  7. Reinstall the kernel package. That way during the next reboot the kernel will install the new microcode in the initramfs. Refer to the upstream kernel files from the Ubuntu* archives (sorted by the most recent build). Substitute linux-image-<kernel version>.deb with the one downloaded from this link. 
    # apt install ./linux-image-.deb
  8. Reboot the system to let changes take effect. 
    # reboot

On Ubuntu you can also use the update-intel-microcode tool. Update-intel-microcode is a script that downloads the current microcode for Intel processors and installs it on the filesystem.

Red Hat*, Fedora* and OpenSUSE*

For Red Hat* or Fedora*, use the dracut utility. If this tool is not available on your system, there are two ways to install it:

  1. Using yum: 
    # yum install dracut
  2. Installing it from source:
    $ wget https://mirrors.edge.kernel.org/pub/linux/utils/boot/dracut/dracut-(latest_version).tar.gz
    $ tar xf dracut-(latest_version).tar.gz // e.g. tar xf dracut-050.tar.gz
    $ cd dracut-(latest_version) // cd dracut-050
    $ make
    $ su
    # make install sbindir=/sbin sysconfdir=/etc
  3. Using the RPM package:
    Go to the Fedora dracut download directory. Click on the suitable version. It will redirect you to another window where RPM packages for that specific version are located. To download and install RPM packages use wget and yum install commands, as shown in the example below:
    # wget https://harald.fedorapeople.org/downloads/dracut/dracut-029-15.git20130705.fc19/dracut-029-15.git20130705.fc19.x86_64.rpm
    # rpm -U dracut-029-15.git20130705.fc19.x86_64.rpm

Note Depending on your system, you might need to install additional packages from the dracut homepage.

Once you have dracut installed, use the steps below to install the microcode using dracut:

  1. Download the microcode for your CPU from the Intel microcode repository in GitHub.
  2. Check if the /lib/firmware/intel-ucode directory exists. Create it if it doesn’t using the following commands:
    # mkdir /lib/firmware/intel-ucode
    # cd /lib/firmware/intel-ucode
  3. Backup the old microcode: 
    # rsync -av /lib/firmware/intel-ucode /lib/firmware/intel-ucode.bak
  4. Put the new microcode in /lib/firmware/intel-ucode.
    1. If a microcode with the same CPU Family-Model-Stepping already exists in /lib/firmware/intel-ucode, you must remove the old, existing microcode before adding the new microcode to the directory. In the example below we remove the 06-55-04 microcode signature: 
      # rm -fr /lib/firmware/intel-ucode/family-model-stepping // e.g. rm -fr 06-55-04
    2. Then we copy the microcode you previously downloaded to the folder:
      # cp family-model-stepping /lib/firmware/intel-ucode/    
      // e.g. cp 06-55-04 /lib/firmware/intel-ucode/
  5. Build new initramfs for the currently running kernel: 
    # dracut -f "initramfs-$(uname -r).img" $(uname -r) // -f to overwrite an existing image
  6. Since microcode is loaded early by the initramfs, rebuild it with the following command: 
    # dracut -f -vvv
  7. You need to reboot the system to let changes take effect: 
    # reboot

Runtime OS MCU (reboot not needed)

The method described here works for upgrading microcode only. It will not work for downgrading microcode. This method is agnostic to your Linux distribution. Loading an MCU during OS runtime must be done with care. Loading an update during runtime may change the CPU behavior in ways that is incompatible with running software. Furthermore, some updates may not be fully effective when loaded during runtime. To make sure CPU features are working properly, the same update should be loaded on all cores.

Therefore, Intel recommends that the system should be quiesced to the maximum extent possible when loading an MCU during runtime.

  1. Download the microcode for your CPU from the Intel microcode repository in GitHub.
  2. Check if /lib/firmware/intel-ucode exists. Create it if it doesn’t:
    # mkdir /lib/firmware/intel-ucode
    # cd /lib/firmware/intel-ucode
  3. Backup the old microcode: 
    # rsync -av /lib/firmware/intel-ucode /lib/firmware/intel-ucode.bak
  4. Put the new microcode in /lib/firmware/intel-ucode.
    1. If prior to putting a new microcode, there is already a microcode with the same CPU Family-Model-Stepping, first you will need to remove that existing microcode before putting a new one. In below example we will be removing 06-55-04 microcode signature: 
      # rm -fr /lib/firmware/intel-ucode/family-model-stepping // e.g. rm -fr 06-55-04
    2. Copy the microcode you previously downloaded to the folder:
      # cp family-model-stepping /lib/firmware/intel-ucode/    
      // e.g. cp 06-55-04 /lib/firmware/intel-ucode/
  5. Reload the microcode. Reloading applies the microcode update without needing to reboot the system. Reload will trigger a microcode refresh action.
    1. Use this command for Linux v3.6 and later: 
      echo 1 > /sys/devices/system/cpu/microcode/reload
    2. Use this command for Linux v3.5 and earlier. (Note: this script will work for bash; you might need to change depending on your shell).
      #!/bin/bash
      for i in /sys/devices/system/cpu/cpu[0-9]*/microcode/reload ; do 
      echo 1 2>/dev/null > "$i" || true
      done
      

Microcode Update Verification

To verify if a microcode update was loaded correctly, check the microcode version before and after updating your system. You can use any of the following ways to check the current version of your microcode:

  • Check for microcode revision:
    $ dmesg | grep microcode
    [    0.000000] microcode: microcode updated early to revision 0xd2, date = 2020-01-09
    [    3.200591] microcode: sig=0x906ed, pf=0x2, revision=0xd2
    [    3.207755] microcode: Microcode Update Driver: v2.2.
  • Display active microcode version:
    $ cat /proc/cpuinfo | grep microcode | sort | uniq
    microcode       : 0xd2
  • The iucode_tool can be used by any Linux distro. Refer to the instructions for how to download and install this tool. iucode_tool scans your system and looks for information about your CPU signature. The value you are looking for is the output column that starts with rev (in bold below). In this example, 06-9e-0d is the signature of the processor currently running on the system.
    $ iucode_tool -l /lib/firmware/intel-ucode/06-9e-0d
            selected microcodes:
            001: sig 0x000906ed, pf mask 0x22, 2020-01-09, rev 0x00d2, size 102400
  • You can check the version of a microcode file by using the od command. This command will display a long output, with the value that contains the microcode version in the third column of the first line of that output (000000d2 in the example below). We query the file 06-9e-0d, located in the folder in which we run the od command.
    $ od -t x4 /lib/firmware/intel-ucode/06-9e-0d
            0000000 00000001 000000d2 01092020 000906ed
  • You might be able to find information about the current microcode version in your system BIOS. Depending on the motherboard, the microcode revision can be found under Platform Information, CPU Information, or Main Menu.

More Information

 

Software Security Guidance Home | Advisory Guidance | Technical Documentation | Best Practices | Resources