summaryrefslogtreecommitdiffstats
path: root/doc/pcie_passthrough.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/pcie_passthrough.tex')
-rw-r--r--doc/pcie_passthrough.tex233
1 files changed, 233 insertions, 0 deletions
diff --git a/doc/pcie_passthrough.tex b/doc/pcie_passthrough.tex
new file mode 100644
index 0000000..1528593
--- /dev/null
+++ b/doc/pcie_passthrough.tex
@@ -0,0 +1,233 @@
+\documentclass[a4paper,10pt]{article}
+
+\usepackage[outer=2cm,inner=2cm]{geometry}
+\usepackage[hidelinks]{hyperref}
+\usepackage{framed}
+\usepackage{lmodern}
+
+\usepackage{fontspec}
+\usepackage{ragged2e}
+\setmainfont{Latin Modern Mono}
+
+\title{PCIe GPU passthrough on Debian}
+\author{Nao Pross}
+
+\begin{document}\tt
+ \maketitle
+
+ \section{Introduzione}
+ Recentemente grazie all'evoluzione delle tecnologie di virtualizzazione \`e
+ diventato possibile passare direttamente un dispositivo collegato in uno
+ slot PCI ad una macchina virtuale, che può quindi usufruire dell'hardware a
+ performance quasi nativa. Un computer configurato per funzionare in tale
+ maniera apparirà come se fossero due computer distinti con due monitors (o
+ ad uno con un kvm switch). Il vantaggio di un setup del genere è la
+ possibilità di cambiare immediatamente da un sistema operativo all’altro
+ senza dover attendere che ma macchina si riavvii (in un dualboot) e si
+ evitano potenziali problemi come Windows Update che rendono il PC inusabile.
+
+ \section{Limitazioni}
+ Come ogni sistema si ha delle limitazioni quali
+ \begin{itemize}
+ \item Per poter vedere l'uscita video della VM si deve collegare un
+ display ad una delle uscite della scheda grafica passata
+ \item Non \`e possibile passare la iGPU ad una VM (\`e possibile ma con
+ altre tecnologie ancora sperimentali)
+ \item Non \`e possibile passare una GPU discreta di un laptop (es NVIDIA
+ Optimus) poich\`e non \`e possibile visualizzare il video in uscita
+ \end{itemize}
+
+ \section{Funzionamento (In grandi linee)}
+ Le macchine virtuali vengono emulate grazie ad un software chiamato QEMU che
+ supporta il passaggio di hardware PCI alla VM, inoltre QEMU utilizza un
+ estensione chiamata KVM che permette di creare delle macchine virtuali
+ collegate alla kernel dunque ottimizzate. Altrimenti QEMU dovrebbe emulare
+ l’intero processore su cui viene virtualizzato il sistema operativo. Infine
+ per gestire questi due componenti LibVirt è un software che salva le
+ configurazioni di QEMU in dei file XML e che permette alle VM di essere
+ tenute accese in background. \\
+
+ Passando una scheda video in PCI ad una macchina virtuale permette di
+ utilizzare la potenza grafica hardware che sarebbe altrimenti emulata (le
+ grafichce virtuali di QEMU non sono per niente ottimizzate, per tali scopi è
+ meglio utilizzare VirtualBox o VMWare Fusion). Quindi per poter vedere la
+ grafica della macchina virtuale si deve collegare un monitor ad una delle
+ entrate della scheda video.
+
+ \section{Hardware Requirements}
+ \begin{itemize}
+ \item Intel processor with iGPU (or 2 GPUs)
+ \item Processor with VT-x and VT-d
+ \item NVIDIA or AMD graphics card (2 if with no iGPU)
+ \item Motherboard with VT-d support
+ \item Motherboard with UEFI based bootloader
+ \item Motherboard with IOMMU support (per configurazioni avanzate)
+ \end{itemize}
+
+ \section{Software Requirements}
+ \begin{itemize}
+ \item Linux Kernel with iommu\_groups support ( kernel >= 3.9 )
+ \end{itemize}
+
+ \section{Hardware utilizzato}
+ Per questo questo test ho usato una configurazione hardware esagerata, anche
+ con un sistema decisamente meno costoso \`e possibile realizzare il
+ progetto.
+ \begin{itemize}
+ \item ASUS Z170-A motherboard
+ \item Intel Core i7 Skylake 6700 CPU with Intel Graphics 530
+ \item MSI NVIDIA GTX1050Ti OC 4GB
+ \item 32GB DDR4
+ \end{itemize}
+
+ \section{BIOS Settings}
+ Per incominciare è necessario controllare che nel BIOS siano attivate le
+ tecnologie di virtualizzazione VT-x e VT-d. Inoltre se si vuole utilizzare
+ la iGPU in alcune motherboard (come nel mio caso) si deve modificare un
+ impostazione nel bios per non disattivarla qundo viene inserita una scheda
+ grafica secondaria.
+
+ \section{Sistema Operativo}
+ Per avere un sistema stabile consiglio di utilizzare Debian Linux poiché
+ essendo utilizzato soprattuto nei servers il ciclo di testing e updates è
+ molto lento in modo da avere sempre un supporto legacy e un sistema stabile.
+ Purtroppo però attualmente (12.2016) Debian 8 Jessie ha ancora la kernel
+ 3.16 quindi si deve abilitare il supporto backport per poter installare una
+ versione aggiornata della kernel. \\
+
+ Prima di installare il sistema operativo è consigliato rimuovere la GPU che
+ si utilizzerà per il passthrough dallo slot PCI per evitare che Linux si
+ autoconfiguri per utilizzare i suoi driver grafici. Una volta installato il
+ sistema si devono installare i seguenti pacchetti:
+ \begin{framed}\raggedright
+ \% sudo apt-get install \textbackslash \\
+ ~ qemu-kvm libvirt-bin virtinst bridge-utils virt-manager ssh-askpass ovmf
+ \end{framed}
+
+ \section{Kernel Modules and GRUB}
+ Normalmente Debian viene con GRUB2 preinstallato come bootloader, se si
+ dovesse avere un altro bootloader si deve semplicemente passare gli stessi
+ parametri alla kernel quando si avvia. \\
+
+ Dalla kernel 3.9 Linux ha introdotto gli iommu\_groups che permettono di
+ mappare dispositivi di memoria reale ad indirizzi virtuali che possono
+ essere a loro volta passati alla VM. Per poter utilizzare questa
+ funzionalit\`a la si deve abilitare inoltre \`e necessario anche il supporto
+ degli ACS per poter suddividere i sottocomponenti del gruppo iommu (per
+ esempio le porte individuali di un estensione di USB via PCI). Per attivare
+ le funzionalit\`a si deve passare alla kernel i seguenti parametri:
+ \begin{framed}\raggedright \footnotesize
+ \# file: /etc/default/grub \\
+ ... \\
+ GRUB\_DEFAULT\_CMDLINE\_LINUX\_DEFAULT="intel\_iommu=on iommu=1 pcie\_acs\_override=downstream" \\
+ ...
+ \end{framed}
+ Per aggiornale le impostazioni installate
+ \begin{framed}\raggedright
+ \% sudo update-grub
+ \end{framed}
+
+ \section{GPU Settings}
+ Per evitare che Debian utilizzi la GPU all’avvio si deve modificare le
+ impostazioni dell’initramfs in maniera tale che il modulo della kernel non
+ venga avviato. Per sapere il nome del modulo della kernel caricato per la
+ GPU si può usare il seguente comando (nel mio caso la scheda è una NVIDIA):
+ \begin{framed}\raggedright \scriptsize
+ \% lspci -nnk | grep -i -A2 nvidia \\
+ 02:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP107 [GeForce GTX 1050 Ti] [10de:1c82] (rev a1) \\
+ ~~~~~~~~Subsystem: Micro-Star International Co., Ltd. [MSI] GP107 [GeForce GTX 1050 Ti] [1462:8c96] \\
+ ~~~~~~~~Kernel driver in use: nouveau \\
+ -- \\
+ 02:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:0fb9] (rev a1) \\
+ ~~~~~~~~Subsystem: Micro-Star International Co., Ltd. [MSI] Device [1462:8c96] \\
+ ~~~~~~~~Kernel driver in use: snd\_hda\_intel
+ \end{framed}
+ Nel file di configurazione
+ \begin{framed}\raggedright
+ \# file: /etc/modprobe.d/blacklist.conf \\
+ ... \\
+ blacklist nouveau
+ \end{framed}
+ Infine per aggiornare la configurazione
+ \begin{framed}\raggedright
+ \% sudo update-initramfs -u
+ \end{framed}
+
+ \section{Driver binding}
+ Per passare un dispositivo ad una VM si deve indicare alla kernel di
+ utilizzare il modulo `vfio-pci', perci\`o \`e necessario inizializzare
+ questi dispositivi all'avvio. Per questo possiamo usare questo script preso
+ da \href{https://www.reddit.com/r/pcmasterrace/comments/3lno0t/gpu_passthrough_revisited_an_updated_guide_on_how/?ref=share&ref_source=link}{qui}
+ salvandolo come `/usr/local/bin/vfio-bind'.
+ \begin{framed}\raggedright
+ \# file: /usr/local/bin/vfio-bind
+ \begin{verbatim}
+#!/bin/bash
+
+modprobe vfio-pci
+
+for dev in "$@"; do
+ vendor=$(cat /sys/bus/pci/devices/$dev/vendor)
+ device=$(cat /sys/bus/pci/devices/$dev/device)
+ if [ -e /sys/bus/pci/devices/$dev/driver ]; then
+ echo $dev > /sys/bus/pci/devices/$dev/driver/unbind
+ fi
+ echo $vendor $device > /sys/bus/pci/drivers/vfio-pci/new_id
+done \end{verbatim}
+ \end{framed}
+ Attivando la flag per poterlo eseguire:
+ \begin{framed}\raggedright
+ \% sudo chmod +x /usr/local/bin/vfio-bind
+ \end{framed}
+ Con questo script possiamo collegare il driver per la virtualizzazione a
+ qualsiasi dispositivo PCI nella seguente maniera:
+ \begin{framed}\raggedright
+ \% sudo vfio-bind <indirizzi pci>
+ \end{framed}
+ Per trovare l'indizirro dei dispositivi che vogliamo passare utilizziamo di
+ nuovo il seguente comando:
+ \begin{framed}\raggedright \scriptsize
+ \% lspci -nnk | grep -i -A2 nvidia \\
+ 02:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP107 [GeForce GTX 1050 Ti] [10de:1c82] (rev a1) \\
+ ~~~~~~~~Subsystem: Micro-Star International Co., Ltd. [MSI] GP107 [GeForce GTX 1050 Ti] [1462:8c96] \\
+ ~~~~~~~~Kernel driver in use: nouveau \\
+ -- \\
+ 02:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:0fb9] (rev a1) \\
+ ~~~~~~~~Subsystem: Micro-Star International Co., Ltd. [MSI] Device [1462:8c96] \\
+ ~~~~~~~~Kernel driver in use: snd\_hda\_intel
+ \end{framed}
+ Nel mio caso gli indirizzi da passare alla VM sono `0000:02:00.0' per il
+ video e `0000:02:00.1' per l'audio. Successivamente possiamo automatizzare
+ la configurazione in modo che il driver per la virtualizzazione venga
+ avviato subito all'avvio della macchina. Quindi lo facciamo con una unit di
+ SystemD.
+ \begin{framed}\raggedright
+ \# file: /etc/systemd/system/vfio-pci-bind.service
+
+ \begin{verbatim}
+[Unit]
+Description=Bind PCI devices to the virtio driver
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/vfio-bind 0000:02:00.0 0000:02:00.1
+
+[Install]
+WantedBy=multi-user.target
+Before=libvirt-guests.service \end{verbatim}
+ \end{framed}
+
+ \section*{Appendici}
+ \subsection*{i915 Skylake iGPU support} \label{skylakeigpu}
+ Attualmente (12.2016) i driver grafici per i nuovi processori intel di
+ architettura skylake sono disponibili e relativamente stabili dalle kernel
+ 4.7+, quindi nella mia installazione di debian ho deciso di utilizzare il
+ backport della kernel 4.8.0. Per abilitare i backports si deve aggiungere
+ un nuovo repo nel file `/etc/apt/sources.list'.
+ \begin{framed}\raggedright
+ \# file: /etc/apt/sources.list \\
+ deb http://ftp.debian.org/debian jessie-backports main non-free
+ \end{framed}
+ Successivamente si deve aggiornare la kernel e i driver grafici mesa
+
+\end{document}