# PCI通透 [TOC] ## 簡介 為了架設基於[Proxmox VE](https://pve.proxmox.com/wiki/Main_Page)的伺服器,並讓[Proxmox VE](https://pve.proxmox.com/wiki/Main_Page)所建立的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 ``` --- #### 更新設定 在完成上方修改之後,需要執行以下指令來更新設定: ```bash= 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`之中。 ```bash= 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`來使主系統的部分驅動程式無法取用顯示卡資源。 ```bash= echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf echo "blacklist nvidia" >> /etc/modprobe.d/blacklist.conf ``` :::warning 上方列為黑名單的是Nvidia以及與Nvidia顯示卡有關的驅動程式。對於Intel以及AMD顯示卡的部分,可以參考此篇[文章](https://wiki.freedomstu.com/books/proxmox-ve-%E8%99%9B%E6%93%AC%E7%B3%BB%E7%B5%B1%E8%A8%98%E9%8C%84/page/%E5%9C%A8-vm-%E8%A3%A1%E9%9D%A2%E4%BD%BF%E7%94%A8%E9%A1%AF%E7%A4%BA%E5%8D%A1)中的設定。 ::: #### 將顯示卡資訊寫入於VFIO設定中 為了讓VFIO模組了解哪一個PCI設備是顯示卡,我們需要以下步驟: 1. 找出顯示卡對應ID 為了找出顯示卡對應的ID,我們可以使用以下指令: ```bash= lspci | grep VGA ``` 以我自己的工作站而言,會有以下結果: ``` 01:00.0 VGA compatible controller: NVIDIA Corporation GA102 [GeForce RTX 3090] (rev a1) ``` 這時,我可以得知我的顯示卡ID為`01:00.0`。 2. 獲取顯示卡規格 在取得了顯示卡ID之後,我們便可以利用以下指令取得顯示卡的細部規格: ```bash= 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`檔案中即可。以下是用以將設定寫入的指令: ```bash= echo "options vfio-pci ids=10de:2204" > /etc/modprobe.d/vfio.conf ``` 如果想要關閉VGA功能,可以在後方加入`disable_vga=1`參數: ```bash= echo "options vfio-pci ids=10de:2204 disable_vga=1" > /etc/modprobe.d/vfio.conf ``` 在寫入完成後,執行下方指令並重新開機即可套用前述的所有設定。 ```bash= update-initramfs -u ``` :::warning 在此我們只有示範了最基礎的設定,對於更完整以及更多的設定選擇,可以參考[PVE官網](https://pve.proxmox.com/wiki/Pci_passthrough#Required_Modules)所提供的介紹。 ::: ## 虛擬機配置設定 在前幾個部分中,我們已經完成了PCI通透大部分所需要的系統設置。接下來,我們將進行對虛擬機的設定,讓虛擬機可以順利的取用顯示卡資源。 1. 創建並設定虛擬機的配置 首先,我們先利用網頁中的`Create VM`按鈕來建立一個新的虛擬機。  接下來,將BIOS設定為`OVMF(UEFI)`模式,並將`Machine`選項設定為q35。  在硬碟設定上,可以使用`IDE`或`VirtIO Block`(但需要額外設定VirtIO driver)。  在CPU的設定上,核心數量可以自訂,但是必須將`Type`設置為`host`以避免出錯。[^4]  完成上述的必要設定之後,只要儲存設定即可完成初步設定。 :::warning 完成此步驟後,請先啟動虛擬機,並完成基礎的系統安裝。後續將顯示卡指定至虛擬機時,可能因為`disable_vga=1`的設定導致PVE預設使用的`noVNC`無法連線至虛擬機,進而導致無法進行系統安裝。 ::: 2. 指定PCI裝置至虛擬機 在虛擬機建立後,我們可以到`Harware`中點選`Add`來新增`PCI device`。  然後在選單中選取對應的顯示卡。  將`All Functions`、`Primary GPU`以及`PCI Express`選項打勾。  接下來只要點選`Add`並啟動虛擬機即可。 ## 參考資料及相關資料 1. PVE官網對於PCI通透的[設定手冊](https://pve.proxmox.com/wiki/Pci_passthrough#Required_Modules)。 2. PVE官網對於Host Bootloader的[相關手冊](https://pve.proxmox.com/wiki/Host_Bootloader)。 3. IOMMU技術[介紹](https://zhuanlan.zhihu.com/p/348826888)。 4. Intel虛擬化技術[介紹](https://www.intel.com.tw/content/www/tw/zh/virtualization/virtualization-technology/intel-virtualization-technology.html)。 5. [在 VM 裡面使用顯示卡 ](https://wiki.freedomstu.com/books/proxmox-ve-%E8%99%9B%E6%93%AC%E7%B3%BB%E7%B5%B1%E8%A8%98%E9%8C%84/page/%E5%9C%A8-vm-%E8%A3%A1%E9%9D%A2%E4%BD%BF%E7%94%A8%E9%A1%AF%E7%A4%BA%E5%8D%A1) 6. VFIO[介紹](https://www.kernel.org/doc/html/latest/driver-api/vfio.html) 7. OSSLab的PVE設定[教學文章](https://www.osslab.com.tw/proxmox-ve-pci-e-pass/) [^1]: 於兩大x86平台中分別被稱為Intel VT-X以及AMD SVM。啟用方式可以參考此份[介紹](https://bce.berkeley.edu/enabling-virtualization-in-your-pc-bios.html)。 [^2]: 記憶體虛擬化係指Intel VT-d以及AMD IOMMU技術,其設定依主機板供應商不同而有所差異。AMD在ASRock主機板平台上的設定可以參考此份[介紹](https://www.reddit.com/r/VFIO/comments/cm6xme/comment/ew0r5x7/?utm_source=share&utm_medium=web2x&context=3)。 [^3]: 關於如何辨別,可以使用`proxmox-boot-tool status`指令進行查看。詳細可以參考此篇[介紹](https://pve.proxmox.com/wiki/Host_Bootloader)。 [^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)`。
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.