微碼
處理器製造商會發布對處理器微碼的穩定性和安全性更新。這些更新提供了對系統穩定性至關重要的錯誤修復。如果沒有這些更新,則可能會遇到不明原因的崩潰或難以跟蹤的意外停機。
使用 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
未壓縮的微碼CPIO可以預置到initramfs中並用作單個initramfs文件。此方法優於#Microcode in a separate initramfs file,因為不需要額外的引導參數配置。
為了使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.conf(5) § DESCRIPTION。
早期微碼更新必須通過在引導加載程序配置文件中添加/boot/amd-ucode.img或/boot/intel-ucode.img作為第一個initrd來啟用。這是在正常initrd文件之前。請參閱以下常見引導加載程序的說明。
在以下部分中,將cpu_manufacturer替換為您的CPU製造商,即amd或intel。
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 ...
為每個菜單項重複此操作。
使用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。
附加兩個initrd=選項:
initrd=\cpu_manufacturer-ucode.img initrd=\initramfs-linux.img
編輯/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"
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和可能其他舊的引導加載程序不支持多個initrd鏡像。請改用#Microcode initramfs packed together with the main initramfs in one file方法。
對於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 項目
用戶可以查閱 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 內核參數。