Gentoo Linux: Building/rebuilding a kernel and Intel CPU microcode in an installation with initramfs
January 19, 2022 1 Comment
In a 2014 post I explained how to update the Intel CPU microcode in a Gentoo Linux installation with an initramfs (I use sys-kernel/genkernel
to build the kernel in the installation on my Compal NBLB2 laptop, which is running the Testing Branch of Gentoo Linux although the branch is not important). The initscript method (Method 1 in that post) for updating the CPU microcode is no longer valid, and the behaviour of the tool sys-apps/iucode_tool
for updating the CPU microcode (Method 2 in that post) has changed, hence this update.
Although not essential I normally perform the microcode upgrade procedure when I either rebuild or upgrade the Linux kernel, therefore I explain both procedures contiguously here.
These days the grub-mkconfig
command edits the file /boot/grub/grub.cfg
to add a line to the GRUB menu entries, to load the CPU microcode at boot, but nevertheless I prefer to follow a slightly different method that works reliably for me.
Below is the procedure I follow to build/rebuild the kernel and the Intel CPU microcode. Others may have a different approach, but this has always worked well for me, even if some of the steps are sometimes nugatory.
If they are not already installed, you need to merge a couple of packages before starting the main procedure:
root # emerge app-arch/lzma # Needed to build bzImage.
root # emerge iucode_tool
1. Mount the boot directory if it is on a separate partition
root # mount /dev/sda3 /boot
2. Check which kernel sources are installed and which of those sources is currently selected
root # eselect kernel list
3. Make a back-up configuration file for the current running kernel
root # zcat /proc/config.gz > /usr/src/config
4. Select the kernel sources I want to build
root # eselect kernel set <n>
5. Build the kernel image and the initramfs image
root # genkernel --kernel-config=/usr/src/config --clean --menuconfig --microcode=intel --no-splash --module-rebuild all
I have configured the following kernel options relating to the early loading of the Intel CPU microcode (see later):
root # grep CONFIG_BLK_DEV_INITRD /usr/src/linux/.config
CONFIG_BLK_DEV_INITRD=y
root # # grep CONFIG_MICROCODE /usr/src/linux/.config
CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=y
# CONFIG_MICROCODE_AMD is not set
# CONFIG_MICROCODE_OLD_INTERFACE is not set
# grep CONFIG_INITRAMFS_SOURCE /usr/src/linux/.config
CONFIG_INITRAMFS_SOURCE=""
6. Rebuild the X Windows Server and X Windows drivers
I always do this even though not always necessary. One less thing to think about (not rebuilding them has sometimes caused me problems).
root # emerge xorg-server xorg-drivers
7. Rebuild NetworkManager if it is installed
I always do this even though not always necessary. One less thing to think about (not rebuilding it has sometimes caused me problems).
root # emerge networkmanager
8. If there is a new version of the Intel CPU microcode, generate it and copy it to the boot directory
For several years updates to the package sys-kernel/linux-firmware have not resulted in a change to the version of Intel CPU microcode for the legacy Intel Core i7-720QM CPU in my Compal NBLB2 laptop, as Intel no longer supports that version of CPU. Nevertheless it does no harm to repeat the procedure.
root # emerge sys-firmware/intel-microcode
root # rm /boot/microcode.cpio
root # iucode_tool -S --write-earlyfw=/boot/microcode.cpio /lib/firmware/intel-ucode/*
root # rm /boot/intel-uc.img
(The fourth command is to stop the grub-mkconfig
command (see Step 9.2) adding intel-uc.img
to the initrd line in the grub.cfg
file.)
Note the USE flags for that I have set and cleared for sys-firmware/intel-microcode
:
root # equery uses intel-microcode
[ Legend : U - final flag setting for installation]
[ : I - package is installed with flag ]
[ Colors : set, unset ]
* Found these USE flags for sys-firmware/intel-microcode-20210608_p20210830:
U I
- - hostonly : only install ucode(s) supported by currently available (=online) processor(s)
- - initramfs : install a small initramfs for use with CONFIG_MICROCODE_EARLY
+ + split-ucode : install the split binary ucode files (used by the kernel directly)
- - vanilla : install only microcode updates from Intel's official microcode tarball
9. Create a new grub.cfg
file
9.1 First check the contents of /etc/default/grub
to make sure it will be OK for the new version of the kernel
root # nano /etc/default/grub
Modify the contents of /etc/default/grub
if necessary for the kernel version that has just been built.
9.2 Generate a new grub.cfg
file
root # grub-mkconfig -o /boot/grub/grub.cfg
9.3 Check the new grub.cfg
file includes the loading of the CPU microcode
root # nano /boot/grub/grub.cfg
The last line for each menu entry (i.e. the line before the closing curly bracket of the menu entry) should contain:
initrd /microcode.cpio /initramfs-<kernel version>-gentoo-x86_64.img
as shown in the example file excerpt below:
[...] ### BEGIN /etc/grub.d/10_linux ### menuentry 'Gentoo GNU/Linux' --class gentoo --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-9db2f668-a682-4d6f-abc5-ed6f6c515b95' { load_video set gfxpayload=1024x768 insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos3' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos3 --hint-efi=hd0,msdos3 --hint-baremetal=ahci0,msdos3 597e8c88-8d50-443f-ae19-f510844f5d4e else search --no-floppy --fs-uuid --set=root 597e8c88-8d50-443f-ae19-f510844f5d4e fi echo 'Loading Linux 5.15.0-gentoo-x86_64 ...' linux /vmlinuz-5.15.0-gentoo-x86_64 root=/dev/sda6 ro BOOT_IMAGE=/kernel-genkernel-x86_64-5.15.0-gentoo root=/dev/ram0 ramdisk=8192 real_root=/dev/sda6 init=/linuxrc resume=swap:/dev/sda5 real_resume=/dev/sda5 intel_iommu=off net.ifnames=0 snd_hda_intel.power_save=0 radeon.modeset=1 echo 'Loading initial ramdisk ...' initrd /microcode.cpio /initramfs-5.15.0-gentoo-x86_64.img } submenu 'Advanced options for Gentoo GNU/Linux' $menuentry_id_option 'gnulinux-advanced-9db2f668-a682-4d6f-abc5-ed6f6c515b95' { menuentry 'Gentoo GNU/Linux, with Linux 5.15.0-gentoo-x86_64' --class gentoo --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-gentoo-x86_64-advanced-9db2f668-a682-4d6f-abc5-ed6f6c515b95' { load_video set gfxpayload=1024x768 insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos3' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos3 --hint-efi=hd0,msdos3 --hint-baremetal=ahci0,msdos3 597e8c88-8d50-443f-ae19-f510844f5d4e else search --no-floppy --fs-uuid --set=root 597e8c88-8d50-443f-ae19-f510844f5d4e fi echo 'Loading Linux 5.15.0-gentoo-x86_64 ...' linux /vmlinuz-5.15.0-gentoo-x86_64 root=/dev/sda6 ro BOOT_IMAGE=/kernel-genkernel-x86_64-5.15.0-gentoo root=/dev/ram0 ramdisk=8192 real_root=/dev/sda6 init=/linuxrc resume=swap:/dev/sda5 real_resume=/dev/sda5 intel_iommu=off net.ifnames=0 snd_hda_intel.power_save=0 radeon.modeset=1 echo 'Loading initial ramdisk ...' initrd /microcode.cpio /initramfs-5.15.0-gentoo-x86_64.img } menuentry 'Gentoo GNU/Linux, with Linux 5.15.0-gentoo-x86_64 (recovery mode)' --class gentoo --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.0-gentoo-x86_64-recovery-9db2f668-a682-4d6f-abc5-ed6f6c515b95' { load_video set gfxpayload=1024x768 insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos3' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos3 --hint-efi=hd0,msdos3 --hint-baremetal=ahci0,msdos3 597e8c88-8d50-443f-ae19-f510844f5d4e else search --no-floppy --fs-uuid --set=root 597e8c88-8d50-443f-ae19-f510844f5d4e fi echo 'Loading Linux 5.15.0-gentoo-x86_64 ...' linux /vmlinuz-5.15.0-gentoo-x86_64 root=/dev/sda6 ro single BOOT_IMAGE=/kernel-genkernel-x86_64-5.15.0-gentoo root=/dev/ram0 ramdisk=8192 real_root=/dev/sda6 init=/linuxrc resume=swap:/dev/sda5 real_resume=/dev/sda5 intel_iommu=off net.ifnames=0 snd_hda_intel.power_save=0 radeon.modeset=1 echo 'Loading initial ramdisk ...' initrd /microcode.cpio /initramfs-5.15.0-gentoo-x86_64.img } } ### END /etc/grub.d/10_linux ### [...]
10. Reboot
11. Rebuild VirtualBox if it is installed
root # emerge virtualbox
12. Check the current version of the Intel CPU microcode
Either:
root # dmesg | grep microcode
or:
root # grep microcode /proc/cpuinfo
For example:
root # dmesg | grep microcode
[ 0.000000] microcode: microcode updated early to revision 0xa, date = 2018-05-08
[ 0.127937] MDS: Vulnerable: Clear CPU buffers attempted, no microcode
[ 1.558008] microcode: sig=0x106e5, pf=0x10, revision=0xa
[ 1.559335] microcode: Microcode Update Driver: v2.2.
root # grep microcode /proc/cpuinfo
microcode : 0xa
microcode : 0xa
microcode : 0xa
microcode : 0xa
microcode : 0xa
microcode : 0xa
microcode : 0xa
microcode : 0xa
Note from the output of the dmesg
command that this specific CPU model is susceptible to the MDS (Microarchitectural Data Sampling) vulnerability.
13. Edit /var/lib/portage/world
and add (or change) the specific kernel sources package version
I do this in order to ensure the command ‘emerge --depclean
‘ does not remove a specific kernel’s source code during a world update. I want Portage always to install the latest version of gentoo-sources
but not to delete the version of gentoo-sources
that corresponds to the kernel my installation is currently using.
For example, let’s say I have just replaced a kernel built from gentoo-sources:5.15.11
with a kernel built from gentoo-sources:5.15.12
. My world
file would initially contain the following:
[...] sys-kernel/gentoo-sources sys-kernel/gentoo-sources:5.15.11 [...]
If, following a successful reboot with kernel 5.15.12, I want to delete the files for kernel 5.15.11 in /boot/
(initramfs-5.15.11-gentoo-x86_64.img
, System.map-5.15.11-gentoo-x86_64
and vmlinuz-5.15.11-gentoo-x86_64
) and to edit the file /boot/grub/grub.cfg
to remove the menu entries for kernel 5.15.11, I would change the world
file’s contents to:
[...] sys-kernel/gentoo-sources sys-kernel/gentoo-sources:5.15.12 [...]
On the other hand, if, following a successful reboot, I want to keep the files for both kernel 5.15.11 and kernel 5.15.12, I would change the world
file’s contents to:
[...] sys-kernel/gentoo-sources sys-kernel/gentoo-sources:5.15.11 sys-kernel/gentoo-sources:5.15.12 [...]