[PATCH 0/2] Add support for hotplugging evdev input devices

This patch series extends the current evdev device implementation to allow hotplugging, including live attachment and detachment. Resolves: https://gitlab.com/libvirt/libvirt/-/issues/529 Rayhan Faizel (2): qemu: Implement support for hotplugging evdev input devices qemuhotplugtest: Add testcases for hotplugging evdev input devices src/qemu/qemu_command.c | 2 +- src/qemu/qemu_command.h | 3 + src/qemu/qemu_hotplug.c | 95 +++++++++++++------ tests/qemuhotplugtest.c | 5 + .../qemuhotplug-input-evdev.xml | 3 + .../qemuhotplug-base-live+input-evdev.xml | 58 +++++++++++ 6 files changed, 137 insertions(+), 29 deletions(-) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-input-evdev.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+input-evdev.xml -- 2.34.1

Unlike other input types, evdev is not a true device since it's backed by '-object'. We must use object-add/object-del monitor commands instead of device-add/device-del in this particular case. This patch adds support for handling live attachment and detachment of evdev type devices. Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com> --- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_command.h | 3 ++ src/qemu/qemu_hotplug.c | 95 +++++++++++++++++++++++++++++------------ 3 files changed, 71 insertions(+), 29 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9859ea67a4..63bfeb790e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4367,7 +4367,7 @@ qemuBuildInputUSBDevProps(const virDomainDef *def, } -static virJSONValue * +virJSONValue * qemuBuildInputEvdevProps(virDomainInputDef *dev) { g_autoptr(virJSONValue) props = NULL; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 341ec43f9a..dca8877703 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -233,6 +233,9 @@ virJSONValue * qemuBuildInputUSBDevProps(const virDomainDef *def, virDomainInputDef *dev); +virJSONValue * +qemuBuildInputEvdevProps(virDomainInputDef *dev); + virJSONValue * qemuBuildVsockDevProps(virDomainDef *def, virDomainVsockDef *vsock, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 3b39941780..4739beead8 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3016,36 +3016,40 @@ qemuDomainAttachInputDevice(virDomainObj *vm, bool teardowncgroup = false; qemuAssignDeviceInputAlias(vm->def, input, -1); + if (input->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) { + if (!(devprops = qemuBuildInputEvdevProps(input))) + goto cleanup; + } else { + switch ((virDomainInputBus) input->bus) { + case VIR_DOMAIN_INPUT_BUS_USB: + if (virDomainUSBAddressEnsure(priv->usbaddrs, &input->info) < 0) + return -1; - switch ((virDomainInputBus) input->bus) { - case VIR_DOMAIN_INPUT_BUS_USB: - if (virDomainUSBAddressEnsure(priv->usbaddrs, &input->info) < 0) - return -1; - - releaseaddr = true; + releaseaddr = true; - if (!(devprops = qemuBuildInputUSBDevProps(vm->def, input))) - goto cleanup; - break; + if (!(devprops = qemuBuildInputUSBDevProps(vm->def, input))) + goto cleanup; + break; - case VIR_DOMAIN_INPUT_BUS_VIRTIO: - if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0) - goto cleanup; + case VIR_DOMAIN_INPUT_BUS_VIRTIO: + if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev) < 0) + goto cleanup; - if (!(devprops = qemuBuildInputVirtioDevProps(vm->def, input, priv->qemuCaps))) - goto cleanup; - break; + if (!(devprops = qemuBuildInputVirtioDevProps(vm->def, input, priv->qemuCaps))) + goto cleanup; + break; - case VIR_DOMAIN_INPUT_BUS_DEFAULT: - case VIR_DOMAIN_INPUT_BUS_PS2: - case VIR_DOMAIN_INPUT_BUS_XEN: - case VIR_DOMAIN_INPUT_BUS_PARALLELS: - case VIR_DOMAIN_INPUT_BUS_NONE: - case VIR_DOMAIN_INPUT_BUS_LAST: - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, - _("input device on bus '%1$s' cannot be hot plugged."), - virDomainInputBusTypeToString(input->bus)); - return -1; + case VIR_DOMAIN_INPUT_BUS_DEFAULT: + case VIR_DOMAIN_INPUT_BUS_PS2: + case VIR_DOMAIN_INPUT_BUS_XEN: + case VIR_DOMAIN_INPUT_BUS_PARALLELS: + case VIR_DOMAIN_INPUT_BUS_NONE: + case VIR_DOMAIN_INPUT_BUS_LAST: + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("input device on bus '%1$s' cannot be hot plugged."), + virDomainInputBusTypeToString(input->bus)); + return -1; + } } if (qemuDomainNamespaceSetupInput(vm, input, &teardowndevice) < 0) @@ -3066,9 +3070,14 @@ qemuDomainAttachInputDevice(virDomainObj *vm, if (qemuDomainAttachExtensionDevice(priv->mon, &input->info) < 0) goto exit_monitor; - if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0) { - ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info)); - goto exit_monitor; + if (input->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) { + if (qemuMonitorAddObject(priv->mon, &devprops, NULL) < 0) + goto exit_monitor; + } else { + if (qemuMonitorAddDeviceProps(priv->mon, &devprops) < 0) { + ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info)); + goto exit_monitor; + } } qemuDomainObjExitMonitor(vm); @@ -6093,6 +6102,29 @@ qemuDomainDetachDeviceLease(virQEMUDriver *driver, } +static int +qemuDomainDetachDeviceInputEvdev(virQEMUDriver *driver, + virDomainObj *vm, + virDomainDeviceDef *detach) +{ + int rc; + virDomainInputDef *input = detach->data.input; + qemuDomainObjPrivate *priv = vm->privateData; + + qemuDomainObjEnterMonitor(vm); + rc = qemuMonitorDelObject(priv->mon, input->info.alias, true); + qemuDomainObjExitMonitor(vm); + + if (rc < 0) + return -1; + + if (qemuDomainRemoveDevice(driver, vm, detach) < 0) + return -1; + + return 0; +} + + int qemuDomainDetachDeviceLive(virDomainObj *vm, virDomainDeviceDef *match, @@ -6176,6 +6208,13 @@ qemuDomainDetachDeviceLive(virDomainObj *vm, &detach.data.input) < 0) { return -1; } + + /* + * Input devices of type 'evdev' are regular QOM objects + * (-object instead of -device), so it must be handled differently. + */ + if (detach.data.input->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) + return qemuDomainDetachDeviceInputEvdev(driver, vm, &detach); break; case VIR_DOMAIN_DEVICE_REDIRDEV: if (qemuDomainDetachPrepRedirdev(vm, match->data.redirdev, -- 2.34.1

