Intel microcode

From Gentoo Wiki
Jump to: navigation, search
This page contains changes which are not marked for translation.

Resources

This article describes the process of updating the microcode on Intel processors.

Installation

Note
The microcode-ctl utility has been deprecated as of version 1.28-r1(Gentoo unstable)[1] and no longer contains the init script. It also does not work on certain CPUs such as Intel Haswells, you should switch to the "Early microcode" method explained directly below. If however you wish to continue using microcode-ctl please skip to the "Microcode-ctl" section near the bottom of this page.

Kernel

You need to activate the following kernel options:

KERNEL Enable CONFIG_BLK_DEV_INITRD, CONFIG_MICROCODE, and CONFIG_MICROCODE_INTEL
General setup  --->
    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
Processor type and features  --->
    <*> CPU microcode loading support
    [*]   Intel microcode loading support
Note
Modules don't work for early microcode, so make sure microcode loading is built-in.

Software

You can now install the microcode sys-firmware/intel-microcode

root #emerge --ask sys-firmware/intel-microcode

And a tool to manipulate it sys-apps/iucode_tool

root #emerge --ask sys-apps/iucode_tool

Configuration

After emerging sys-firmware/intel-microcode, generate the microcode cpio archive using sys-apps/iucode_tool:

root #iucode_tool -S --write-earlyfw=/boot/early_ucode.cpio /lib/firmware/intel-ucode/*
iucode_tool: system has processor(s) with signature 0x000306c3
iucode_tool: Writing selected microcodes to: /boot/early_ucode.cpio

GRUB Legacy

