Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for early microcode loading #18

Open
reanimus opened this issue Jan 12, 2018 · 8 comments
Open

Support for early microcode loading #18

reanimus opened this issue Jan 12, 2018 · 8 comments
Labels

Comments

@reanimus
Copy link

So, I use buildkernel as part of your EFI guide, as I'm sure many others do.

I was looking to enable early microcode updates for my system in order to patch it for recent CPU vulnerabilities. The usual way of doing this is one of three methods:

  1. Load the microcode archive before initrd from bootloader (not applicable; EFI stub)
  2. Append the initrd to the microcode archive (buildkernel doesn't support this, as it builds and appends it internally)
  3. Include the microcode binaries directly in the kernel via CONFIG_EXTRA_FIRMWARE.

I'm currently including it in the kernel via method 3 in buildkernel.conf.

user_conform_config_file() {
    FW=$(ls -xw0 /lib/firmware/intel-ucode/ | sed -r 's/([^ ]+)\s*/intel-ucode\/\1 /g')
    set_kernel_config "EXTRA_FIRMWARE" "\"${FW}\""
}

This will stick the contents of the intel-ucode directory into the list of firmware in the kernel. This works, but it's a bit clunky considering gentoo offers the ability for intel-ucode to produce a cpio archive at /lib/firmware/microcode.cpio that includes the microcode for you. If buildkernel could pick this up and create the appropriate conjoined image, that would be nice. Alternatively, including the support for AMD and Intel microcode updates in buildkernel would be good in general in light of CPU-level issues like this.

@sakaki-
Copy link
Owner

sakaki- commented Jan 12, 2018

I use method 3 myself, it comes to the same thing anyway as the
initramfs ends up bundled in the kernel (so both can be covered by a
single secure-boot signature).

However, if you have a chance, perhaps you could try adding the
following in your /etc/buildkernel.conf:

user_modify_initramfs() {
    # do stuff with ${INITRAMFSDIR} directory contents;
    # the cpio archive is already unpacked here upon function entry
    # and will be repacked again automatically for you afterwards

    mkdir -p "${INITRAMFSDIR}/lib/firmware"
    cp -r "/lib/firmware/intel-ucode" "${INITRAMFSDIR}/lib/firmware/"
    # prune firmware in ${INITRAMFSDIR}/lib/firmware/ if desired
    # (but full archive isn't very large, so this is optional)
}

With CONFIG_MICROCODE and CONFIG_MICROCODE_INTEL set, does this work on
your system?

If so, it'd be relatively straightforward to add this (force-set of uc
options + initramfs append) to the main code, controlled by an option...
I'd be happy to accept a PR to this effect ^-^

@reanimus
Copy link
Author

Nope. The microcode has a special process for loading that's done in very early kernel init, at a fixed location. The details are located at https://www.kernel.org/doc/Documentation/x86/early-microcode.txt

"The following example script shows how to generate a new combined initrd file in /boot/initrd-3.5.0.ucode.img with original microcode microcode.bin and original initrd image /boot/initrd-3.5.0.img."

mkdir initrd
cd initrd
mkdir -p kernel/x86/microcode
cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
find . | cpio -o -H newc >../ucode.cpio
cd ..
cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img

I thought it could be stuck into that location as part of the initrd rolled together by buildkernel, but it seems that the kernel specifically expects a separate cpio archive, either prepended to the initramfs cpio archive directly or simply loaded before the initramfs.

@sakaki-
Copy link
Owner

sakaki- commented Jan 13, 2018

OK, that's interesting info, thanks.
I'll look into adding an option to create the cpio and prepend it, in that case.

@alex-serbsky
Copy link

I'll look into adding an option to create the cpio and prepend it, in that case.

I think cpio prepend is not needed. I use this approach:

  1. emerge sys-firmware/intel-microcode with "+split-ucode -initramfs" USE flags.

  2. Add this to kernel config via menuconfig:
    CONFIG_MICROCODE=y
    CONFIG_MICROCODE_INTEL=y
    CONFIG_MICROCODE_OLD_INTERFACE=y
    CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3c-03"
    CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"

  3. In buildkernel.conf, set:
    ADDITIONALGENKERNELOPTS="--all-ramdisk-modules --firmware"

  4. Run buildkernel. Then reboot and ensure microcode is loaded properly:
    $ dmesg | grep -i "updated early"
    [ 0.000000] microcode: microcode updated early to revision 0x23, date = 2017-11-20

@sakaki-
Copy link
Owner

sakaki- commented Jan 13, 2018

@alex-serbsky, this approach does indeed work and is the 'method 3' mentioned by @reanimus above (and I currently use it).

The only (minor) issue is the need to set CONFIG_EXTRA_FIRMWARE correctly via a grep, whereas with the cpio approach, you can directly build the cpio with just the necessary components, via iucode_tool -S --write-earlyfw=<install_path>/early_ucode.cpio /lib/firmware/intel-ucode/* per the wiki (or force the initramfs USE flag to sys-firmware/intel-microcode, which does basically the same thing).

@VTimofeenko
Copy link

For somebody stumbling upon this from search:

I'll look into adding an option to create the cpio and prepend it, in that case.

I think cpio prepend is not needed. I use this approach:

1. emerge sys-firmware/intel-microcode with "+split-ucode -initramfs" USE flags.

2. Add this to kernel config via menuconfig:
   CONFIG_MICROCODE=y
   CONFIG_MICROCODE_INTEL=y
   CONFIG_MICROCODE_OLD_INTERFACE=y
   CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3c-03"
   CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"

3. In buildkernel.conf, set:
   ADDITIONALGENKERNELOPTS="--all-ramdisk-modules --firmware"

4. Run buildkernel. Then reboot and ensure microcode is loaded properly:
   $ dmesg | grep -i "updated early"
   [    0.000000] microcode: microcode updated early to revision 0x23, date = 2017-11-20

To determine the exact value needed for CONFIG_EXTRA_FIRMWARE, run the iucode_tool -S -l /lib/firmware/intel-ucode/* from that wiki article

_microcode=$(iucode_tool -S -l /lib/firmware/intel-ucode/* 2>&1 | tail -n1 | sed 's/\/[0-9].*$//' | awk '{print $1}'); iucode_tool -S -l /lib/firmware/intel-ucode/* 2>&1 | grep " bundle ${_microcode}"

@sarnold
Copy link

sarnold commented May 13, 2020

This is basically my 3rd-priority update problem-of-the-day, and for a minute I thought genkernel would handle it but support does not seem to exist in genkernel-next-70 (only in sys-kernel/genkernel-3.5.0.7 and up according to the wiki page). I was just about to file a different buildkernel issue (you're welcome ;) but since I can no longer build my kernel easily I was hoping for some clarity here, since I have way too many machines/arch builds to fiddle with this manually every time I touch a kernel build (also I just got the exact answer I did not want in #toolchain...)

So, did you decide on a fix for this one yet?

@sakaki- sakaki- added the EOL label Oct 31, 2020
@sakaki-
Copy link
Owner

sakaki- commented Oct 31, 2020

31 Oct 2020: sadly, due to legal obligations arising from a recent change in my 'real world' job, I must announce I am standing down as maintainer of this project with immediate effect. For the meantime, I will leave the repo up (for historical interest, and it may be of use to others); however, I plan no further updates, nor will I be accepting / actioning further pull requests or bug reports from this point. Email requests for support will also have to be politely declined, so, please treat this as an effective EOL notice.

For further details, please see my post here.

With sincere apologies, sakaki ><

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants