Come passare completamente la gestione di una periferica USB da un sistema virtualizzante (host) QEMU (GNU/Linux con KVM) ad un sistema virtualizzato (guest) Windows 10. Procedura sperimentata su Debian GNU/Linux 11 Bullseye.
Il programma emulatore qemu-system-x86_64 deve sapere quale periferica USB deve essere collegata alla macchina guest. È possibile identificare la periferica in tre modi diversi:
Consideriamo come esempio un lettore di flash card. Inserendo il dispositivo in una porta USB, il sistema ospitante GNU/Linux lo identifica come segue (output del comando lsusb):
Bus 001 Device 026: ID 05e3:0723 Genesys Logic, Inc. GL827L SD/MMC/MS Flash Card Reader
In particolare notiamo:
Se vogliamo conoscere la posizione fisica sul bus USB utilizziamo il comando lsusb -t:
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M |__ Port 1: Dev 26, If 0, Class=Mass Storage, Driver=usbfs, 480M
In questo caso notiamo:
È possibile eseguire il programma qemu-system-x86_64
da utente non privilegiato, ma l'emulatore dovrà avere pieno accesso alla periferica USB di cui si desidera il passthrough a Windows. Dopo aver identificato hostbus e hostaddr assegnati dal kernel alla periferica, l'utente root potrà assegnare i permessi necessari. Ad esempio con:
chmod 0666 /dev/bus/usb/001/026
È possibile configurare il sistema in modo tale che una determinata periferica riceva automaticamente gli opportuni permessi ad ogni connessione. Ad esempio si potrebbe volere che la periferica sia in lettura/scrittura per gli utenti che appartengono al gruppo plugdev (in Debian è il gruppo degli utenti autorizzati a montare e smontare i dispostivi rimuovibili). Per ottenere questo risultato si crea un file ad esempio /etc/udev/rules.d/99-flash-card-reader.rules con il seguente contenuto:
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="05e3", ATTR{idProduct}=="0723", GROUP="plugdev", MODE="0660"
Per forzare il sistema udev a rileggere i file di configurazione si esegue:
udevadm control --reload-rules && udevadm trigger
Alla successiva connessione della periferica si può verificare che abbia ricevuto i giusti permessi.
Se la periferica è già collegata all'host al momento dell'avvio di QEMU, è possibile passare dalla riga di comando gli opportuni parametri all'emulatore qemu-system-x86_64, in modo che la periferica venga aggiunta e compaia in Gesione dispositivi. Qui di seguito i parametri per fare il passthrough della periferica identificandola in uno dei tre modi possibili:
-usb -device usb-host,vendorid=0x05e3,productid=0x0723
-usb -device usb-host,hostbus=1,hostaddr=26
-usb -device usb-host,hostbus=1,hostport=1.1'
Ecco una riga di comando minimale, ma completa per avviare l'emulatore:
qemu-system-x86_64 -m 4096 -machine accel=kvm \ -device qemu-xhci \ -usb -device 'usb-host,vendorid=0x05e3,productid=0x0723' \ -drive 'file=win10_64bit_c.img,format=raw' -boot c
Notare la presenza del device qemu-xhci; se la macchina ospite supporta le specifiche hardware XHCI (ogni macchina successiva al 2010 dovrebbe) è opportuno caricare tale emulazione, che supporta con un solo controller le periferiche USB 1.1, USB 2.0 e USB 3.0. Utilizzando questo driver non è necessario aggiungere la specifica bus={usb-bus.0|ehci.0}
nei comandi che aggiungono le periferiche USB. Senza esplicitare quel device l'emulazione delle periferiche USB 3.0 non funziona e la periferica compare in Gestione dispositivi di Windows con un triangolo giallo con punto esclamativo.
Se la periferica USB viene collegata dopo che QEMU è stato avviato, è possibile utilzzare la console di QEMU per aggiungere la periferica al sistema Windows guest.
Attivando Show Tabs dal menu View di QEMU sarà possibile accedere alla console compat_monitor0, quindi si possono eseguire i comandi info usbhost per verificare che a periferica sia stata riconosciuta:
(qemu) info usbhost Bus 1, Addr 26, Port 1.1, Speed 480 Mb/s Class 00: USB device 05e3:0723, USB Storage
ATTENZIONE! Se QEMU non ha identificato correttamente il tipo della periferica (USB Storage in questo caso), è possibile che manchino i permessi di lettura/scrittura sulla periferica stessa.
A questo punto la periferica può essere aggiunta con un comando del tipo:
(qemu) device_add usb-host,vendorid=0x05e3,productid=0x0723
Immediatamente il Gestione dispositivi di Windows dovrebbe riconoscere la nuova periferica.