Add the generated microcode to your kernel command line as an initrd parameter (this should be done even if you don't use an initrd image in order to boot, the microcode update merely leverages the initrd hooks):

FILE /boot/grub/grub.conf
title Gentoo Linux 4.4.6
root (hd0,0)
kernel /boot/vmlinuz-4.4.6-gentoo root=/dev/sda3
initrd early_ucode.cpio

GRUB

Change this small section of /etc/grub.d/10_linux from:

FILE /etc/grub.d/10_linuxBefore
initrd=
  for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
           "initrd-${version}" "initramfs-${version}.img" \
           "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
           "initrd-${alt_version}" "initramfs-${alt_version}.img" \
           "initramfs-genkernel-${version}" \
           "initramfs-genkernel-${alt_version}" \
           "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
           "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
    if test -e "${dirname}/${i}" ; then
      initrd="$i"
      break
    fi
  done

To this:

FILE /etc/grub.d/10_linuxAfter
initrd=
  for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
           "initrd-${version}" "initramfs-${version}.img" \
           "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
           "initrd-${alt_version}" "initramfs-${alt_version}.img" \
           "initramfs-genkernel-${version}" \
           "initramfs-genkernel-${alt_version}" \
           "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
           "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
    if test -e "${dirname}/${i}" ; then
      initrd="early_ucode.cpio ${rel_dirname}/${i}"
      break
    else
      initrd="early_ucode.cpio"
    fi
  done
Note
This is the most pain-free method I've found to load the microcode, works with or without an initramfs.
Warning
If you were not using an initrd before, make sure to specify the root partition by name instead of UUID. The root partition name can be specified directly in GRUB menu or by editing grub.cfg

Regenerate the grub.cfg with:

root #grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.6.3-gentoo
Found initrd image: /boot/early_ucode.cpio /initramfs-genkernel-x86_64-4.6.3-gentoo
done
Note
This is similar to what you should see, minus the initramfs if you do not have one.

Reboot and you're all done.

Verification

Here is an example of a CPU with no available microcode updates or the system was not configured to load them properly:

root #dmesg | grep microcode
[    1.196567] microcode: CPU0 sig=0x6fd, pf=0x80, revision=0xa3
[    1.196575] microcode: CPU1 sig=0x6fd, pf=0x80, revision=0xa3
[    1.196623] microcode: Microcode Update Driver: v2.01 <tigran@aivazian.fsnet.co.uk>, Peter Oruba

Here is the same CPU but with microcode updates being applied successfully:

root #dmesg | grep microcode
[    0.000000] microcode: microcode updated early to revision 0xa4, date = 2010-10-02
[    1.207385] microcode: CPU0 sig=0x6fd, pf=0x80, revision=0xa4
[    1.207393] microcode: CPU1 sig=0x6fd, pf=0x80, revision=0xa4
[    1.207445] microcode: Microcode Update Driver: v2.01 <tigran@aivazian.fsnet.co.uk>, Peter Oruba

Microcode-ctl

Note
The microcode-ctl utility has been deprecated as of 1.28-r1 (Gentoo unstable) and will no longer contain the init script. It also does not work on certain CPUs such as Intel Haswells, the information below this point is only relevant to microcode-ctl users.

Kernel

Activate the following kernel options:

KERNEL Enable CONFIG_MICROCODE and CONFIG_MICROCODE_INTEL
Processor type and features  --->
    <M> CPU microcode loading support
    [*]   Intel microcode loading support
Note
If you build it as module, it will automatically get loaded as needed and then unloaded after microcode update saving some memory.

Software

Install sys-apps/microcode-ctl:

root #emerge --ask sys-apps/microcode-ctl

OpenRC

Start microcode-ctl:

root #/etc/init.d/microcode_ctl start

To start microcode-ctl at boot time, add it your boot runlevel:

root #rc-update add microcode_ctl boot
Note
Using boot runlevel ensures the CPU is updated as soon as possible.

systemd

See: Systemd. Simply make sure that the Microcode loader is set as a module in the kernel configuration as noted above. You don't need to add a service or do anything else.

New method without initram-fs/disk

Note
This method should be preferable, especially for EFI-Stub systems (some motherboard firmware might have issues with parsing/passing custom boot command line options), since these changes are less likely to leave your system unbootable (and possibly unrepairable without an EFI compatible rescue disk which can be very tricky on headless machines) the way a broken firmware boot entry and/or incorrect initram-fs/disk would, while it also works on BIOS systems or EFI systems with custom bootloaders on disk. However, this requires a relatively recent kernel version (possibly unstable at the time of writing). It was tested with Linux 4.8.0

Software

You can install the officially published microcode package and let it automatically processed by sys-firmware/intel-microcode

root #emerge --ask sys-firmware/intel-microcode
Note
Save the output of this command or make sure it's logged in a file you can find and access (you will need that long list of microcode files with their matching signatures in the next step).

And you can use this tool to identify your actual CPU signature(s) sys-apps/iucode_tool

root #emerge --ask sys-apps/iucode_tool
root #iucode_tool -S
iucode_tool: system has processor(s) with signature 0x000306c3

To find the appropriate filename(s) for the listed signature(s) use:

root #iucode_tool -S -l /lib/firmware/intel-ucode/*
iucode_tool: system has processor(s) with signature 0x000306c3
[...]
microcode bundle 49: /lib/firmware/intel-ucode/06-3c-03
[...]
selected microcodes:
  049/001: sig 0x000306c3, pf_mask 0x32, 2017-01-27, rev 0x0022, size 22528

The signature found in the microcode bundle 49, so the filename to use is intel-ucode/06-3c-03

Kernel

You need tho enable and configure the following kernel options:

KERNEL Enable CONFIG_MICROCODE, CONFIG_MICROCODE_INTEL, and CONFIG_FIRMWARE_IN_KERNEL
Processor type and features  --->
    <*> CPU microcode loading support
    [*]   Intel microcode loading support

Device Drivers  --->
  Generic Driver Options  --->
    [*]   Include in-kernel firmware blobs in kernel binary
    (intel-ucode/06-3c-03) External firmware blobs to build into the kernel binary
    (/lib/firmware/) Firmware blobs root directory
Note
These should be built-in, not loadable external modules and the filename and directory needs to be set according to where you placed the microcode file(s) for your specific CPU(s). In this example (for a i7-4790K CPU), the relevant filename was 06-3c-03 (the location was the system default) for the signature 0x000306c3.

Rebuild and install the kernel as normal.

Verification

After the next reboot, you should see something like this:

root #dmesg | grep microcode
[    0.000000] microcode: microcode updated early to revision 0x22, date = 2017-01-27
[    1.153262] microcode: sig=0x306c3, pf=0x2, revision=0x22
[    1.153815] microcode: Microcode Update Driver: v2.2.
Note
Note how this is the very fist step the kernel logs now.
Note
Be aware that injecting the microcode update directly into the motherboard firmware (which might sounds tempting) might result in CPU0 being updated but the rest of the CPUs (or CPU cores in a multi-core system) being left at their initial revision (which might cause more problems than running them all at the same initial version). And, since most stock motherboard firmware has some microcode updates (even in their initial release versions), it's probably a good enough reason for everybody to make sure their kernel tries to update all CPUs (and cores) to the same version (so, let this update driver running even if the kernel has the same version which is stored in the motherboard firmware). Injecting the microcode into the firmware might be desirable still (to make sure it's loaded for the boot CPU before the kernel is loaded and able to update the rest of the microcode).

See also

  • Intel — the open source graphics driver for Intel GMA on-board graphics cards, starting with the Intel 810.

External resources

References

  1. https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=719cc5ef240b766953ddbe1e7a6593f8091eed12 The microcode-ctl utility has been deprecated as of version 1.28-r1(Gentoo unstable) and no longer contains the init script. It also does not work on certain CPUs such as Intel Haswells.