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