Microcode (简体中文)
处理器制造商发布对处理器微码的稳定性和安全性更新。这些更新提供了对系统稳定性至关重要的错误修复。如果没有这些更新,您可能会遇到不明原因的崩溃或难以跟踪的意外停机。
使用 AMD 或 Intel CPU 的用户都应该安装这些微代码更新,以确保系统稳定性。
通常主板的固件会包含微代码更新,并在初始化时使用最新的微代码版本。但是 OEM 可能无法给所有机型提供及时的最新固件,所以 Linux 内核提供了启动时应用最新微代码的功能。Linux microcode 加载器 支持三种加载方式:
- 早期加载 在非常早的启动阶段生效,比 initramfs 阶段还早,所以是推荐的方式,如果 CPU 有严重的硬件问题时尤其如此,比如 Intel Haswell 和 Broadwell 处理器。
- 后期加载 在启动后生效,有时这个时间太晚了,因为 CPU 可能已经执行了有问题的指令集。即使已经启用了早加载,晚加载依然有价值,可以让系统不重启的时候也应用到最新的微代码更新。
- 内置微代码 可以编译到内核中,在启动的早期阶段应用。.
启用早期微码更新
由于用户的早期引导配置具有很大的可变性,因此Arch的默认配置不会自动启用早加载。AUR 里很多内核都遵循这个设定。
要启用早加载,必须通过把 /boot/amd-ucode.img
或者 /boot/intel-ucode.img
作为第一个 initrd 添加到 bootloader 的配置文件里来启用。下面的章节有常见的 bootloader 的配置。
cpu_manufacturer
换成 CPU 的制造商, 即 amd
或者 intel
。安装
对于 Intel 处理器,安装 intel-ucode。
如果你在一个移动介质上安装Arch Linux,需要应该安装以上两个厂商处理器的微码软件包。
在自定义内核中启用微代码加载
启用 “CPU microcode loading support” 才能在启动早期加载微代码,必须编译到内核中,而不是编译为模块。然后将 “Early load microcode” 设置为 “Y”。
CONFIG_BLK_DEV_INITRD=Y CONFIG_MICROCODE=y CONFIG_MICROCODE_INTEL=y CONFIG_MICROCODE_AMD=y
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
/boot/loader/entries/entry.conf
title Arch Linux linux /vmlinuz-linux initrd /cpu_manufacturer-ucode.img initrd /initramfs-linux.img options ...
最新的 cpu_manufacturer-ucode.img
必须在启动时存在于 ESP分区. ESP 必须挂载到 /boot
,这样才能在 amd-ucode 或 intel-ucode 更新时才能更新里面的 img 文件。否则需要在微代码更新时手动将 /boot/cpu_manufacturer-ucode.img
复制到 ESP。
Unified kernel images
For unified kernel images, first generate the initrd to integrate by creating a new one as follows:
$ cat /boot/cpu_manufacturer-ucode.img /boot/initramfs-linux.img > my_new_initrd.img $ objcopy ... --add-section .initrd=my_new_initrd .img
EFISTUB
Append two initrd=
options:
initrd=\cpu_manufacturer-ucode.img initrd=\initramfs-linux.img
rEFInd
Edit boot options in /boot/refind_linux.conf
and add initrd=boot\cpu_manufacturer-ucode.img
(or initrd=cpu_manufacturer-ucode.img
if /boot
is a separate partition) as the first initramfs. For example:
"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"
initrd
kernel parameter will need to follow the steps described in rEFInd#Configuration to enable passing of multiple initrd
parameters.如果在 esp/EFI/refind/refind.conf
中使用 手动配置 定义所要引导的内核,那么添加 initrd=/boot/cpu_manufacturer-ucode.img
(如果 /boot
独立分区则添加initrd=/cpu_manufacturer-ucode.img
) 到选项行。并不需要修改配置的主干部分。
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
initrd 文件间不要用空格,下面的点不是省略号,INITRD
行必须和下面示例中一样。在配置文件/boot/syslinux/syslinux.cfg
中,多个 initrd 可以通过逗号来分隔。
LABEL arch MENU LABEL Arch Linux LINUX ../vmlinuz-linux INITRD ../cpu_manufacturer-ucode.img,../initramfs-linux.img APPEND ...
LILO
LILO和其他的老版本启动引导器可能不支持多个initrd镜像,所以intel-ucode
和 initramfs-linux
需要被合并成一个镜像。
initramfs-linux
必须在 intel-ucode
之后。合并两个镜像并生成 initramfs-merged.img
:
# cat /boot/intel-ucode.img /boot/initramfs-linux.img > /boot/initramfs-merged.img
现在编辑 /etc/lilo.conf
装载新的镜像:
... initrd=/boot/initramfs-merged.img ...
以root运行lilo
:
# lilo
后期加载
微码更新的后期加载,是指在系统启动之后的加载。它使用了 /usr/lib/firmware/amd-ucode/
和 /usr/lib/firmware/intel-ucode/
文件夹里的文件。
对于 AMD 处理器来说,微码更新的文件由 linux-firmware 软件包提供。
对于 Intel 的处理器,没有任何软件包提供微码更新文件 (FS#59841)。要使用后期加载,你可能需要从英特尔提供的压缩包里手动解压出 intel-ucode/
文件夹。
启用微码更新后期加载
后期加载是默认启用的,由 /usr/lib/tmpfiles.d/linux-firmware.conf
实现。在启动过程完成之后,微码更新文件由 systemd-tmpfiles-setup.service(8) 解析,实现 CPU 微码更新。
如果要手动触发微码更新:
# echo 1 > /sys/devices/system/cpu/microcode/reload
更新了 linux-firmware 之后想不重启就应用微码更新,这个命令比较有用。要自动化这个过程,可以创建一个 pacman hook:
/etc/pacman.d/hooks/microcode_reload.hook
[Trigger] Operation = Upgrade Type = Path Target = usr/lib/firmware/amd-ucode/* [Action] Description = Applying CPU microcode updates... When = PostTransaction Depends = sh Exec = /bin/sh -c 'echo 1 > /sys/devices/system/cpu/microcode/reload'
禁用微码更新的后期加载
对于 AMD 的处理器来说,即使不安装 amd-ucode,CPU 的微码仍然会被更新,因为所需的文件是由 linux-firmware 提供的(FS#59840)。
虚拟机 和 容器 (FS#46591) 不支持 CPU 微代码更新,所以需要禁用此功能。需要覆盖 /usr/lib/tmpfiles.d/linux-firmware.conf
这个 tmpfile,通过在 /etc/tmpfiles.d/
创建一个名字也是 linux-firmware.conf
的文件来实现。当然也可以这样来实现覆盖的效果:
# ln -s /dev/null /etc/tmpfiles.d/linux-firmware.conf
验证微指令已在启动时更新
使用 /usr/bin/dmesg
可以查看微代码有没有更新:
# dmesg | grep microcode
在 Intel 系统上,你应当会看到和下面类似的一些东西,表明微指令已在早先更新:
[ 0.000000] CPU0 microcode updated early to revision 0x1b, date = 2014-05-29 [ 0.221951] CPU1 microcode updated early to revision 0x1b, date = 2014-05-29 [ 0.242064] CPU2 microcode updated early to revision 0x1b, date = 2014-05-29 [ 0.262349] CPU3 microcode updated early to revision 0x1b, date = 2014-05-29 [ 0.507267] microcode: CPU0 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507272] microcode: CPU1 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507276] microcode: CPU2 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507281] microcode: CPU3 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507286] microcode: CPU4 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507292] microcode: CPU5 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507296] microcode: CPU6 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507300] microcode: CPU7 sig=0x306a9, pf=0x2, revision=0x1b [ 0.507335] microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba
如果硬件比较新,也可能没有任何微代码更新,结果应该是下面这样:
[ 0.292893] microcode: CPU0 sig=0x306c3, pf=0x2, revision=0x1c [ 0.292899] microcode: CPU1 sig=0x306c3, pf=0x2, revision=0x1c [ 0.292906] microcode: CPU2 sig=0x306c3, pf=0x2, revision=0x1c [ 0.292912] microcode: CPU3 sig=0x306c3, pf=0x2, revision=0x1c [ 0.292956] microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba
在 AMD 系统上,微指令会在启动的更晚阶段被更新,所以输出会看起来像这样:
[ 0.807879] microcode: CPU0: patch_level=0x01000098 [ 0.807888] microcode: CPU1: patch_level=0x01000098 [ 0.807983] microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba [ 16.150642] microcode: CPU0: new patch_level=0x010000c7 [ 16.150682] microcode: CPU1: new patch_level=0x010000c7
哪些 CPU 可以接受微指令更新
可以从 Intel 和 AMD 的网站查看支持的型号:
- AMD 操作系统研发中心.
- Intel 下载中心[失效链接 2020-08-04 ⓘ].
检查可用微指令更新
可以通过 iucode-tool 来检查 intel-ucode.img 是否包含适用于你 CPU 的微指令映像。
- 安装 intel-ucode (检测并不需要修改 initrd)
- 从 AUR 安装 iucode-tool
- 加载
cpuid
内核模块:# modprobe cpuid
- 解包微指令映像,并根据你的 cpuid 搜索是否适用:
# bsdtar -Oxf /boot/intel-ucode.img | iucode_tool -tb -lS -
- 如果有更新可用,它应该会在 selected microcodes 之下显示
- 微码可能已经在你的BIOS里,所以不会在dmesg里出现。和正在运行的微码对比:
grep microcode /proc/cpuinfo