微碼 - Arch Linux 中文维基

跳至內容

# 微碼

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 Microcode，最近一次同步於 2025-04-09，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

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

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

## 安裝

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

- amd-ucode包 用於 AMD 處理器，
- intel-ucode包 用於 Intel 處理器。

mkinitcpio 和 dracut 默認會生成組合的 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製造商，即`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

提示：以前未指定`initrd`內核參數的用戶需要按照rEFInd#Configuration中描述的步驟啟用傳遞多個`initrd`參數。

編輯`/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

### 晚期加載

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

晚期加載微碼更新發生在系統啟動後。它使用`/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 維基，以查看特定型號是否受支持：

- Gentoo:AMD microcode#Microcode firmware files。
- Intel 的 Github 倉庫。

### 檢測可用的微碼更新

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

1. 安裝 intel-ucode包 和 iucode-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` 輸出來獲取系列、型號和步進。但您需要將值轉換為十六進制。

## 參見

- 更新微碼 – 社區經驗
- 關於 Intel 微碼更新的筆記 – Ben Hawkes
- 內核微碼加載器 – 內核文檔
- Haswell/Broadwell 中的勘誤 – AnandTech
- iucode-tool GitLab 項目

## 禁用微碼加載器

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

## 參見

- Updating microcodes – Experiences in the community
- Notes on Intel Microcode updates – Ben Hawkes
- Kernel microcode loader – kernel documentation
- Erratum found in Haswell/Broadwell – AnandTech
- iucode-tool GitLab project
- Intel, AMD, VIA & Freescale CPU Microcode Repositories
- CPUID dumps

分類：​

- CPU
- 安全

微碼
新增話題