qemu: Improve PS/2 controller detection

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@szczek.dev>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Kamil Szczęk 2024-08-19 01:17:11 +00:00 committed by Michal Privoznik
parent 22fc1e2977
commit 51521d13a8
5 changed files with 45 additions and 6 deletions

View File

@ -6008,6 +6008,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

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -4874,8 +4874,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));