Up until now, we've assumed that all x86 machines have a PS/2 controller built-in. This assumption was correct until QEMU v4.2 introduced a new x86-based machine type - microvm. Due to this assumption, a pair of unnecessary PS/2 inputs are implicitly added to all microvm domains. This patch fixes that by whitelisting machine types which are known to include the i8042 PS/2 controller. Signed-off-by: Kamil Szczęk <kamil@xxxxxxxxxx> --- src/qemu/qemu_capabilities.c | 20 ++++++++++++++++++++ src/qemu/qemu_capabilities.h | 5 ++++- src/qemu/qemu_domain.c | 28 +++++++++++++++++++++++++--- src/qemu/qemu_domain.h | 1 + src/qemu/qemu_validate.c | 4 ++-- 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2f66a49711..2765fba7c8 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1360,6 +1360,13 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "vhost-user-vga", QEMU_CAPS_DEVICE_VHOST_USER_VGA }, { "ramfb", QEMU_CAPS_DEVICE_RAMFB }, { "max-arm-cpu", QEMU_CAPS_ARM_MAX_CPU }, + /* + * The i8042 controller is a built-in device and is not user-creatable. + * However, since not all machine types include this controller, you should + * avoid checking for this capability directly. + * + * Prefer using virQEMUCapsSupportsI8042() instead. + */ { "i8042", QEMU_CAPS_DEVICE_I8042 }, { "rng-builtin", QEMU_CAPS_OBJECT_RNG_BUILTIN }, { "tpm-spapr", QEMU_CAPS_DEVICE_TPM_SPAPR }, @@ -6008,6 +6015,19 @@ virQEMUCapsSupportsVmport(virQEMUCaps *qemuCaps, STREQ(def->os.machine, "isapc"); } +bool +virQEMUCapsSupportsI8042(virQEMUCaps *qemuCaps, + const virDomainDef *def) +{ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_I8042)) + return false; + + return qemuDomainIsI440FX(def) || + qemuDomainIsQ35(def) || + qemuDomainIsXenFV(def) || + STREQ(def->os.machine, "isapc"); +} + /* * The preferred machine to use if none is listed explicitly diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index edeb870e01..659efd9182 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -535,7 +535,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_SMP_DIES, /* -smp dies= */ /* 350 */ - QEMU_CAPS_DEVICE_I8042, /* PS/2 controller */ + QEMU_CAPS_DEVICE_I8042, /* PS/2 controller, use virQEMUCapsSupportsI8042() to query this capability */ QEMU_CAPS_OBJECT_RNG_BUILTIN, /* -object rng-builtin */ X_QEMU_CAPS_VIRTIO_NET_FAILOVER, /* virtio-net-*.failover */ QEMU_CAPS_DEVICE_TPM_SPAPR, /* -device tpm-spapr */ @@ -718,6 +718,9 @@ void virQEMUCapsInitProcessCapsInterlock(virQEMUCaps *qemuCaps); bool virQEMUCapsSupportsVmport(virQEMUCaps *qemuCaps, const virDomainDef *def); +bool virQEMUCapsSupportsI8042(virQEMUCaps *qemuCaps, + const virDomainDef *def); + const char *virQEMUCapsGetBinary(virQEMUCaps *qemuCaps); virArch virQEMUCapsGetArch(virQEMUCaps *qemuCaps); unsigned int virQEMUCapsGetVersion(virQEMUCaps *qemuCaps); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index f87ba6ba51..2b4bb54efc 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3925,9 +3925,10 @@ virXMLNamespace virQEMUDriverDomainXMLNamespace = { static int -qemuDomainDefAddImplicitInputDevice(virDomainDef *def) +qemuDomainDefAddImplicitInputDevice(virDomainDef *def, + virQEMUCaps *qemuCaps) { - if (ARCH_IS_X86(def->os.arch)) { + if (virQEMUCapsSupportsI8042(qemuCaps, def)) { if (virDomainDefMaybeAddInput(def, VIR_DOMAIN_INPUT_TYPE_MOUSE, VIR_DOMAIN_INPUT_BUS_PS2) < 0) @@ -4166,7 +4167,7 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver, bool addITCOWatchdog = false; /* add implicit input devices */ - if (qemuDomainDefAddImplicitInputDevice(def) < 0) + if (qemuDomainDefAddImplicitInputDevice(def, qemuCaps) < 0) return -1; /* Add implicit PCI root controller if the machine has one */ @@ -9177,6 +9178,21 @@ qemuDomainMachineIsMipsMalta(const char *machine, return false; } +static bool +qemuDomainMachineIsXenFV(const char *machine, + const virArch arch) +{ + if (!ARCH_IS_X86(arch)) + return false; + + if (STREQ(machine, "xenfv") || + STRPREFIX(machine, "xenfv-")) { + return true; + } + + return false; +} + /* You should normally avoid this function and use * qemuDomainHasBuiltinIDE() instead. */ @@ -9263,6 +9279,12 @@ qemuDomainIsLoongArchVirt(const virDomainDef *def) return qemuDomainMachineIsLoongArchVirt(def->os.machine, def->os.arch); } +bool +qemuDomainIsXenFV(const virDomainDef *def) +{ + return qemuDomainMachineIsXenFV(def->os.machine, def->os.arch); +} + bool qemuDomainHasPCIRoot(const virDomainDef *def) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index af0bb04c45..1179b0d6dc 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -838,6 +838,7 @@ bool qemuDomainIsLoongArchVirt(const virDomainDef *def); bool qemuDomainIsRISCVVirt(const virDomainDef *def); bool qemuDomainIsPSeries(const virDomainDef *def); bool qemuDomainIsMipsMalta(const virDomainDef *def); +bool qemuDomainIsXenFV(const virDomainDef *def); bool qemuDomainHasPCIRoot(const virDomainDef *def); bool qemuDomainHasPCIeRoot(const virDomainDef *def); bool qemuDomainHasBuiltinIDE(const virDomainDef *def); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index b885fe7c77..6f7aeababe 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4868,8 +4868,8 @@ qemuValidateDomainDeviceDefInput(const virDomainInputDef *input, int cap; int ccwCap; - if (input->bus == VIR_DOMAIN_INPUT_BUS_PS2 && !ARCH_IS_X86(def->os.arch) && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_I8042)) { + if (input->bus == VIR_DOMAIN_INPUT_BUS_PS2 && + !virQEMUCapsSupportsI8042(qemuCaps, def)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("%1$s is not supported by this QEMU binary"), virDomainInputBusTypeToString(input->bus)); -- 2.45.0