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