PCI通透

簡介

為了架設基於Proxmox VE的伺服器,並讓Proxmox VE所建立的VM能夠存取伺服器的顯示卡資源,我們必須要啟用 PCI通透(PCI Passthrough) 的功能來將PCI的通訊傳遞至VM之中。

前置準備

在開始設定IOMMU之前,我們必須先完成幾項前置作業:

  1. 於BIOS啟動CPU虛擬化功能。[1]
  2. 於BIOS開啟記憶體虛擬化以及相關設置。[2]
  3. 確認PVE是使用GRUB還是systemd-boot作為開機引導。[3]

流程圖

首先,我們透過下方的流程圖來了解設定PCI通透並將GPU分配給VM該如何進行。整個流程主要分成四大部分

  1. 開機引導設置
  2. IOMMU重映射設定
  3. 模組設定
  4. 虛擬機配置設定

詳細流程解說

開機引導設定

根據PVE所使用的開機引導不同,需要進行的設置也有所不同。開機引導主要有兩種:GRUB以及systemd-boot


GRUB

針對GRUB的設定,需要修改/etc/default/grub中的GRUB_CMDLINE_LINUX_DEFAULT參數。根據CPU供應商的不同,設置上也有些微的差異。

AMD CPU

針對AMD CPU,需要在GRUB_CMDLINE_LINUX_DEFAULT加入amd_iommu=on的參數。

#修改前 GRUB_CMDLINE_LINUX_DEFAULT='quiet' #修改後 GRUB_CMDLINE_LINUX_DEFAULT='quiet amd_iommu=on'
Intel CPU

針對Intel CPU,需要在GRUB_CMDLINE_LINUX_DEFAULT加入intel_iommu=on的參數。

#修改前 GRUB_CMDLINE_LINUX_DEFAULT='quiet' #修改後 GRUB_CMDLINE_LINUX_DEFAULT='quiet intel_iommu=on'

systemd-boot

針對systemd-boot的設定,需要在/etc/kernel/cmdline的第一行增加額外的參數。根據CPU供應商的不同,設置上也有些微的差異。

AMD CPU

針對AMD CPU,需要在第一行後方加入amd_iommu=on的參數。

#修改前 root=ZFS=rpool/ROOT/pve-1 boot=zfs #修改後 root=ZFS=rpool/ROOT/pve-1 boot=zfs amd_iommu=on
Intel CPU

針對Intel CPU,需要在第一行後方加入intel_iommu=on的參數。

#修改前 root=ZFS=rpool/ROOT/pve-1 boot=zfs #修改後 root=ZFS=rpool/ROOT/pve-1 boot=zfs intel_iommu=on

更新設定

在完成上方修改之後,需要執行以下指令來更新設定:

proxmox-boot-tool refresh

這些設定將在重新啟動後被套用。

IOMMU重映射設定

對於使用PCI通透來說,設置中斷重映射(Interrupt Remapping)是必要的,若沒有設定這個機制,將無法正確的使用PCI通透的相關功能,並且可能出現以下錯誤訊息:

Failed to assign device "[device name]": Operation not 
permitted' or 'Interrupt Remapping hardware not found, 
passing devices to unprivileged domains is insecure.

大部分的狀況下,無論是AMD或是Intel的CPU都有支援中斷重映射的機制。我們可以透過dmesg | grep 'remapping'來檢查。若有支援,將會跳出以下訊息:

  • AMD CPU: "AMD-Vi: Interrupt remapping enabled"
  • Intel CPU: "DMAR-IR: Enabled IRQ remapping in x2apic mode" ('x2apic' can be different on old CPUs, but should still work)

若檢查後並沒有跳出以上訊息,則需要手動設置。設置方法為將options vfio_iommu_type1 allow_unsafe_interrupts=1參數加入到/etc/modprobe.d/iommu_unsafe_interrupts.conf之中。

echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf

此改動的目的是在CPU平台未提供中斷重映射的機制時,允許使用不安全的中斷方式來進行重映射的中斷。

模組設定

啟用VFIO模組

為了讓硬體設備可以被虛擬機直接取用,還需要額外更改/etc/modules的設定來啟用VFIO模組。只要在/etc/modules中加入以下四行文字即可。

vfio vfio_iommu_type1 vfio_pci vfio_virqfd

將驅動程式加入黑名單避免PVE系統取用顯示卡資源

為了避免PVE系統使用顯示卡資源並排擠到虛擬機的資源,我們需要編輯/etc/modprobe.d/blacklist.conf來使主系統的部分驅動程式無法取用顯示卡資源。

echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf echo "blacklist nvidia" >> /etc/modprobe.d/blacklist.conf

