跳至內容
出自 Arch Linux 中文维基

處理器製造商會發布對處理器微碼的穩定性和安全性更新。這些更新提供了對系統穩定性至關重要的錯誤修復。如果沒有這些更新,則可能會遇到不明原因的崩潰或難以跟蹤的意外停機。

使用 AMD 或 Intel CPU 的用戶都應該安裝微碼更新以確保系統穩定性。在虛擬機或容器中,微碼更新應在主機上實施,而不是在客戶機系統中。

安裝

要獲取更新的微碼,根據處理器類型,安裝以下其中一個軟體包:

mkinitcpiodracut 默認會生成組合的 initramfs 文件。微碼將在啟動時自動加載。Booster 不支持生成組合的 initramfs,請參閱#微碼在單獨的initramfs文件中 中所需的引導加載程序配置。

加載微碼

微碼更新通常與主板的固件一起發布,並在固件初始化期間應用。由於OEM可能不會及時發布固件更新,且舊系統根本不會獲得新的固件更新,Linux內核增加了在啟動期間應用CPU微碼更新的功能。Linux微碼加載器支持三種加載方法:

  1. 內置微碼可以編譯到內核中,然後由早期加載器應用。
  2. 早期加載在啟動的非常早期階段(在initramfs階段之前)更新微碼,比晚期加載更受推薦。這對於具有嚴重硬體錯誤的CPU(如Intel Haswell和Broadwell處理器系列)是強制性的。
  3. 晚期加載可能危險的)在啟動後更新微碼,這可能為時已晚,因為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,因為不需要額外的引導參數配置。

提示:您可以選擇將boot/*-ucode.img添加到/etc/pacman.conf中的NoExtract,因為微碼文件將直接從/usr/lib/firmware/*-ucode/中獲取。
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製造商,即amdintel

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-ucodeintel-ucode時更新微碼。否則,請在每次更新微碼包時將/boot/cpu_manufacturer-ucode.img複製到您的ESP。

EFISTUB

附加兩個initrd=選項:

initrd=\cpu_manufacturer-ucode.img initrd=\initramfs-linux.img
rEFInd
提示:以前未指定initrd內核參數的用戶需要按照rEFInd#Configuration中描述的步驟啟用傳遞多個initrd參數。

編輯/boot/refind_linux.conf中的引導選項,並添加一個initrd=選項作為傳遞的第一個initrd參數。使用initrd=boot\cpu_manufacturer-ucode.imginitrd=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.imginitramfs-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

晚期加載

警告:晚期微碼加載被認為是危險的,在Linux 5.19及更高版本上使用它將污染內核。[1]

晚期加載微碼更新發生在系統啟動後。它使用/usr/lib/firmware/amd-ucode//usr/lib/firmware/intel-ucode/中的文件。微碼更新文件分別由amd-ucodeintel-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 接受微碼更新

用戶可以查閱 Intel 的倉庫或 Gentoo 的 AMD 維基,以查看特定型號是否受支持:

檢測可用的微碼更新

對於 Intel,可以使用 iucode_tool(8) 來檢查 /usr/lib/firmware/intel-ucode/ 是否包含運行中 CPU 的微碼。

  1. 安裝 intel-ucodeiucode-tool
  2. 加載 cpuid 內核模塊:
    # modprobe cpuid
  3. 搜索您的 cpuid:
    $ iucode_tool -lS /usr/lib/firmware/intel-ucode/
  4. 如果有可用的更新,它應該會顯示在「selected microcodes」下面
  5. 微碼可能已經在您的供應商 BIOS 中,並且不會在 dmesg 中顯示加載。與當前運行的微碼進行比較 grep microcode /proc/cpuinfo

對於 AMD,可以手動完成。

  1. 找出 CPU 的系列、型號和步進。例如,通過運行以下命令:
    # journalctl -k --grep='CPU0:'
    查看輸出部分,如 (family: 0x15, model: 0x10, stepping: 0x1)
  2. 根據 amd-ucode README 中的列表匹配相應的值。
  3. 如果匹配,將 當前運行的微碼版本 與列出的 Patch 值進行比較。
注意:您也可以使用 lscpu(1)/proc/cpuinfo 輸出來獲取系列、型號和步進。但您需要將值轉換為十六進制。

參見

禁用微碼加載器

如果更新的 CPU 微碼導致問題,您可能希望暫時禁用微碼加載器以允許成功啟動並降級軟體包。要禁用內核的微碼加載器,請指定 dis_ucode_ldr 內核參數

參見