References ========== - http://ark.intel.com/products/52231/Intel-Core-i7-2620M-Processor-4M-Cache-up-to-3_40-GHz - IntelĀ® Virtualization Technology for Directed I/O (VT-d) - YES - http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM - https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/Virtualization/chap-Virtualization-PCI_passthrough.html PCI passthrough of a sound card with KVM/QEMU ============================================= Check/enable Intel IOMMU on host -------------------------------- Check if VT-d (Intel IOMMU) is enabled: $ dmesg -H -T | grep -i iommu If it's not present, enable it by adding `intel_iommu=on` to /etc/grub2.cfg, reboot, and run `dmesg` again: $ dmesg -H -T | grep -i iommu [Sat Mar 22 00:41:30 2014] Command line: BOOT_IMAGE=/vmlinuz-3.13.4-200.fc20.x86_64 root=/dev/mapper/fedora_dhcp193--46-root ro rd.lvm.lv=fedora_dhcp193-46/swap rd.md=0 rd.dm=0 rd.lvm.lv=fedora_dhcp193-46/root rd.luks=0 vconsole.keymap=us rhgb quiet LANG=en_US.UTF-8 intel_iommu=on [Sat Mar 22 00:41:30 2014] Kernel command line: BOOT_IMAGE=/vmlinuz-3.13.4-200.fc20.x86_64 root=/dev/mapper/fedora_dhcp193--46-root ro rd.lvm.lv=fedora_dhcp193-46/swap rd.md=0 rd.dm=0 rd.lvm.lv=fedora_dhcp193-46/root rd.luks=0 vconsole.keymap=us rhgb quiet LANG=en_US.UTF-8 intel_iommu=on [Sat Mar 22 00:41:30 2014] Intel-IOMMU: enabled [Sat Mar 22 00:41:30 2014] dmar: IOMMU 0: reg_base_addr fed90000 ver 1:0 cap c0000020e60262 ecap f0101a [Sat Mar 22 00:41:30 2014] dmar: IOMMU 1: reg_base_addr fed91000 ver 1:0 cap c9008020660262 ecap f0105a [Sat Mar 22 00:41:30 2014] IOAPIC id 2 under DRHD base 0xfed91000 IOMMU 1 [Sat Mar 22 00:41:30 2014] IOMMU 0 0xfed90000: using Queued invalidation [Sat Mar 22 00:41:30 2014] IOMMU 1 0xfed91000: using Queued invalidation [Sat Mar 22 00:41:30 2014] IOMMU: Setting RMRR: [Sat Mar 22 00:41:30 2014] IOMMU: Setting identity map for device 0000:00:02.0 [0xdb800000 - 0xdf9fffff] [Sat Mar 22 00:41:30 2014] IOMMU: Setting identity map for device 0000:00:1d.0 [0xdacd5000 - 0xdacebfff] [Sat Mar 22 00:41:30 2014] IOMMU: Setting identity map for device 0000:00:1a.0 [0xdacd5000 - 0xdacebfff] [Sat Mar 22 00:41:30 2014] IOMMU: Prepare 0-16MiB unity mapping for LPC [Sat Mar 22 00:41:30 2014] IOMMU: Setting identity map for device 0000:00:1f.0 [0x0 - 0xffffff] Add the Audio PCI device via `virsh` ------------------------------------ Identify the sound card on the host: $ lspci | grep -i audio 00:1b.0 Audio device: Intel Corporation 6 Series/C200 Series Chipset Family High Definition Audio Controller (rev 04) Enumerate the PCI vendor and device code for the above Audio device: $ lspci -n | grep 00:1b.0 00:1b.0 0403: 8086:1c20 (rev 04) Identify the string the PCI node device: $ virsh nodedev-list --tree | grep -i 1b +- pci_0000_00_1b_0 Dump the XML representation of the PCI node device: $ virsh nodedev-dumpxml pci_0000_00_1b_0 pci_0000_00_1b_0 /sys/devices/pci0000:00/0000:00:1b.0 computer snd_hda_intel 0 0 27 0 6 Series/C200 Series Chipset Family High Definition Audio Controller Intel Corporation
Detach the above PCI node device, so it can be safely used by guests via passthrough: $ virsh nodedev-detach pci_0000_00_1b_0 Device pci_0000_00_1b_0 detached Convert slot and function values to hexadecimal values (from decimal) to get the PCI bus addresses. Append "0x" to the beginning of the output to tell the computer that the value is a hexadecimal number. From the above XML representation, the bus, slot and function values are: bus=0, slot=27, function=0 $ printf %x 0 0 $ $ printf %x 27 1b $ printf %x 0 0 The values to use in the guest XML configuration: bus='0x00' slot='0x1b' function='0x00' Edit the guest XML, and add a attribute to attach the Audio card to the guest: $ virsh edit f20vm [. . .] Add the below XML xnippet and save the configuration:
Once saved, dump the XML representation to ensure it reflects the new reality (i.e. the slot (0x1b) of the sound card should be visible): $ virsh dumpxml ostack-controller | grep 1b -B2 -A3
Ensure the device is under the PCI stub (since we already detached the device from the host): $ readlink /sys/bus/pci/devices/0000\:00\:1b.0/driver ../../../bus/pci/drivers/pci-stub Detach the device: $ virsh nodedev-detach pci_0000_00_1b_0 Device pci_0000_00_1b_0 detached Ensure VFIO is being used: $ lsmod | grep -i vfio vfio_iommu_type1 17636 0 vfio 20160 1 vfio_iommu_type1 Temporarily, set SELinux to permissive: $ setenforce 0 $ virsh start foo Inside the guest, run `lspci` again and grep for the Audio card: $ lspci | grep -i Audio 00:05.0 Audio device: Intel Corporation 6 Series/C200 Series Chipset Family High Definition Audio Controller (rev 04) To reattach device back to the host ----------------------------------- Shutdown the guest: $ virsh shutdown foo Re-attach the device node again: $ virsh nodedev-reattach pci_0000_00_1b_0 Device pci_0000_00_1b_0 re-attached NOTES ----- Thanks to Alex Williamson. - The PCI slot inside the guest won't be at the same address as the host unless you configure it to be. - Sanity test: For audio where you can't physically hear the output, pull up something like pandora and watch interrupts in the host to see if the device is continuing to generate interrupts $ watch -d grep vfio /proc/interrupts