微码
处理器制造商发布处理器 微码 的稳定性和安全性更新。这些更新提供了错误修复,这对系统的稳定性至关重要。没有它们,您可能会遇到难以追踪的虚假崩溃或意外的系统停止。
所有使用 AMD 或 Intel CPU 的用户都应该安装微码更新以确保系统稳定性。在虚拟机和容器中,微码更新应安装在宿主机上,而不是在客户机系统中。
安装
要获取更新的微码,根据处理器类型,安装 以下软件包之一
- amd-ucode 用于 AMD 处理器,
- intel-ucode 用于 Intel 处理器。
mkinitcpio 和 dracut 默认生成组合的 initramfs 文件。微码将在启动时自动加载。Booster 不支持生成组合的 initramfs,请参阅 #微码位于单独的 initramfs 文件中 中所需的引导加载程序配置。
加载微码
微码更新通常与主板的固件一起发布,并在固件初始化期间应用。由于 OEM 可能不会及时发布固件更新,并且旧系统根本不会获得新的固件更新,因此 Linux 内核添加了在启动期间应用 CPU 微码更新的功能。Linux 微码加载器 支持三种加载方法
- 内置微码 可以编译到内核中,然后由早期加载器应用。
- 早期加载 在启动的非常早期更新微码,在 initramfs 阶段之前,并且优于后期加载。对于具有严重硬件错误的 CPU(如 Intel Haswell 和 Broadwell 处理器系列)来说,这是强制性的。
- 后期加载 (可能 可能 是 危险的) 在启动后更新微码,这可能为时已晚,因为 CPU 可能已经尝试使用有缺陷的指令。即使已经使用早期加载,后期加载仍然可以用于应用更新的微码更新,而无需重新启动。
早期加载
内核的早期加载器期望在未压缩的 CPIO 归档文件(initramfs 镜像)内的 /kernel/x86/microcode/GenuineIntel.bin
或 /kernel/x86/microcode/AuthenticAMD.bin
中找到微码更新文件。
早期的 initramfs 镜像可以与主 initramfs 镜像组合成一个文件,并作为单个 initramfs 传递给内核(通过引导加载程序的 initrd=
内核命令行选项,或者当打包在统一内核镜像中时),或者它可以作为单独的文件存在,在这种情况下,需要使用多个 initrd=
内核命令行选项。在这两种情况下,包含微码的未压缩 CPIO 归档文件必须放在主 initramfs 之前。
请注意,由于用户早期启动配置的广泛差异,Arch 的默认配置可能不会自动触发微码更新。
自定义构建内核
为了使早期加载在自定义内核中工作,“CPU 微码加载支持”需要编译到内核中,而不是作为模块编译。这将启用“Early load microcode”提示,应将其设置为 Y
。
CONFIG_BLK_DEV_INITRD=Y CONFIG_MICROCODE=y CONFIG_MICROCODE_INTEL=Y CONFIG_MICROCODE_AMD=y
微码 initramfs 与主 initramfs 打包在一个文件中
未压缩的微码 CPIO 可以预先添加到 initramfs 中,并用作单个 initramfs 文件。此方法优于#微码位于单独的 initramfs 文件中,因为不需要额外的引导参数配置。
boot/*-ucode.img
添加到 /etc/pacman.conf
中的 NoExtract,因为微码文件将直接从 /usr/lib/firmware/*-ucode/
中获取。mkinitcpio
对于 mkinitcpio 生成包含微码的 initramfs 文件,请确保 microcode
在 /etc/mkinitcpio.conf
中的 HOOKS
数组中。
如果 autodetect
hook 在 microcode
之前,则只会包含当前 CPU 的微码。要包含系统上可以找到的所有 CPU 微码文件,请将 microcode
hook 移动到 autodetect
之前,或者完全删除 autodetect
hook。
生成 initramfs 时,mkinitcpio 将显示
-> Early uncompressed CPIO image generation successful
您可以使用 lsinitcpio(1) 验证 initramfs 是否包含微码更新文件。例如:
# lsinitcpio --early /boot/initramfs-linux.img | grep microcode
kernel/x86/microcode/ kernel/x86/microcode/AuthenticAMD.bin
dracut
对于 dracut,请参阅 dracut.conf(5) § DESCRIPTION。
微码位于单独的 initramfs 文件中
否则,必须通过将 /boot/amd-ucode.img
或 /boot/intel-ucode.img
添加为引导加载程序配置文件中的第一个 initrd 来启用早期微码更新。这在正常的 initrd 文件之前。有关常见引导加载程序的说明,请参见下文。
在以下部分中,将 cpu_manufacturer
替换为您的 CPU 制造商,即 amd
或 intel
。
GRUB
grub-mkconfig 将自动检测微码更新并适当配置 GRUB。安装微码软件包后,重新生成 GRUB 配置以激活加载微码更新,方法是运行
# grub-mkconfig -o /boot/grub/grub.cfg
或者,手动管理 GRUB 配置文件的用户可以添加 /boot/cpu_manufacturer-ucode.img
(如果 /boot
是单独的分区,则添加 /cpu_manufacturer-ucode.img
),如下所示
/boot/grub/grub.cfg
... echo 'Loading initial ramdisk' initrd /boot/cpu_manufacturer-ucode.img /boot/initramfs-linux.img ...
为每个菜单条目重复此操作。
systemd-boot
在初始 ramdisk 之前,使用 initrd
选项加载微码,如下所示
/boot/loader/entries/entry.conf
title Arch Linux linux /vmlinuz-linux initrd /cpu_manufacturer-ucode.img initrd /initramfs-linux.img ...
最新的微码 cpu_manufacturer-ucode.img
必须在启动时在您的 EFI 系统分区 (ESP) 中可用。必须将 ESP 挂载为 /boot
,以便在每次 amd-ucode 或 intel-ucode 更新时更新微码。否则,在每次更新微码软件包时,将 /boot/cpu_manufacturer-ucode.img
复制到您的 ESP。
EFISTUB
附加两个 initrd=
选项
initrd=\cpu_manufacturer-ucode.img initrd=\initramfs-linux.img
rEFInd
编辑 /boot/refind_linux.conf
中的引导选项,并为微码镜像添加 initrd=
选项作为传递的第一个 initrd
参数。根据 /boot
中的文件是否位于单独分区的根目录,使用 initrd=boot\cpu_manufacturer-ucode.img
或 initrd=cpu_manufacturer-ucode.img
。
微码需要是为引导选项列表声明的第一个 initramfs。例如
"Boot using default options" "root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw add_efi_memmap initrd=boot\cpu_manufacturer-ucode.img initrd=boot\initramfs-%v.img"
手动引导条目
在 esp/EFI/refind/refind.conf
中使用 手动条目 定义内核的用户应添加 initrd=
参数,其中包含引导分区中的正确路径。此参数是 options 行的一部分,而不是条目的主要部分。例如:
options "root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw add_efi_memmap initrd=boot\cpu_manufacturer-ucode.img"
Syslinux
cpu_manufacturer-ucode.img
和 initramfs-linux.img
initrd 文件之间不能有空格。INITRD
行必须与下面所示的完全一致。多个 initrd 可以用逗号在 /boot/syslinux/syslinux.cfg
中分隔
LABEL arch MENU LABEL Arch Linux LINUX ../vmlinuz-linux INITRD ../cpu_manufacturer-ucode.img,../initramfs-linux.img ...
LILO
LILO 以及可能其他旧的引导加载程序不支持多个 initrd 镜像。请遵循 #微码 initramfs 与主 initramfs 打包在一个文件中 方法。
Limine
对于 Limine,您只需要通过 limine.conf 文件中的 MODULE_PATH
选项添加微码的路径。这是一个例子
limine.conf
default_entry: 1 timeout: 3 /Arch comment: Arch Linux protocol: linux kernel_path: boot():/vmlinuz-linux kernel_cmdline: root=UUID=c0748521-eca9-4f38-989c-43811b6e39a1 rw loglevel=3 module_path: boot():/cpu_manufacturer-ucode.img module_path: boot():/initramfs-linux.img
后期加载
微码更新的后期加载发生在系统启动后。它使用 /usr/lib/firmware/amd-ucode/
和 /usr/lib/firmware/intel-ucode/
中的文件。微码更新文件分别由 amd-ucode 和 intel-ucode 提供。
后期加载需要内核构建时启用 CONFIG_MICROCODE_LATE_LOADING=y
,但 Arch 官方支持的内核 目前并非如此。[2]
后期加载微码更新
要手动重新加载微码,例如在更新 /usr/lib/firmware/amd-ucode/
或 /usr/lib/firmware/intel-ucode/
中的微码文件后,运行
# echo 1 > /sys/devices/system/cpu/microcode/reload
这允许在无需重启系统的情况下应用更新的微码更新。
验证微码是否在启动时更新
使用 journalctl 检查内核消息,以查看微码是否已更新
# journalctl -k --grep='microcode:'
每次启动时,应该能看到类似下面的信息,表明微码已在启动早期更新
kernel: microcode: Current revision: 0x00000012 kernel: microcode: Updated early from: 0x0000000e
尤其是在较新的硬件上,CPU 有可能没有微码更新。
在使用延迟加载的 AMD 系统上,输出将显示旧微码的版本,然后在重新加载微码后显示新微码的版本。
哪些 CPU 接受微码更新
用户可以查阅英特尔的仓库或 Gentoo 的 AMD Wiki,通过以下链接查看特定型号是否受支持
检测可用的微码更新
对于英特尔,可以检查 /usr/lib/firmware/intel-ucode/
是否包含正在运行的 CPU 的微码,使用 iucode_tool(8)。
- 安装 intel-ucode 和 iucode-tool
- 加载
cpuid
内核模块# modprobe cpuid
- 搜索您的 cpuid
$ iucode_tool -lS /usr/lib/firmware/intel-ucode/
- 如果有可用的更新,它应该在selected microcodes(已选择的微码)下方显示
- 微码可能已存在于您的供应商 BIOS 中,并且不会在 dmesg 中显示加载。与当前运行的微码进行比较,运行
grep microcode /proc/cpuinfo
对于 AMD,可以手动完成。
- 找出 CPU 的 family(系列)、model(型号)和 stepping(步进)。例如,通过运行以下命令
# journalctl -k --grep='CPU0:'
查看类似(family: 0x15, model: 0x10, stepping: 0x1)
的输出部分。 - 将这些值与 amd-ucode README 中的列表进行匹配。
- 如果匹配,将运行中微码的当前修订版与列出的
Patch
值进行比较。
/proc/cpuinfo
输出获取 family(系列)、model(型号)和 stepping(步进)。但您需要将这些值转换为十六进制。禁用微码加载器
如果更新的 CPU 微码导致问题,您可能需要暂时禁用微码加载器,以便成功启动并降级软件包。要禁用内核的微码加载器,请指定 dis_ucode_ldr
内核参数。