4

I have a Windows 10 Pro virtual machine using KVM. It is set up through virt-manager using the latest version of libvirt and QEMU. All of this is running on Manjaro Linux 20. Manjaro defaults to using PulseAudio for its audio output (at least for Manjaro 20). I was wondering if there is a way to use PulseAudio with libvirt/QEMU/KVM to have an audio pass-through from the guest OS to the host. Meaning that anything that is playing in the Guest OS will need to be heard through the default output device in Manjaro Linux. First, I tried setting environment variables to set it up, but that didn't work, and it also is deprecated past QEMU 4.1 (I am using 5.1.) Then, I tried using this tutorial, which ended up somehow bricking Manjaro, and I had to reinstall. I am currently using the default Spice server through virt-manager. I have heard that the Spice server introduces lots of overhead, and I can't afford that. I need every CPU cycle, and if PulseAudio is already running, I may as well use it. My libvirt XML config WITHOUT the Spice server is as follows:

<domain type="kvm">
  <name>windows10pro</name>
  <uuid>1916e748-a979-40b7-b9d3-ff1b9a16155e</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">4</vcpu>
  <os>
    <type arch="x86_64" machine="pc-q35-5.1">hvm</type>
    <loader readonly="yes" type="pflash">/usr/share/edk2-ovmf/x64/OVMF_CODE.fd</loader>
    <nvram>/var/lib/libvirt/qemu/nvram/windows10pro_VARS.fd</nvram>
    <boot dev="hd"/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <hyperv>
      <relaxed state="on"/>
      <vapic state="on"/>
      <spinlocks state="on" retries="8191"/>
      <vendor_id state="on" value="none"/>
    </hyperv>
    <kvm>
      <hidden state="on"/>
    </kvm>
    <vmport state="off"/>
  </features>
  <cpu mode="host-passthrough" check="partial" migratable="on">
    <topology sockets="1" dies="1" cores="4" threads="1"/>
    <feature policy="disable" name="hypervisor"/>
  </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="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/var/lib/libvirt/images/windows10pro.qcow2"/>
      <target dev="vda" bus="virtio"/>
      <address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/>
    </disk>
    <controller type="usb" index="0" model="qemu-xhci" ports="15">
      <address type="pci" domain="0x0000" bus="0x02" 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="0x10"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
    </controller>
    <controller type="pci" index="2" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="2" port="0x11"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
    </controller>
    <controller type="pci" index="3" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="3" port="0x12"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
    </controller>
    <controller type="pci" index="4" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="4" port="0x13"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
    </controller>
    <controller type="pci" index="5" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="5" port="0x14"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
    </controller>
    <controller type="pci" index="6" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="6" port="0x15"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
    </controller>
    <controller type="pci" index="7" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="7" port="0x8"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0" multifunction="on"/>
    </controller>
    <controller type="pci" index="8" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="8" port="0x9"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x1"/>
    </controller>
    <controller type="pci" index="9" model="pcie-to-pci-bridge">
      <model name="pcie-pci-bridge"/>
      <address type="pci" domain="0x0000" bus="0x08" slot="0x00" function="0x0"/>
    </controller>
    <controller type="virtio-serial" index="0">
      <address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
    </controller>
    <interface type="network">
      <mac address="52:54:00:fe:e2:a2"/>
      <source network="default"/>
      <model type="e1000e"/>
      <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
    </interface>
    <input type="tablet" bus="usb">
      <address type="usb" bus="0" port="1"/>
    </input>
    <input type="mouse" bus="ps2"/>
    <input type="keyboard" bus="ps2"/>
    <hostdev mode="subsystem" type="pci" managed="yes">
      <source>
        <address domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
      </source>
      <address type="pci" domain="0x0000" bus="0x06" slot="0x00" function="0x0"/>
    </hostdev>
    <hostdev mode="subsystem" type="pci" managed="yes">
      <source>
        <address domain="0x0000" bus="0x01" slot="0x00" function="0x1"/>
      </source>
      <address type="pci" domain="0x0000" bus="0x07" slot="0x00" function="0x0"/>
    </hostdev>
    <hostdev mode="subsystem" type="usb" managed="yes">
      <source>
        <vendor id="0x1b1c"/>
        <product id="0x1b49"/>
      </source>
      <address type="usb" bus="0" port="4"/>
    </hostdev>
    <hostdev mode="subsystem" type="usb" managed="yes">
      <source>
        <vendor id="0x264a"/>
        <product id="0x1011"/>
      </source>
      <address type="usb" bus="0" port="5"/>
    </hostdev>
    <redirdev bus="usb" type="spicevmc">
      <address type="usb" bus="0" port="2"/>
    </redirdev>
    <redirdev bus="usb" type="spicevmc">
      <address type="usb" bus="0" port="3"/>
    </redirdev>
    <memballoon model="virtio">
      <address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
    </memballoon>
  </devices>
</domain>

Revvz
  • 455
  • 1
  • 6
  • 14

3 Answers3

4

This is more of a comment, really...

I don't use libvirt myself, but as far as I can tell there aren't any audio devices in your config.

Here are the qemu command line options I use for guest (Win10 and others) audio output to PulseAudio output on -machine q35 :

 -device ich9-intel-hda,addr=1f.1
 -audiodev pa,id=snd0
 -device hda-output,audiodev=snd0

Basically, audiodev pa is the host's PulseAudio, and device hda-output is a line-out device on the guest (which is routed through audiodev=snd0). ...And hda-output requires an ich9-intel-hda bus to connect to.

