Borislav Petkov | 0e32587 | 2017-07-24 12:12:27 +0200 | [diff] [blame] | 1 | The Linux Microcode Loader |
| 2 | |
| 3 | Authors: Fenghua Yu <fenghua.yu@intel.com> |
| 4 | Borislav Petkov <bp@suse.de> |
| 5 | |
| 6 | The kernel has a x86 microcode loading facility which is supposed to |
| 7 | provide microcode loading methods in the OS. Potential use cases are |
| 8 | updating the microcode on platforms beyond the OEM End-Of-Life support, |
| 9 | and updating the microcode on long-running systems without rebooting. |
| 10 | |
| 11 | The loader supports three loading methods: |
| 12 | |
| 13 | 1. Early load microcode |
| 14 | ======================= |
| 15 | |
| 16 | The kernel can update microcode very early during boot. Loading |
| 17 | microcode early can fix CPU issues before they are observed during |
| 18 | kernel boot time. |
| 19 | |
| 20 | The microcode is stored in an initrd file. During boot, it is read from |
| 21 | it and loaded into the CPU cores. |
| 22 | |
| 23 | The format of the combined initrd image is microcode in (uncompressed) |
| 24 | cpio format followed by the (possibly compressed) initrd image. The |
| 25 | loader parses the combined initrd image during boot. |
| 26 | |
| 27 | The microcode files in cpio name space are: |
| 28 | |
| 29 | on Intel: kernel/x86/microcode/GenuineIntel.bin |
| 30 | on AMD : kernel/x86/microcode/AuthenticAMD.bin |
| 31 | |
| 32 | During BSP (BootStrapping Processor) boot (pre-SMP), the kernel |
| 33 | scans the microcode file in the initrd. If microcode matching the |
| 34 | CPU is found, it will be applied in the BSP and later on in all APs |
| 35 | (Application Processors). |
| 36 | |
| 37 | The loader also saves the matching microcode for the CPU in memory. |
| 38 | Thus, the cached microcode patch is applied when CPUs resume from a |
| 39 | sleep state. |
| 40 | |
| 41 | Here's a crude example how to prepare an initrd with microcode (this is |
| 42 | normally done automatically by the distribution, when recreating the |
| 43 | initrd, so you don't really have to do it yourself. It is documented |
| 44 | here for future reference only). |
| 45 | |
| 46 | --- |
| 47 | #!/bin/bash |
| 48 | |
| 49 | if [ -z "$1" ]; then |
| 50 | echo "You need to supply an initrd file" |
| 51 | exit 1 |
| 52 | fi |
| 53 | |
| 54 | INITRD="$1" |
| 55 | |
| 56 | DSTDIR=kernel/x86/microcode |
| 57 | TMPDIR=/tmp/initrd |
| 58 | |
| 59 | rm -rf $TMPDIR |
| 60 | |
| 61 | mkdir $TMPDIR |
| 62 | cd $TMPDIR |
| 63 | mkdir -p $DSTDIR |
| 64 | |
| 65 | if [ -d /lib/firmware/amd-ucode ]; then |
| 66 | cat /lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin |
| 67 | fi |
| 68 | |
| 69 | if [ -d /lib/firmware/intel-ucode ]; then |
| 70 | cat /lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin |
| 71 | fi |
| 72 | |
| 73 | find . | cpio -o -H newc >../ucode.cpio |
| 74 | cd .. |
| 75 | mv $INITRD $INITRD.orig |
| 76 | cat ucode.cpio $INITRD.orig > $INITRD |
| 77 | |
| 78 | rm -rf $TMPDIR |
| 79 | --- |
| 80 | |
| 81 | The system needs to have the microcode packages installed into |
| 82 | /lib/firmware or you need to fixup the paths above if yours are |
| 83 | somewhere else and/or you've downloaded them directly from the processor |
| 84 | vendor's site. |
| 85 | |
| 86 | 2. Late loading |
| 87 | =============== |
| 88 | |
| 89 | There are two legacy user space interfaces to load microcode, either through |
| 90 | /dev/cpu/microcode or through /sys/devices/system/cpu/microcode/reload file |
| 91 | in sysfs. |
| 92 | |
| 93 | The /dev/cpu/microcode method is deprecated because it needs a special |
| 94 | userspace tool for that. |
| 95 | |
| 96 | The easier method is simply installing the microcode packages your distro |
| 97 | supplies and running: |
| 98 | |
| 99 | # echo 1 > /sys/devices/system/cpu/microcode/reload |
| 100 | |
| 101 | as root. |
| 102 | |
| 103 | The loading mechanism looks for microcode blobs in |
| 104 | /lib/firmware/{intel-ucode,amd-ucode}. The default distro installation |
| 105 | packages already put them there. |
| 106 | |
| 107 | 3. Builtin microcode |
| 108 | ==================== |
| 109 | |
| 110 | The loader supports also loading of a builtin microcode supplied through |
| 111 | the regular firmware builtin method CONFIG_FIRMWARE_IN_KERNEL. Only |
| 112 | 64-bit is currently supported. |
| 113 | |
| 114 | Here's an example: |
| 115 | |
| 116 | CONFIG_FIRMWARE_IN_KERNEL=y |
| 117 | CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin" |
| 118 | CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware" |
| 119 | |
| 120 | This basically means, you have the following tree structure locally: |
| 121 | |
| 122 | /lib/firmware/ |
| 123 | |-- amd-ucode |
| 124 | ... |
| 125 | | |-- microcode_amd_fam15h.bin |
| 126 | ... |
| 127 | |-- intel-ucode |
| 128 | ... |
| 129 | | |-- 06-3a-09 |
| 130 | ... |
| 131 | |
| 132 | so that the build system can find those files and integrate them into |
| 133 | the final kernel image. The early loader finds them and applies them. |
| 134 | |
| 135 | Needless to say, this method is not the most flexible one because it |
| 136 | requires rebuilding the kernel each time updated microcode from the CPU |
| 137 | vendor is available. |