Microcode

From ArchWiki

This article or section needs expansion.

Reason: (Discuss in Talk:Microcode)

Processor manufacturers release stability and security updates to the processor microcode. These updates provide bug fixes that can be critical to the stability of your system. Without them, you may experience spurious crashes or unexpected system halts that can be difficult to track down.

All users with an AMD or Intel CPU should install the microcode updates to ensure system stability. In virtual machines and containers, the microcode updates belongs on the host, not in the guest system.

Loading microcode

Microcode updates are usually shipped with the motherboard's firmware and applied during firmware initialization. Since OEMs might not release firmware updates in a timely fashion and old systems do not get new firmware updates at all, the ability to apply CPU microcode updates during boot was added to the Linux kernel. The Linux microcode loader supports three loading methods:

  1. Built-in microcode can be compiled into the kernel and then applied by the early loader.
  2. Early loading updates the microcode very early during boot, before the initramfs stage, and is preferred over late loading. This is mandatory for CPUs with severe hardware bugs, like the Intel Haswell and Broadwell processor families.
  3. Late loading (dangerous) updates the microcode after booting which could be too late since the CPU might have already tried to use a faulty instruction. Even if already using early loading, late loading can still be used to apply a newer microcode update without needing to reboot.

To acquire updated microcode, depending on the processor, install one of the following packages:

Microcode built in the initramfs

This article or section needs expansion.

Reason:
  • This should have a change in structure splitting unified kernel images like the output of dracut or a manually/"voluntarily" generated one and the other images like the default configuration of Booster or mkinitcpio.
  • The introduction does not cover this section.
(Discuss in Talk:Microcode)

One can prepend the microcode cpio into the initramfs. Some initramfs generators, like dracut (see dracut.conf(5) § DESCRIPTION), do this by default. This makes #Early loading and #Late loading unnecessary. However, Arch Linux defaults to using mkinitcpio to generate its initial ramdisk (initramfs), which does not support this. It does, however, support loading the microcode via a UEFI stub: see #Unified kernel images.

Early loading

If not compiled into the kernel, microcode must be loaded by the early loader. It can be passed to the loader as part of a unified kernel image, or as an initrd image by your boot loader.

Note that because of the wide variability in users' early-boot configuration, microcode updates may not be triggered automatically by Arch's default configuration.

Unified kernel images

See Unified kernel images for guidance on how to include microcode in single-file images.

Initrd images

Microcode updates must otherwise be enabled by adding /boot/amd-ucode.img or /boot/intel-ucode.img as the first initrd in the bootloader configuration file. This is before the normal initrd file. See below for instructions for common bootloaders.

In the following sections replace cpu_manufacturer with your CPU manufacturer, i.e. amd or intel.

Tip: For Arch Linux on a removable drive, which could be run on any of these processors, install both packages and add both microcode files as initrd to the boot loader configuration. Their order does not matter as long as they both are specified before the initramfs image.
Enabling early microcode loading in custom kernels

In order for early loading to work in custom kernels, "CPU microcode loading support" needs to be compiled into the kernel, not compiled as a module. This will enable the "Early load microcode" prompt which should be set to Y.

CONFIG_BLK_DEV_INITRD=Y
CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=Y
CONFIG_MICROCODE_AMD=y
GRUB

grub-mkconfig will automatically detect the microcode update and configure GRUB appropriately. After installing the microcode package, regenerate the GRUB configuration to activate loading the microcode update by running:

# grub-mkconfig -o /boot/grub/grub.cfg

Alternatively, users that manage their GRUB configuration file manually can add /boot/cpu_manufacturer-ucode.img (or /cpu_manufacturer-ucode.img if /boot is a separate partition) as follows:

/boot/grub/grub.cfg
...
echo 'Loading initial ramdisk'
initrd	/boot/cpu_manufacturer-ucode.img /boot/initramfs-linux.img
...

Repeat it for each menu entry.

systemd-boot

Use the initrd option to load the microcode, before the initial ramdisk, as follows:

/boot/loader/entries/entry.conf
title   Arch Linux
linux   /vmlinuz-linux
initrd  /cpu_manufacturer-ucode.img
initrd  /initramfs-linux.img
...

The latest microcode cpu_manufacturer-ucode.img must be available at boot time in your EFI system partition (ESP). The ESP must be mounted as /boot in order to have the microcode updated every time amd-ucode or intel-ucode is updated. Otherwise, copy /boot/cpu_manufacturer-ucode.img to your ESP at every update of the microcode package.

EFISTUB

Append two initrd= options:

initrd=\cpu_manufacturer-ucode.img initrd=\initramfs-linux.img
rEFInd
Tip: Users who previously did not specify an initrd kernel parameter need to follow the steps described in rEFInd#Configuration to enable the passing of multiple initrd parameters.

Edit boot options in /boot/refind_linux.conf and add an initrd= option for the microcode image as the first initrd argument passed. Use either initrd=boot\cpu_manufacturer-ucode.img or initrd=cpu_manufacturer-ucode.img depending if the files in /boot are in the root of a separate partition.

The microcode is required to be the first initramfs declared for the boot options list. For example:

"Boot using default options"  "root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw add_efi_memmap initrd=boot\cpu_manufacturer-ucode.img initrd=boot\initramfs-%v.img"
Manual boot stanzas

Users employing manual stanzas in esp/EFI/refind/refind.conf to define kernels should add the initrd= parameter with the proper path within the boot partition. This parameter is required as part of the options line, and not in the main part of the stanza. E.g.:

options  "root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw add_efi_memmap initrd=boot\cpu_manufacturer-ucode.img"
Syslinux
Note: There must be no spaces between the cpu_manufacturer-ucode.img and initramfs-linux.img initrd files. The INITRD line must be exactly as illustrated below.

Multiple initrd's can be separated by commas in /boot/syslinux/syslinux.cfg:

LABEL arch
    MENU LABEL Arch Linux
    LINUX ../vmlinuz-linux
    INITRD ../cpu_manufacturer-ucode.img,../initramfs-linux.img
...
LILO

LILO and potentially other old bootloaders do not support multiple initrd images. In that case, cpu_manufacturer-ucode.img and initramfs-linux.img will have to be merged into one image.

Warning: The merged image must be recreated after each kernel update!
Note: The order is important. The original image initramfs-linux.img must be placed after cpu_manufacturer-ucode.img in the resulting image.

To merge both images into one image named initramfs-merged.img, the following command can be used:

# cat /boot/cpu_manufacturer-ucode.img /boot/initramfs-linux.img > /boot/initramfs-merged.img

Now, edit /etc/lilo.conf to load the new image.

...
initrd=/boot/initramfs-merged.img
...

And run lilo as root:

# lilo
Limine

For Limine you will just need to add the path to the microcode through the MODULE_PATH option in your limine.cfg file. Here is an example:

limine.cfg
DEFAULT_ENTRY=1
TIMEOUT=3

:Arch
    COMMENT=Arch Linux

    PROTOCOL=linux
    KERNEL_PATH=boot:///vmlinuz-linux
    CMDLINE=root=UUID=c0748521-eca9-4f38-989c-43811b6e39a1 rw loglevel=3
    MODULE_PATH=boot:///cpu_manufacturer-ucode.img
    MODULE_PATH=boot:///initramfs-linux.img

Late loading

Warning: Late microcode loading is considered dangerous, using it on Linux 5.19 and later will taint the kernel.[1]

Late loading of microcode updates happens after the system has booted. It uses files in /usr/lib/firmware/amd-ucode/ and /usr/lib/firmware/intel-ucode/.

Late loading requires the kernel to be built with CONFIG_MICROCODE_LATE_LOADING=y, which is not the case for Arch officially supported kernels at the moment. [2]

For AMD processors the microcode update files are provided by amd-ucode.

For Intel processors no package provides the microcode update files (FS#59841). To use late loading you need to manually extract intel-ucode/ from Intel's provided archive.

Late loading microcode updates

To manually reload the microcode, e.g. after updating the microcode files in /usr/lib/firmware/amd-ucode/ or /usr/lib/firmware/intel-ucode/, run:

# echo 1 > /sys/devices/system/cpu/microcode/reload

This allows to apply newer microcode updates without rebooting the system.

Verifying that microcode got updated on boot

Check the kernel messages with journalctl to see if the microcode has been updated:

# journalctl -k --grep=microcode

On Intel systems one should see something similar to the following on every boot, indicating that microcode is updated very early on:

kernel: microcode: Current revision: 0x00000012
kernel: microcode: Updated early from: 0x0000000e

It is entirely possible, particularly with newer hardware, that there is no microcode update for the CPU.

On AMD systems using early loading the output would look something like this:

kernel: microcode: CPU3: patch_level=0x0a20102b
kernel: microcode: CPU10: patch_level=0x0a20102b
...
kernel: microcode: Microcode Update Driver: v2.2.

On AMD systems using late loading the output will show the version of the old microcode before reloading the microcode and the new one once it is reloaded.

Which CPUs accept microcode updates

Users may consult either Intel own website or Gentoo's wiki on AMD at the following links to see if a particular model is supported:

Detecting available microcode update

It is possible to find out if the intel-ucode.img contains a microcode image for the running CPU with iucode-tool.

  1. Install intel-ucode (changing initrd is not required for detection)
  2. Install iucode-tool
  3. Load the cpuid kernel module:
    # modprobe cpuid
  4. Extract microcode image and search it for your cpuid:
    # bsdtar -Oxf /boot/intel-ucode.img | iucode_tool -tb -lS -
  5. If an update is available, it should show up below selected microcodes
  6. The microcode might already be in your vendor bios and not show up loading in dmesg. Compare to the current microcode running grep microcode /proc/cpuinfo

See also