Alternative KVM HAOS USB zigbee adapter config

Hello from a new user,

In most guides I run across the common way to connect the HAOS KVM guest with a USB zigbee adapter is with USB passthrough, but unfortunately USB passthrough protocol might use more CPU in the host than the HAOS guest itself.

It’s perhaps simpler to configure ZHA with the guest using USB passthrough first because the UI seem to like to see the USB device, but once you successfully configured ZHA, and you notice the increased CPU load in the host, you may want to switch the config to use pci-serial.

In qemu command line terms it means to replace:

-device usb-host,vendorid=0x0000,productid=0x0000

with:

-chardev serial,path=/dev/ttyUSB0,id=serial-usb0 -device pci-serial,chardev=serial-usb0

You also need the cp210x kernel module in loaded in the host (east to check with lsmod). At last you need to be in the dialout group (as in /etc/group) or otherwise to have enough permission to open /dev/ttyUSB0.

After the KVM config change, you can boot again and then ssh into HAOS (inside the ssh container, host root not required) and edit ~/config/.storage/core.config_entries, search 115200 and change the line above that starts with “/dev/serial…” to point to “/dev/ttyS1” or maybe S0 if you had no other serial line. The actual number depends on your machine type topology. Then reboot (the guest).

At the next boot, assuming you picked the right guest serial line number, ZHA should be working again, no need to touch the ZHA configuration UI.

If pci-serial doesn’t work for whatever reason, it should be possible to reboot the guest back into USB passthrough mode. Once back in USB passthrough mode, the HAOS UI should be able to fixup ZHA with a few clicks. I successfully switched back and forth from USB passthrough and pci-serial with the above procedure no apparent regression.

Hope this helps save some CPU power. It should be applicable to all KVM based solutions using the qcow2 image, enjoy.

Thanks for this.
I’m making a few notes along the way and was wondering if you could also dump the portion of the xml file that pertains to this as I’ve seen other HA Forum users use <serial type="dev"> in their xml which I suspect results in the same qemu paramter settings as you mentioned, but just want to see the xml for comparison.

Also, can you comment on roughly how much CPU power was saved?

Thanks :slight_smile:

I’m invoking qemu directly without xml, the only tricky part of doing that is the clean shutdown that requires sending the system_powerdown command to the monitor and to wait 20sec.

So I haven’t tested with the xml, so I’m just guessing here that it may be something along these lines:

<devices>
 <serial type='serial'>
   <source path='/dev/ttyUSB0/>
   <target port='1'/>
 </serial>
</devices>

You may want to try to use virsh domxml-to-native to convert from xml to the qemu command line, then make the edits to the command line, and then re-import with virsh domxml-from-native. Then you may also want to double check with “pgrep -al qemu” that you got the right command line executed with chardev serial, pci-serial and no usbdevice.

Also I forgot to mention the qemu backend serial driver implementation probably only works for serial devices supporting baud rate 115200. The adapter I use was configured at 115200 by default by ZHA incidentally.

In the worst case the xml has an option to go manual and append a string to the qemu command line, but it shouldn’t be necessary. So the last resort if the conversion to xml fails could be:

<qemu:commandline>
          <qemu:arg value='......'/>
</qemu:commandline>

The CPU utilization in my case (on a fairly old i7 x86-64) was about 9% of one core, let’s say it was a bit too far from idle to do nothing about it. strace -p $(pgrep qemu) would show a ppoll flood caused by the ppoll timeout set around 1msec, so I’d run thousand of ppoll syscall per second and ppoll isn’t exactly fast either, unlike epoll. After removing USB passthrough the ppoll timeout of the main loop is up to 0.5sec and the CPU utilization is 0.7% according to top.

If your qemu process uses ~0.x% of CPU in top with USB passthrough already, I’d be interested to know just in case some other sw version fares better. I almost never used USB passthrough before with KVM, so I’m not exactly sure what kind of overhead is to be expected when emulating the USB protocol in the guest… Thanks!