...I'd expect virt-manager to allow this type of setup.

rfmodulator
  • 3,638
  • 3
  • 18
  • 22
  • Thanks for this. I'll see if I can work something out. I mentioned in my question that I use a Spice server, and I put the config without that and audio. Just thought I'd let you know. It looks like ```hda``` refers to Intel's HD Audio, right? I have a Realtek motherboard built-in sound chip and haven't found any documentation on it – Revvz Oct 28 '20 at 20:13
  • 1
    Also, how do you check which audiodevs are active? – Revvz Oct 28 '20 at 20:19
  • 1
    These are virtual devices that emulate Intel's HDA in the VM... your physical motherboard doesn't matter. (Side note: the virtual `AC97` device is *supposed* to work with the Realtek driver, but I didn't have much luck with it.) – rfmodulator Oct 28 '20 at 20:21
  • You mean like `qemu --help | grep audiodev`? Mine shows `none`, `pa`, `spice` and `wav`, for instance. Again, this is the host's **output** side. – rfmodulator Oct 28 '20 at 20:23
  • 1
    I am referring to the ```audiodev=snd0``` part. What is that used for? Is it a physical connection? – Revvz Oct 28 '20 at 23:20
  • 1
    That refers to the `id` of the `audiodev` that was created on the previous line. It means that the guest's `hda-output` device *output* is going to ***be sent*** to the host's `audiodev` with `id=snd0`, in this case PulseAudio (`pa`). ...Maybe that's confusing? ...I'm not sure how else to say it. – rfmodulator Oct 28 '20 at 23:26
  • Ok. I think I understand it. the audiodev created on the previous line as you mentioned is being set to the id of ```snd0```, which is really the PulseAudio. Correct? – Revvz Oct 29 '20 at 00:46
  • `snd0` is just the `id` I assigned to *that* `audiodev`, it could have been anything. The `pa` on the previous line is what tells `qemu` to use PulseAudio. – rfmodulator Oct 29 '20 at 00:49
  • right. That's what I meant. Thanks for the explanation. I'll try it out and see what happens. – Revvz Oct 29 '20 at 01:02
  • 1
    for the ```ich9-intel-hda``` address (```addr=```): is it always ```1f.1```? I have the following XML for the ICH9 audio device: ```
    ```
    – Revvz Oct 29 '20 at 01:09
  • The `addr` isn't important, that's just where I put it (it makes for a nice `lspci` output when everything is organized). – rfmodulator Oct 29 '20 at 01:13
  • 1
    It doesn't output any sound to the host for some reason. The ```ICH9```audio device is detected in Windows 10. Here are the [qemu XML args](https://pastebin.com/D65gdy7U) and here is the [full config](https://pastebin.com/wHPX0nCX). At least it didn't corrupt the host :) – Revvz Oct 29 '20 at 01:27
  • There are multiple possible reasons why. – rfmodulator Oct 29 '20 at 01:45
0

VM Sound Setup on Debian 11 KVM

I am running Debian 11 a Dell r620 with a 25w HDMI NVIDIA card using an HDMI audio extractor. Pulseaudio runs at boot from a pulseaudio.service file so if you're running as a user the server path and files will differ so modify accordingly. The mathiashueber link below is a fantastic source but I could not get his xml configuration to work. The working xml section is from the second source.

Sources

  1. https://mathiashueber.com/virtual-machine-audio-setup-get-pulse-audio-working/
  2. https://www.reddit.com/r/VFIO/comments/4kuvxs/setting_up_a_kvmqemu_vga_passthrough_gaming_vm/

Uncomment, Edit, or Add

nano /etc/libvirt/qemu.conf
user = "root"
group = "root"
nographics_allow_host_audio = 1

nano /etc/pulse/daemon.conf
default-sample-rate = 44100
alternate-sample-rate = 48000

Set the frequency of your Windows VM Sound to 44100 Hz

Note I did not change sample rate in Windows VM yet and it still works well enough.

Save your VM xml configuration

virsh dumpxml vmname >> vmbackup.xml

Locate the pulse/native file on your system

> ls /var/run/pulse/native 
/var/run/pulse/native
>
> ls /run/user/1000/pulse/native
-bash: /run/user/1000/pulse/native: No such file or directory

Edit your VM xml file

virsh edit vmname
- change first line as follows -
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

  - at bottom of xml add or change after </devices> retain indentation!

  </devices>
  <qemu:commandline>
    <qemu:env name='QEMU_AUDIO_DRV' value='pa'/>
    <qemu:env name='QEMU_PA_SERVER' value='/var/run/pulse/native'/>
  </qemu:commandline>
</domain>

Edit /etc/apparmor.d/abstractions/libvirt-qemu

nano /etc/apparmor.d/abstractions/libvirt-qemu
  # JDS ADDED
  /etc/pulse/client.conf.d/ r,
  /etc/pulse/client.conf.d/* r,
  /var/run/pulse/native rw,
  /root/.config/pulse/* r,
  /root/.config/pulse/cookie k,

Reboot host and start VM Manager

Edit VM Audio Settings and select HDA (ICH9)

Note in my case I had to set sound service to autostart in Windows 2019 Server

sjohn
  • 1
  • 1
0

Its easier to just buy a usb to audio jack and pass that over to vm you can then go ahead and attach your speakers or headphones to the jack. Better than pulseaudio actual audio.