Page MenuHomeFreeBSD

bhyve: add virtio-input emulation
ClosedPublic

Authored by c.koehne_beckhoff.com on Apr 28 2021, 9:25 AM.

Details

Summary

Description:

Adds a new virtio-input device to send keyboard and mouse input events to a guest.

How to test:

Add a virtio-input device to your bhyve config:

-s <slot>,virtio-input,/dev/input/eventX

Known Limitations:

  • Only works with Windows
  • Cannot gain exklusive access to the input device (solved by D30542)

    Occurs when using legacy drivers for FreeBSD. Your guest and your FreeBSD host process the input events of your device. When moving the mouse, the mouse pointer of the VM and of FreeBSD will move.
  • CAPSICUM support untested
  • No support for snapshots

Diff Detail

Repository
rG FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

Have you tested this code with CAPSICUM enabled?

I think that sc->vsc_fd operations should be limited using caph_rights_limit in pci_vtinput_init().

See for an example: https://cgit.freebsd.org/src/tree/usr.sbin/bhyve/pci_virtio_rnd.c#n163

Sadly, I don't know how to implement CAPSICUM support or how to test CAPSICUM. For that reason, I left out support for CAPSICUM.

The capsicum support should look something like this:

diff --git a/usr.sbin/bhyve/pci_virtio_input.c b/usr.sbin/bhyve/pci_virtio_input.c
index a7a0366428f..80aff822972 100644
--- a/usr.sbin/bhyve/pci_virtio_input.c
+++ b/usr.sbin/bhyve/pci_virtio_input.c
@@ -35,6 +35,10 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#ifndef WITHOUT_CAPSICUM
+#include <sys/capsicum.h>
+#include <capsicum_helpers.h>
+#endif
 #include <sys/ioctl.h>
 #include <sys/linker_set.h>
 #include <sys/uio.h>
@@ -629,6 +633,9 @@ static int
 pci_vtinput_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
 {
        struct pci_vtinput_softc *sc;
+#ifndef WITHOUT_CAPSICUM
+       cap_rights_t rights;
+#endif
 
        /*
         * Keep it here.
@@ -712,6 +719,12 @@ pci_vtinput_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
                goto failed;
        }
 
+#ifndef WITHOUT_CAPSICUM
+       cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ, CAP_WRITE);
+       if (caph_rights_limit(sc->vsc_fd, &rights) == -1)
+               errx(EX_OSERR, "Unable to apply rights for sandbox");
+#endif
+
        /* link virtio to softc */
        vi_softc_linkup(
            &sc->vsc_vs, &vtinput_vi_consts, sc, pi, sc->vsc_queues);

But I only tested that the code builds.

Only works with Windows

Hmm, why? What happens with a Linux guest?

Cannot gain exklusive access to the input device

You are doing EVIOCGRAB, so it would be exclusive against other evdev clients.
But yes, that currently won't exclude keyboards from the vt console, or mouses from various legacy interfaces (that moused uses, etc.).
Shouldn't be an issue if you do have a GUI running, but of course not every VM host is a desktop.
Pinging @wulf — would be nice to make evdev_grab_client tell the driver to pause vt kbd events etc.
(or to make vt/syscons an evdev client already and rip out the old kbd system that requires a lot of weird code to be copy-pasted into every keyboard driver :D)

Cannot gain exklusive access to the input device

You are doing EVIOCGRAB, so it would be exclusive against other evdev clients.
But yes, that currently won't exclude keyboards from the vt console, or mouses from various legacy interfaces (that moused uses, etc.).
Shouldn't be an issue if you do have a GUI running, but of course not every VM host is a desktop.
Pinging @wulf — would be nice to make evdev_grab_client tell the driver to pause vt kbd events etc.

It is trivially can be done for mices but not that easy for keyboards.
There are some special cases like KDB, shutdown thread and terminal control commands in K_CODE and K_XLATE modes, when we may want to pass events unconditionally.

(or to make vt/syscons an evdev client already and rip out the old kbd system that requires a lot of weird code to be copy-pasted into every keyboard driver :D)

kbd system is a classic of legacy code. You see a lot of places which must be refactored, but you fear even touch that can of worms as it gives you no benefit and a lot of headache.

usr.sbin/bhyve/pci_virtio_input.c
343

That is not bug but incorrect.
Evdev bitmaps are arrays of longs rather then chars.
Required number of longs can be calculated as:

count = ((count + (sizeof(long) * 8) - 1) / (sizeof(long) * 8))

But current code will work too as all *_CNT constants are properly aligned.

663

Moving O_NONBLOCK to open() flags will save you dozen lines of code.

c.koehne_beckhoff.com edited the summary of this revision. (Show Details)
  • add CAPSICUM support (note: untested yet)
  • fix calculation of evdev bitmap count
  • open /dev/input/eventX device with O_NONBLOCK flag

Hmm, why? What happens with a Linux guest?

Linux identifies the device as virtio-input device. However, I'm not able to move the mouse or use the keyboard in Linux. I did no further investigations why Linux fails to use the virtio-input device yet.

jhb added inline comments.
usr.sbin/bhyve/pci_virtio_input.c
632

I tried to allow for arbitrary new words in the future in most of the other models. An example of this style (with a mandated initial parameter) is in block_if.c:blockif_legacy_config() which sets 'path' to the first argument.

657

Please document any new config vars used in bhyve_config.5.

  • fix coding style of pci_vtinput_legacy_config
  • add manpage entry for VirtIO Input

Hmm, why? What happens with a Linux guest?

Linux identifies the device as virtio-input device. However, I'm not able to move the mouse or use the keyboard in Linux. I did no further investigations why Linux fails to use the virtio-input device yet.

Seems like VirtIO version needs to be 1.0 for Linux:
https://github.com/torvalds/linux/blob/master/drivers/virtio/virtio_input.c#L218-L226

Could you test https://reviews.freebsd.org/D30542 ?
It should fix

Cannot gain exklusive access to the input device
Occurs when using legacy drivers for FreeBSD

In D30020#685930, @wulf wrote:

Could you test https://reviews.freebsd.org/D30542 ?
It should fix

Cannot gain exklusive access to the input device
Occurs when using legacy drivers for FreeBSD

Works fine. Thank you very much!

jhb added a subscriber: grehan.

I haven't reviewed the spec and how the model implements it, but the config stuff all seems fine. I'll give @grehan a chance to chime in on the other bits if he wants to.

usr.sbin/bhyve/pci_virtio_input.c
640

This will support arbitrary config settings in the future.

This revision is now accepted and ready to land.Jun 1 2021, 6:37 PM
This revision now requires review to proceed.Jun 2 2021, 5:28 AM

Verified this works with a mouse on Win10.

The upcoming virtio 1.1 patch from khng (D29708) will allow Linux operation.

This revision is now accepted and ready to land.Jun 4 2021, 7:21 AM
This revision was automatically updated to reflect the committed changes.