This patch adds testcases to exercise hotplugging/hotunplugging evdev input devices. Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com> --- tests/qemuhotplugtest.c | 5 ++ .../qemuhotplug-input-evdev.xml | 3 + .../qemuhotplug-base-live+input-evdev.xml | 58 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-input-evdev.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+input-evdev.xml diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 961a7a3c64..d935ad58ed 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -774,6 +774,11 @@ mymain(void) "device_del", QMP_DEVICE_DELETED("scsi0-0-0-4") QMP_OK, "blockdev-del", QMP_OK); + DO_TEST_ATTACH("x86_64", "base-live", "input-evdev", false, true, + "object-add", QMP_OK); + DO_TEST_DETACH("x86_64", "base-live", "input-evdev", false, false, + "object-del", QMP_OK); + #define DO_TEST_CPU_GROUP(archname, prefix, vcpus, expectfail) \ do { \ cpudata.test = prefix; \ diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-input-evdev.xml b/tests/qemuhotplugtestdevices/qemuhotplug-input-evdev.xml new file mode 100644 index 0000000000..7f3d9cfd72 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-input-evdev.xml @@ -0,0 +1,3 @@ +<input type='evdev'> + <source dev='/dev/input/event1234' grab='all' repeat='on' grabToggle='ctrl-ctrl'/> +</input> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+input-evdev.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+input-evdev.xml new file mode 100644 index 0000000000..50d8815a5c --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+input-evdev.xml @@ -0,0 +1,58 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <input type='evdev'> + <source dev='/dev/input/event1234' grab='all' grabToggle='ctrl-ctrl' repeat='on'/> + <alias name='input2'/> + </input> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> + <seclabel type='none' model='none'/> +</domain> -- 2.34.1

On 5/15/24 12:27, Rayhan Faizel wrote:
This patch series extends the current evdev device implementation to allow hotplugging, including live attachment and detachment.
I've put this into the commit message of the first patch as it's where it belongs.
Rayhan Faizel (2): qemu: Implement support for hotplugging evdev input devices qemuhotplugtest: Add testcases for hotplugging evdev input devices
src/qemu/qemu_command.c | 2 +- src/qemu/qemu_command.h | 3 + src/qemu/qemu_hotplug.c | 95 +++++++++++++------ tests/qemuhotplugtest.c | 5 + .../qemuhotplug-input-evdev.xml | 3 + .../qemuhotplug-base-live+input-evdev.xml | 58 +++++++++++ 6 files changed, 137 insertions(+), 29 deletions(-) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-input-evdev.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+input-evdev.xml
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> and merged. Michal
participants (2)
-
Michal Prívozník
-
Rayhan Faizel