kvm vga passthrough
My setup for VGA passthrough with KVM
I wanted to experiment with VGA passthrough once again on Linux. In addition to the doing the VGA passthrough I wanted to:
- have a convenient way of passing input back and forth
- forward certain controllers directly to the VM
- force cpu pinning
This is a cheatsheet for the resources used, as well as the configuration options I ended up with.
Dependencies
In addition to the userland applications (virt-manager, qemu, etc) and services certain kernel options must be enabled:
- https://wiki.gentoo.org/wiki/GPU_passthrough_with_libvirt_qemu_kvm
- https://wiki.gentoo.org/wiki/Evdev
- https://wiki.gentoo.org/wiki/QEMU
Once the setup is complete one can check it via the kvm-ok
script provided by the cpu-checker package (https://manpages.ubuntu.com/manpages/xenial/man1/kvm-ok.1.html)
grub configuration
First we need to determine the ids of the pci devices we wish to passthrough (via lspci -nn), and append them to the GRUB_CMDLINE_LINUX in /etc/default/grub:
iommu=on iommu=pt amd_iommu=on pcie_acs_override=downstream,multifunction kvm.ignore_msrs=1 vfio-pci.ids=10de:1b81,10de:10f0
dracut
add the following to /etc/dracut.conf.d/vfio.conf
hostonly="yes"
hostonly_cmdline="amd_iommu=on iommu=pt"
force_drivers+="vfio_pci vfio vfio_iommu_type1 vfio_virqfd"
polkit
add
daemon without authentication */
polkit.addRule(function(action, subject) {
if (action.id == "org.libvirt.unix.manage" &&
subject.isInGroup("kvm")) {
return polkit.Result.YES;
}
});
to /etc/polkit-1/rules.d/50-libvirt.rules
qemu.conf
Make sure that the user and group are set correctly
add the devices to be managed by evdev to the list
cgroup_device_acl
, in my case:cgroup_device_acl = [ "/dev/null", "/dev/full", "/dev/zero", "/dev/random", "/dev/urandom", "/dev/ptmx", "/dev/kvm", "/dev/input/by-id/usb-04d9_USB_Keyboard-event-kbd", "/dev/input/by-id/usb-Corsair_Corsair_Gaming_M65_Pro_RGB_Mouse_0C04201CAF0C904259322463F5001942-event-mouse" ]
uncomment
nographics_allow_host_audio = 1
/etc/libvirt/libvirtd.conf
unix_sock_group = "libvirt"
unix_sock_rw_perms = "0770"
/etc/libvirt/libvirt.conf
uri_default = "qemu:///system"
Add user to kvm and libvirt groups
gpasswd -a tse kvm
gpasswd -a tse libvirt
virtual machine .xml
We now need to configure the virtual machine so that we can make use of evdev to pass the devices back and forth to the virtual machine EDITOR=vim virsh edit win10
and add the following, before closing the domain
tag:
<qemu:commandline>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=kbd1,evdev=/dev/input/by-id/usb-04d9_USB_Keyboard-event-kbd,grab_all=on,repeat=on'/>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=kbd21,evdev=/dev/input/by-id/ckb-Corsair_Gaming_M65_Pro_RGB_Mouse_vKB_-event'/>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=mouse1,evdev=/dev/input/by-id/ckb-Corsair_Gaming_M65_Pro_RGB_Mouse_vM_-event'/>
<qemu:arg value='-audiodev'/>
<qemu:arg value='pa,id=snd0,server=/run/user/1000/pulse/native'/>
<qemu:arg value='-mem-path'/>
<qemu:arg value='/mnt/hugepages/'/>
</qemu:commandline>
This also enables hugepages (https://wiki.debian.org/Hugepages).
nvidia error 43
If you get the nvidia error 43 it can be fixed by adding the vendor_id
tag under hyperv
:
<vendor_id state='on' value='123456789ab'/>
and the following needs needs to be added to the features
(after hyperv
) tag:
<kvm>
<hidden state='on'/>
</kvm>
<ioapic driver='kvm'/>
CPU Pinning
In order to enable CPU pinning add the following:
<vcpu placement='static'>16</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='12'/>
<vcpupin vcpu='2' cpuset='1'/>
<vcpupin vcpu='3' cpuset='13'/>
<vcpupin vcpu='4' cpuset='2'/>
<vcpupin vcpu='5' cpuset='14'/>
<vcpupin vcpu='6' cpuset='3'/>
<vcpupin vcpu='8' cpuset='15'/>
<vcpupin vcpu='9' cpuset='4'/>
<vcpupin vcpu='10' cpuset='16'/>
<vcpupin vcpu='11' cpuset='5'/>
<vcpupin vcpu='12' cpuset='17'/>
<vcpupin vcpu='13' cpuset='6'/>
<vcpupin vcpu='14' cpuset='18'/>
<vcpupin vcpu='15' cpuset='7'/>
<emulatorpin cpuset='0,19'/>
</cputune>
(https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF#CPU_pinning)
using VirtIO for mouse/keyboard:
https://passthroughpo.st/using-evdev-passthrough-seamless-vm-input/
<input type='mouse' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/>
</input>
<input type='keyboard' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
Audio
In virt-manager I added the audio interface (kingston hyperx) to the vm.
USB controller
In order to have usb devices being automatically detected by the vm I decided to pass a usb controller.
1) list usb controllers:
lspci |grep -i usb
2) list all the iommu groups (iommu_groups.sh
) and make sure that we have a usb controller in an IOMMU group by itself:
#!/bin/bash
#https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF#Setting_up_IOMMU
shopt -s nullglob
for g in /sys/kernel/iommu_groups/*; do
echo "IOMMU Group ${g##*/}:"
for d in $g/devices/*; do
echo -e "\t$(lspci -nns ${d##*/})"
done;
done;
3) using the device_to_group.sh
script check if the peripherals are connected to the correct controller:
#!/bin/bash
# from https://mathiashueber.com/usb-device-passthrough-setup-virtual-machines/
for usb_ctrl in $(find /sys/bus/usb/devices/usb* -maxdepth 0 -type l); do pci_path="$(dirname "$(realpath "${usb_ctrl}")")"; echo "Bus $(cat "${usb_ctrl}/busnum") --> $(basename $pci_path) (IOMMU group $(basename $(realpath $pci_path/iommu_group)))"; lsusb -s "$(cat "${usb_ctrl}/busnum"):"; echo; done
add devices in virt-manager
Once the usb controller pci device has been identified (together with the graphical card) they should be added in virt-manager (in my case 30:00.3
- usb controller -, 2e:00.0
and 2e:00.1
- nvidia -).
Startup script:
#!/bin/bash
if [ "${1}" = "start" ]; then
mount /mnt/hugepages
su -c 'sysctl vm.nr_hugepages=8192'
# virsh -c qemu:///system start win10
virsh -c qemu:///system create win10.xml
exit 0
fi
if [ "${1}" = "stop" ]; then
umount /mnt/hugepages
su -c 'sysctl vm.nr_hugepages=0'
exit 0
fi
echo "specify start or stop"
exit 1
win10.xml
version 1:
<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
virsh edit win10
or other application using the libvirt API.
-->
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name>win10</name>
<uuid>5cbb13f2-969f-4e74-8d63-6b938f35004b</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/10"/>
</libosinfo:libosinfo>
</metadata>
<memory unit='KiB'>16777216</memory>
<currentMemory unit='KiB'>16777216</currentMemory>
<vcpu placement='static'>16</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='12'/>
<vcpupin vcpu='2' cpuset='1'/>
<vcpupin vcpu='3' cpuset='13'/>
<vcpupin vcpu='4' cpuset='2'/>
<vcpupin vcpu='5' cpuset='14'/>
<vcpupin vcpu='6' cpuset='3'/>
<vcpupin vcpu='8' cpuset='15'/>
<vcpupin vcpu='9' cpuset='4'/>
<vcpupin vcpu='10' cpuset='16'/>
<vcpupin vcpu='11' cpuset='5'/>
<vcpupin vcpu='12' cpuset='17'/>
<vcpupin vcpu='13' cpuset='6'/>
<vcpupin vcpu='14' cpuset='18'/>
<vcpupin vcpu='15' cpuset='7'/>
<emulatorpin cpuset='0,19'/>
</cputune>
<os>
<type arch='x86_64' machine='pc-q35-5.1'>hvm</type>
<loader readonly='yes' type='pflash'>/usr/share/qemu/edk2-x86_64-code.fd</loader>
<nvram>/var/lib/libvirt/qemu/nvram/win10_VARS.fd</nvram>
</os>
<features>
<acpi/>
<apic/>
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vendor_id state='on' value='123456789ab'/>
</hyperv>
<kvm>
<hidden state='on'/>
</kvm>
<vmport state='off'/>
<ioapic driver='kvm'/>
</features>
<cpu mode='host-model' check='partial'>
<topology sockets='1' dies='1' cores='8' threads='2'/>
</cpu>
<clock offset='localtime'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
<timer name='hypervclock' present='yes'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/home/tse/Downloads/Win10_20H2_English_x64.iso'/>
<target dev='sdb' bus='sata'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<disk type='block' device='disk'>
<driver name='qemu' type='raw' cache='none' io='native'/>
<source dev='/dev/disk/by-id/nvme-eui.6479a73cd229cc55'/>
<target dev='sdc' bus='sata'/>
<boot order='1'/>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</disk>
<controller type='usb' index='0' model='qemu-xhci' ports='15'>
<address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
</controller>
<controller type='usb' index='1' model='nec-xhci'>
<address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>
</controller>
<controller type='sata' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pcie-root'/>
<controller type='pci' index='1' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='1' port='0x8'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/>
</controller>
<controller type='pci' index='2' model='pcie-to-pci-bridge'>
<model name='pcie-pci-bridge'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</controller>
<controller type='pci' index='3' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='3' port='0x9'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='4' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='4' port='0xa'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='5' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='5' port='0xb'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x3'/>
</controller>
<controller type='pci' index='6' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='6' port='0xc'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x4'/>
</controller>
<controller type='pci' index='7' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='7' port='0xd'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x5'/>
</controller>
<controller type='pci' index='8' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='8' port='0xe'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x6'/>
</controller>
<controller type='virtio-serial' index='0'>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</controller>
<controller type='pci' index='9' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='9' port='0xf'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x7'/>
</controller>
<interface type='network'>
<mac address='52:54:00:14:80:dc'/>
<source network='default'/>
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/>
</interface>
<serial type='pty'>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<input type='mouse' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/>
</input>
<input type='keyboard' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x2e' slot='0x00' function='0x0'/>
</source>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x2e' slot='0x00' function='0x1'/>
</source>
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<vendor id='0x0951'/>
<product id='0x16a4'/>
</source>
<address type='usb' bus='0' port='3'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x30' slot='0x00' function='0x3'/>
</source>
<address type='pci' domain='0x0000' bus='0x09' slot='0x00' function='0x0'/>
</hostdev>
<redirdev bus='usb' type='spicevmc'>
<address type='usb' bus='0' port='1'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<address type='usb' bus='0' port='2'/>
</redirdev>
<hub type='usb'>
<address type='usb' bus='0' port='5'/>
</hub>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</memballoon>
</devices>
<qemu:commandline>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=kbd1,evdev=/dev/input/by-id/usb-04d9_USB_Keyboard-event-kbd,grab_all=on,repeat=on'/>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=kbd21,evdev=/dev/input/by-id/ckb-Corsair_Gaming_M65_Pro_RGB_Mouse_vKB_-event'/>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=mouse1,evdev=/dev/input/by-id/ckb-Corsair_Gaming_M65_Pro_RGB_Mouse_vM_-event'/>
<qemu:arg value='-audiodev'/>
<qemu:arg value='pa,id=snd0,server=/run/user/1000/pulse/native'/>
<qemu:arg value='-mem-path'/>
<qemu:arg value='/mnt/hugepages/'/>
</qemu:commandline>
</domain>
version 2
<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
virsh edit win10
or other application using the libvirt API.
-->
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name>win10</name>
<uuid>5cbb13f2-969f-4e74-8d63-6b938f35004b</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://microsoft.com/win/10"/>
</libosinfo:libosinfo>
</metadata>
<memory unit='KiB'>16777216</memory>
<currentMemory unit='KiB'>16777216</currentMemory>
<vcpu placement='static'>16</vcpu>
<cputune>
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='12'/>
<vcpupin vcpu='2' cpuset='1'/>
<vcpupin vcpu='3' cpuset='13'/>
<vcpupin vcpu='4' cpuset='2'/>
<vcpupin vcpu='5' cpuset='14'/>
<vcpupin vcpu='6' cpuset='3'/>
<vcpupin vcpu='8' cpuset='15'/>
<vcpupin vcpu='9' cpuset='4'/>
<vcpupin vcpu='10' cpuset='16'/>
<vcpupin vcpu='11' cpuset='5'/>
<vcpupin vcpu='12' cpuset='17'/>
<vcpupin vcpu='13' cpuset='6'/>
<vcpupin vcpu='14' cpuset='18'/>
<vcpupin vcpu='15' cpuset='7'/>
<emulatorpin cpuset='0,19'/>
</cputune>
<os>
<type arch='x86_64' machine='pc-q35-5.1'>hvm</type>
<loader readonly='yes' type='pflash'>/usr/share/qemu/edk2-x86_64-code.fd</loader>
<nvram>/var/lib/libvirt/qemu/nvram/win10_VARS.fd</nvram>
</os>
<features>
<acpi/>
<apic/>
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vendor_id state='on' value='123456789ab'/>
</hyperv>
<kvm>
<hidden state='on'/>
</kvm>
<vmport state='off'/>
<ioapic driver='kvm'/>
</features>
<cpu mode='host-model' check='partial'>
<topology sockets='1' dies='1' cores='8' threads='2'/>
</cpu>
<clock offset='localtime'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
<timer name='hypervclock' present='yes'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/home/tse/Downloads/Win10_20H2_English_x64.iso'/>
<target dev='sdb' bus='sata'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<disk type='block' device='disk'>
<driver name='qemu' type='raw' cache='none' io='native'/>
<source dev='/dev/disk/by-id/nvme-eui.6479a73cd229cc55'/>
<target dev='sdc' bus='sata'/>
<boot order='1'/>
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
</disk>
<controller type='usb' index='0' model='qemu-xhci' ports='15'>
<address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
</controller>
<controller type='usb' index='1' model='nec-xhci'>
<address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>
</controller>
<controller type='sata' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pcie-root'/>
<controller type='pci' index='1' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='1' port='0x8'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/>
</controller>
<controller type='pci' index='2' model='pcie-to-pci-bridge'>
<model name='pcie-pci-bridge'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</controller>
<controller type='pci' index='3' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='3' port='0x9'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='4' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='4' port='0xa'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='5' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='5' port='0xb'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x3'/>
</controller>
<controller type='pci' index='6' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='6' port='0xc'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x4'/>
</controller>
<controller type='pci' index='7' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='7' port='0xd'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x5'/>
</controller>
<controller type='pci' index='8' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='8' port='0xe'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x6'/>
</controller>
<controller type='virtio-serial' index='0'>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</controller>
<controller type='pci' index='9' model='pcie-root-port'>
<model name='pcie-root-port'/>
<target chassis='9' port='0xf'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x7'/>
</controller>
<interface type='network'>
<mac address='52:54:00:14:80:dc'/>
<source network='default'/>
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/>
</interface>
<serial type='pty'>
<target type='isa-serial' port='0'>
<model name='isa-serial'/>
</target>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<input type='mouse' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/>
</input>
<input type='keyboard' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x2e' slot='0x00' function='0x0'/>
</source>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x2e' slot='0x00' function='0x1'/>
</source>
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/>
</hostdev>
<!--
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<vendor id='0x0951'/>
<product id='0x16a4'/>
<!- - <address type='usb' bus='1' device='2'/> - ->
<!- - <address type='usb' bus='3' device='5'/> - ->
</source>
</hostdev>
-->
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x30' slot='0x00' function='0x3'/>
</source>
<address type='pci' domain='0x0000' bus='0x09' slot='0x00' function='0x0'/>
</hostdev>
<redirdev bus='usb' type='spicevmc'>
<address type='usb' bus='0' port='1'/>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
<address type='usb' bus='0' port='2'/>
</redirdev>
<hub type='usb'>
<address type='usb' bus='0' port='5'/>
</hub>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
</memballoon>
</devices>
<memoryBacking>
<hugepages>
<page size='2048' unit='KiB'/>
</hugepages>
<source type="file"/>
<!--
<nosharepages/>
<locked/>
<access mode="private"/>
-->
</memoryBacking>
<qemu:commandline>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=kbd1,evdev=/dev/input/by-id/usb-04d9_USB_Keyboard-event-kbd,grab_all=on,repeat=on'/>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=kbd21,evdev=/dev/input/by-id/ckb-Corsair_Gaming_M65_Pro_RGB_Mouse_vKB_-event'/>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=mouse1,evdev=/dev/input/by-id/ckb-Corsair_Gaming_M65_Pro_RGB_Mouse_vM_-event'/>
<qemu:arg value='-audiodev'/>
<qemu:arg value='pa,id=snd0,server=/run/user/1000/pulse/native'/>
<!-- start of new stuff
<qemu:arg value='-machine'/>
<qemu:arg value='memory-backend=pc.ram'/>
-->
<!--
<qemu:arg value='-object'/>
<qemu:arg value='memory-backend-memfd,id=pc.ram,hugetlb=yes,hugetlbsize=2097152,size=16777216'/>
-->
<!--
<qemu:arg value='-object'/>
<qemu:arg value='memory-backend-file,id=pc.ram,size=16G,mem-path=/mnt/hugepages'/>
-->
<!-- end of new stuff -->
<!-- old
<qemu:arg value='-mem-path'/>
<qemu:arg value='/mnt/hugepages/'/>
-->
<qemu:arg value='-machine'/>
<qemu:arg value='memory-backend=pc.ram'/>
<qemu:arg value='-object'/>
<qemu:arg value='memory-backend-file,id=pc.ram,size=16G,mem-path=/mnt/hugepages,share=off,discard-data=on'/>
<!-- <qemu:arg value='memory-backend-ram,id=pc.ram,size=16777216K'/> -->
<!--
<qemu:arg value='-usb'/>
<qemu:arg value='-device'/>
<qemu:arg value='usb-host,hostbus=1,hostaddr=2'/>
-->
</qemu:commandline>
</domain>
Sharing directories with virtual machines and libvirt
Linux to Linux
Ripped from http://rabexc.org/posts/p9-setup-in-libvirt
Let's say you want to make the directory /opt/test on your desktop machine visible to a virtual machine you are running with libvirt.
All you have to do is:
virsh edit myvmname, edit the XML of the VM to have something like:
<domains ...>
...
<devices ...>
<filesystem type='mount' accessmode='passthrough'>
<source dir='/opt/test'/>
<target dir='testlabel'/>
</filesystem>
</devices>
</domains>
where /opt/test is the path you want to share with the VM, and testlabel is just a mnemonic of your choice.
Make sure to set accessmode to something reasonable for your use case. According to the libvirt documentation, you can use:
- mapped To have files created and accessed as the user running kvm/qemu. Uses extended attributes to store the original user credentials.
- passthrough To have files created and accessed as the user within kvm/qemu.
- none Like passthrough, except failures in privileged operations are ignored.
More details are provided in the next section. For now, just ensure that the new <filesystem> blobs are under <domains> and <devices>, order does not matter. Make also sure to save and exit.
Now start your virtual machine, with virsh start myvmname, and get a console.
Append a few lines to /etc/modules, to make sure the right modules are loaded:
$ sudo -s
# cat >>/etc/modules <<EOF
loop
virtio
9p
9pnet
9pnet_virtio
EOF
As a root user, load those modules:
# service kmod start
Now you should be ready to mount the file system:
# mount testlabel /opt/test -t 9p -o trans=virtio
et voila! If you cd /opt/test you should be able to see the files in your host physical machine.
if you want the file system to be automatically mounted at boot time, you can add something like:
testlabel /opt/test 9p trans=virtio 0 0
to your /etc/fstab file.
Issues
If you get access denied to your files in /opt/test or can't write in the directory, the problem is generally related to the accessmode you picked, and the user your VM is running as.
Don't forget that at the end of the day a Virtual Machine is just another process on your host operating system. This process is running with the privileges of a particular user, and only able to change and touch the files that the specific user is given access to.
If you run ps aux |grep kvm or ps aux |grep qemu on your host system, you will most likely see that a system VM is running as user libvirt-qemu on Debian, while it is running as yourself if it is a session VM. If you are confused about system or session VMs, you should read this article.
This means that kvm/qemu will be able to read or write files or directories either as you, or as the libvirt-qemu user. Make sure that file privileges and directories are set accordingly.
To change the uid under which system VMs are run, you need to:
edit /etc/libvirt/qemu.conf
modify the parameters user and group to have the desired value.
restart libvirt daemons, with service restart libvirt-bin and service restart libvirt-guests.
it may also be necessary to restart any VM that is still running, to pick up the new user and group.
Alternatively, you may want to change accessmode to mapped or none.
additional resources
- https://www.linux-kvm.org/page/9p_virtio
- https://unix.stackexchange.com/questions/86071/use-virt-manager-to-share-files-between-linux-host-and-windows-guest