162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci========================== 462306a36Sopenharmony_ciThe Linux Microcode Loader 562306a36Sopenharmony_ci========================== 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci:Authors: - Fenghua Yu <fenghua.yu@intel.com> 862306a36Sopenharmony_ci - Borislav Petkov <bp@suse.de> 962306a36Sopenharmony_ci - Ashok Raj <ashok.raj@intel.com> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ciThe kernel has a x86 microcode loading facility which is supposed to 1262306a36Sopenharmony_ciprovide microcode loading methods in the OS. Potential use cases are 1362306a36Sopenharmony_ciupdating the microcode on platforms beyond the OEM End-Of-Life support, 1462306a36Sopenharmony_ciand updating the microcode on long-running systems without rebooting. 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciThe loader supports three loading methods: 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciEarly load microcode 1962306a36Sopenharmony_ci==================== 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciThe kernel can update microcode very early during boot. Loading 2262306a36Sopenharmony_cimicrocode early can fix CPU issues before they are observed during 2362306a36Sopenharmony_cikernel boot time. 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ciThe microcode is stored in an initrd file. During boot, it is read from 2662306a36Sopenharmony_ciit and loaded into the CPU cores. 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciThe format of the combined initrd image is microcode in (uncompressed) 2962306a36Sopenharmony_cicpio format followed by the (possibly compressed) initrd image. The 3062306a36Sopenharmony_ciloader parses the combined initrd image during boot. 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciThe microcode files in cpio name space are: 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cion Intel: 3562306a36Sopenharmony_ci kernel/x86/microcode/GenuineIntel.bin 3662306a36Sopenharmony_cion AMD : 3762306a36Sopenharmony_ci kernel/x86/microcode/AuthenticAMD.bin 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciDuring BSP (BootStrapping Processor) boot (pre-SMP), the kernel 4062306a36Sopenharmony_ciscans the microcode file in the initrd. If microcode matching the 4162306a36Sopenharmony_ciCPU is found, it will be applied in the BSP and later on in all APs 4262306a36Sopenharmony_ci(Application Processors). 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciThe loader also saves the matching microcode for the CPU in memory. 4562306a36Sopenharmony_ciThus, the cached microcode patch is applied when CPUs resume from a 4662306a36Sopenharmony_cisleep state. 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciHere's a crude example how to prepare an initrd with microcode (this is 4962306a36Sopenharmony_cinormally done automatically by the distribution, when recreating the 5062306a36Sopenharmony_ciinitrd, so you don't really have to do it yourself. It is documented 5162306a36Sopenharmony_cihere for future reference only). 5262306a36Sopenharmony_ci:: 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci #!/bin/bash 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if [ -z "$1" ]; then 5762306a36Sopenharmony_ci echo "You need to supply an initrd file" 5862306a36Sopenharmony_ci exit 1 5962306a36Sopenharmony_ci fi 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci INITRD="$1" 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci DSTDIR=kernel/x86/microcode 6462306a36Sopenharmony_ci TMPDIR=/tmp/initrd 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci rm -rf $TMPDIR 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci mkdir $TMPDIR 6962306a36Sopenharmony_ci cd $TMPDIR 7062306a36Sopenharmony_ci mkdir -p $DSTDIR 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if [ -d /lib/firmware/amd-ucode ]; then 7362306a36Sopenharmony_ci cat /lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin 7462306a36Sopenharmony_ci fi 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if [ -d /lib/firmware/intel-ucode ]; then 7762306a36Sopenharmony_ci cat /lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin 7862306a36Sopenharmony_ci fi 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci find . | cpio -o -H newc >../ucode.cpio 8162306a36Sopenharmony_ci cd .. 8262306a36Sopenharmony_ci mv $INITRD $INITRD.orig 8362306a36Sopenharmony_ci cat ucode.cpio $INITRD.orig > $INITRD 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci rm -rf $TMPDIR 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciThe system needs to have the microcode packages installed into 8962306a36Sopenharmony_ci/lib/firmware or you need to fixup the paths above if yours are 9062306a36Sopenharmony_cisomewhere else and/or you've downloaded them directly from the processor 9162306a36Sopenharmony_civendor's site. 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciLate loading 9462306a36Sopenharmony_ci============ 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ciYou simply install the microcode packages your distro supplies and 9762306a36Sopenharmony_cirun:: 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci # echo 1 > /sys/devices/system/cpu/microcode/reload 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cias root. 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciThe loading mechanism looks for microcode blobs in 10462306a36Sopenharmony_ci/lib/firmware/{intel-ucode,amd-ucode}. The default distro installation 10562306a36Sopenharmony_cipackages already put them there. 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciSince kernel 5.19, late loading is not enabled by default. 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciThe /dev/cpu/microcode method has been removed in 5.19. 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciWhy is late loading dangerous? 11262306a36Sopenharmony_ci============================== 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciSynchronizing all CPUs 11562306a36Sopenharmony_ci---------------------- 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ciThe microcode engine which receives the microcode update is shared 11862306a36Sopenharmony_cibetween the two logical threads in a SMT system. Therefore, when 11962306a36Sopenharmony_cithe update is executed on one SMT thread of the core, the sibling 12062306a36Sopenharmony_ci"automatically" gets the update. 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciSince the microcode can "simulate" MSRs too, while the microcode update 12362306a36Sopenharmony_ciis in progress, those simulated MSRs transiently cease to exist. This 12462306a36Sopenharmony_cican result in unpredictable results if the SMT sibling thread happens to 12562306a36Sopenharmony_cibe in the middle of an access to such an MSR. The usual observation is 12662306a36Sopenharmony_cithat such MSR accesses cause #GPs to be raised to signal that former are 12762306a36Sopenharmony_cinot present. 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciThe disappearing MSRs are just one common issue which is being observed. 13062306a36Sopenharmony_ciAny other instruction that's being patched and gets concurrently 13162306a36Sopenharmony_ciexecuted by the other SMT sibling, can also result in similar, 13262306a36Sopenharmony_ciunpredictable behavior. 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ciTo eliminate this case, a stop_machine()-based CPU synchronization was 13562306a36Sopenharmony_ciintroduced as a way to guarantee that all logical CPUs will not execute 13662306a36Sopenharmony_ciany code but just wait in a spin loop, polling an atomic variable. 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ciWhile this took care of device or external interrupts, IPIs including 13962306a36Sopenharmony_ciLVT ones, such as CMCI etc, it cannot address other special interrupts 14062306a36Sopenharmony_cithat can't be shut off. Those are Machine Check (#MC), System Management 14162306a36Sopenharmony_ci(#SMI) and Non-Maskable interrupts (#NMI). 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ciMachine Checks 14462306a36Sopenharmony_ci-------------- 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciMachine Checks (#MC) are non-maskable. There are two kinds of MCEs. 14762306a36Sopenharmony_ciFatal un-recoverable MCEs and recoverable MCEs. While un-recoverable 14862306a36Sopenharmony_cierrors are fatal, recoverable errors can also happen in kernel context 14962306a36Sopenharmony_ciare also treated as fatal by the kernel. 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciOn certain Intel machines, MCEs are also broadcast to all threads in a 15262306a36Sopenharmony_cisystem. If one thread is in the middle of executing WRMSR, a MCE will be 15362306a36Sopenharmony_citaken at the end of the flow. Either way, they will wait for the thread 15462306a36Sopenharmony_ciperforming the wrmsr(0x79) to rendezvous in the MCE handler and shutdown 15562306a36Sopenharmony_cieventually if any of the threads in the system fail to check in to the 15662306a36Sopenharmony_ciMCE rendezvous. 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciTo be paranoid and get predictable behavior, the OS can choose to set 15962306a36Sopenharmony_ciMCG_STATUS.MCIP. Since MCEs can be at most one in a system, if an 16062306a36Sopenharmony_ciMCE was signaled, the above condition will promote to a system reset 16162306a36Sopenharmony_ciautomatically. OS can turn off MCIP at the end of the update for that 16262306a36Sopenharmony_cicore. 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciSystem Management Interrupt 16562306a36Sopenharmony_ci--------------------------- 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciSMIs are also broadcast to all CPUs in the platform. Microcode update 16862306a36Sopenharmony_cirequests exclusive access to the core before writing to MSR 0x79. So if 16962306a36Sopenharmony_ciit does happen such that, one thread is in WRMSR flow, and the 2nd got 17062306a36Sopenharmony_cian SMI, that thread will be stopped in the first instruction in the SMI 17162306a36Sopenharmony_cihandler. 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciSince the secondary thread is stopped in the first instruction in SMI, 17462306a36Sopenharmony_cithere is very little chance that it would be in the middle of executing 17562306a36Sopenharmony_cian instruction being patched. Plus OS has no way to stop SMIs from 17662306a36Sopenharmony_cihappening. 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ciNon-Maskable Interrupts 17962306a36Sopenharmony_ci----------------------- 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciWhen thread0 of a core is doing the microcode update, if thread1 is 18262306a36Sopenharmony_cipulled into NMI, that can cause unpredictable behavior due to the 18362306a36Sopenharmony_cireasons above. 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ciOS can choose a variety of methods to avoid running into this situation. 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ciIs the microcode suitable for late loading? 18962306a36Sopenharmony_ci------------------------------------------- 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciLate loading is done when the system is fully operational and running 19262306a36Sopenharmony_cireal workloads. Late loading behavior depends on what the base patch on 19362306a36Sopenharmony_cithe CPU is before upgrading to the new patch. 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ciThis is true for Intel CPUs. 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciConsider, for example, a CPU has patch level 1 and the update is to 19862306a36Sopenharmony_cipatch level 3. 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ciBetween patch1 and patch3, patch2 might have deprecated a software-visible 20162306a36Sopenharmony_cifeature. 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ciThis is unacceptable if software is even potentially using that feature. 20462306a36Sopenharmony_ciFor instance, say MSR_X is no longer available after an update, 20562306a36Sopenharmony_ciaccessing that MSR will cause a #GP fault. 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ciBasically there is no way to declare a new microcode update suitable 20862306a36Sopenharmony_cifor late-loading. This is another one of the problems that caused late 20962306a36Sopenharmony_ciloading to be not enabled by default. 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ciBuiltin microcode 21262306a36Sopenharmony_ci================= 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciThe loader supports also loading of a builtin microcode supplied through 21562306a36Sopenharmony_cithe regular builtin firmware method CONFIG_EXTRA_FIRMWARE. Only 64-bit is 21662306a36Sopenharmony_cicurrently supported. 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ciHere's an example:: 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin" 22162306a36Sopenharmony_ci CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware" 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciThis basically means, you have the following tree structure locally:: 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /lib/firmware/ 22662306a36Sopenharmony_ci |-- amd-ucode 22762306a36Sopenharmony_ci ... 22862306a36Sopenharmony_ci | |-- microcode_amd_fam15h.bin 22962306a36Sopenharmony_ci ... 23062306a36Sopenharmony_ci |-- intel-ucode 23162306a36Sopenharmony_ci ... 23262306a36Sopenharmony_ci | |-- 06-3a-09 23362306a36Sopenharmony_ci ... 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ciso that the build system can find those files and integrate them into 23662306a36Sopenharmony_cithe final kernel image. The early loader finds them and applies them. 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ciNeedless to say, this method is not the most flexible one because it 23962306a36Sopenharmony_cirequires rebuilding the kernel each time updated microcode from the CPU 24062306a36Sopenharmony_civendor is available. 241