处理器制造商会发布对处理器微码的稳定性和安全性更新。这些更新提供了对系统稳定性至关重要的错误修复。如果没有这些更新,则可能会遇到不明原因的崩溃或难以跟踪的意外停机。
使用 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微码加载支持”编译到内核中,而不是编译为模块。这将启用“早期加载微码”提示,应将其设置为Y
。
CONFIG_BLK_DEV_INITRD=Y CONFIG_MICROCODE=y CONFIG_MICROCODE_INTEL=Y CONFIG_MICROCODE_AMD=y
微码initramfs与主initramfs打包在一个文件中
未压缩的微码CPIO可以预置到initramfs中并用作单个initramfs文件。此方法优于#Microcode in a separate initramfs file,因为不需要额外的引导参数配置。
mkinitcpio
为了使mkinitcpio生成包含微码的initramfs文件,请确保microcode
在/etc/mkinitcpio.conf
中的HOOKS
数组中。
如果autodetect
钩子位于microcode
之前,则仅包含当前CPU的微码。要包含系统上可以找到的所有CPU微码文件,请将microcode
钩子移动到autodetect
之前或完全删除autodetect
钩子。
生成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
(或/cpu_manufacturer-ucode.img
如果/boot
是单独的分区)如下:
/boot/grub/grub.cfg
... echo 'Loading initial ramdisk' initrd /boot/cpu_manufacturer-ucode.img /boot/initramfs-linux.img ...
为每个菜单项重复此操作。
systemd-boot
使用initrd
选项加载微码,在初始ramdisk之前,如下所示:
/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
参数。使用initrd=boot\cpu_manufacturer-ucode.img
或initrd=cpu_manufacturer-ucode.img
,具体取决于/boot
中的文件是否在单独分区的根目录中。
微码需要是引导选项列表中声明的第一个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 "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镜像。请改用#Microcode initramfs packed together with the main initramfs in one file方法。
Limine
对于Limine,您只需通过MODULE_PATH
选项在您的limine.conf文件中添加微码的路径。以下是一个示例:
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 系统上使用延迟加载时,输出将显示重新加载微码前的旧微码版本以及重新加载后的新版本。
参见
- 更新微码 – 社区经验
- 关于 Intel 微码更新的笔记 – Ben Hawkes
- 内核微码加载器 – 内核文档
- Haswell/Broadwell 中的勘误 – AnandTech
- iucode-tool GitLab 项目
哪些 CPU 接受微码更新
用户可以查阅 Intel 的仓库或 Gentoo 的 AMD 维基,以查看特定型号是否受支持:
检测可用的微码更新
对于 Intel,可以使用 iucode_tool(8) 来检查 /usr/lib/firmware/intel-ucode/
是否包含运行中 CPU 的微码。
- 安装 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 的系列、型号和步进。例如,通过运行以下命令:
# journalctl -k --grep='CPU0:'
查看输出部分,如(family: 0x15, model: 0x10, stepping: 0x1)
。 - 根据 amd-ucode README 中的列表匹配相应的值。
- 如果匹配,将 当前运行的微码版本 与列出的
Patch
值进行比较。
/proc/cpuinfo
输出来获取系列、型号和步进。但您需要将值转换为十六进制。参见
- 更新微码 – 社区经验
- 关于 Intel 微码更新的笔记 – Ben Hawkes
- 内核微码加载器 – 内核文档
- Haswell/Broadwell 中的勘误 – AnandTech
- iucode-tool GitLab 项目
禁用微码加载器
如果更新的 CPU 微码导致问题,您可能希望暂时禁用微码加载器以允许成功启动并降级软件包。要禁用内核的微码加载器,请指定 dis_ucode_ldr
内核参数。