上方列為黑名單的是Nvidia以及與Nvidia顯示卡有關的驅動程式。對於Intel以及AMD顯示卡的部分,可以參考此篇文章中的設定。

將顯示卡資訊寫入於VFIO設定中

為了讓VFIO模組了解哪一個PCI設備是顯示卡,我們需要以下步驟:

  1. 找出顯示卡對應ID

    為了找出顯示卡對應的ID,我們可以使用以下指令:

    ​​​​lspci | grep VGA
    

    以我自己的工作站而言,會有以下結果:

    ​​​​01:00.0 VGA compatible controller: NVIDIA Corporation GA102 [GeForce RTX 3090] (rev a1)
    

    這時,我可以得知我的顯示卡ID為01:00.0

  2. 獲取顯示卡規格

    在取得了顯示卡ID之後,我們便可以利用以下指令取得顯示卡的細部規格:

    ​​​​lspci -n -s 01:00

    以我的工作站來說,結果如以下所示:

    ​​​​root@pve:~# lspci -n -s 01:00 ​​​​01:00.0 0300: 10de:2204 (rev a1) ​​​​01:00.1 0403: 10de:1aef (rev a1)

    上方可以看現兩個結果。其中10de:2204就是我們在上一步驟中所找到的顯示卡;而10de:1aef則是顯示卡所附帶的音效卡。在PCI通透中我們只需要設定顯示卡的部分即可。

  3. 將顯示卡ID以及相關設定寫入/etc/modprobe.d/vfio.conf檔案中

    在上一步中,我們取得了顯示卡ID對應的規格以及編號,接下來我們只需要將上一步取得的10de:2204搭配必要的參數寫入vfio.conf檔案中即可。以下是用以將設定寫入的指令:

    ​​​​echo "options vfio-pci ids=10de:2204" > /etc/modprobe.d/vfio.conf

    如果想要關閉VGA功能,可以在後方加入disable_vga=1參數:

    ​​​​echo "options vfio-pci ids=10de:2204 disable_vga=1" > /etc/modprobe.d/vfio.conf

    在寫入完成後,執行下方指令並重新開機即可套用前述的所有設定。

    ​​​​update-initramfs -u

    在此我們只有示範了最基礎的設定,對於更完整以及更多的設定選擇,可以參考PVE官網所提供的介紹。

虛擬機配置設定

在前幾個部分中,我們已經完成了PCI通透大部分所需要的系統設置。接下來,我們將進行對虛擬機的設定,讓虛擬機可以順利的取用顯示卡資源。

  1. 創建並設定虛擬機的配置

    首先,我們先利用網頁中的Create VM按鈕來建立一個新的虛擬機。

    接下來,將BIOS設定為OVMF(UEFI)模式,並將Machine選項設定為q35。

    在硬碟設定上,可以使用IDEVirtIO Block(但需要額外設定VirtIO driver)。

    在CPU的設定上,核心數量可以自訂,但是必須將Type設置為host以避免出錯。[4]

    完成上述的必要設定之後,只要儲存設定即可完成初步設定。

    完成此步驟後,請先啟動虛擬機,並完成基礎的系統安裝。後續將顯示卡指定至虛擬機時,可能因為disable_vga=1的設定導致PVE預設使用的noVNC無法連線至虛擬機,進而導致無法進行系統安裝。

  2. 指定PCI裝置至虛擬機

    在虛擬機建立後,我們可以到Harware中點選Add來新增PCI device

    然後在選單中選取對應的顯示卡。

    All FunctionsPrimary GPU以及PCI Express選項打勾。

    接下來只要點選Add並啟動虛擬機即可。

參考資料及相關資料

  1. PVE官網對於PCI通透的設定手冊
  2. PVE官網對於Host Bootloader的相關手冊
  3. IOMMU技術介紹
  4. Intel虛擬化技術介紹
  5. 在 VM 裡面使用顯示卡
  6. VFIO介紹
  7. OSSLab的PVE設定教學文章

  1. 於兩大x86平台中分別被稱為Intel VT-X以及AMD SVM。啟用方式可以參考此份介紹 ↩︎

  2. 記憶體虛擬化係指Intel VT-d以及AMD IOMMU技術,其設定依主機板供應商不同而有所差異。AMD在ASRock主機板平台上的設定可以參考此份介紹 ↩︎

  3. 關於如何辨別,可以使用proxmox-boot-tool status指令進行查看。詳細可以參考此篇介紹 ↩︎

  4. 以Tensorflow為例,預設的KVM選項會讓Tensorflow編譯出現錯誤The TensorFlow library was compiled to use SSE4.2 instructions, but these aren't available on your machine. Aborted (core dumped) ↩︎