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(a)szczek.dev>
---
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