[libvirt] Examples of QEMU machine-type-specific code in libvirt?

Laine Stump laine at laine.org
Wed Aug 3 21:45:40 UTC 2016

On 08/03/2016 04:49 PM, Eduardo Habkost wrote:
> Hi,
> I am collecting some material for my KVM Forum talk, and I am
> interested in hearing from libvirt developers about instances
> where machine-type-specific information is needed by libvirt, and
> the info is not provided by QEMU.
> I found some instances where machine-type capabilities are
> hardcoded in libvirt itself (see below[1]), but I would like to
> know if you have other examples. They may be about things that
> are already done by libvirt today, or about things that you would
> like to do in the future.

(I'm guessing this first one may be what put you onto the topic in the 
first place, but for completeness' sake...)

Without actually instantiating a virtual machine of a particular type, 
It's not possible to know whether that machinetype has a legacy-pci root 
bus, or a PCIe root complex (or neither). This means we have to guess, 
and it has big implications. In some cases our guess is 100% correct 
(i440fx and q35 machinetypes inqemu-system-x86_64) but in other cases we 
may or may not be right (the aarch64 "virt" machinetype, which as I 
understand may or may not have a PCIe root complex, depending on the 
qemu version?)

This in turn leads to differences in which PCI controllers are available 
for a machinetype (e.g., even though the ioh3420 (pcie-root-port) device 
is advertised as available in qemu-system_x86_64, it's only actually 
usable for q35-based machinetypes; same for pxb-pcie, and the xio3130 
upstream/downstream ports.

Same thing goes for some other integrated devices - Q35-based 
machinetypes include an AHCI controller while i440fx machinetypes (as 
well as "sun4u" and "g3beige") include an IDE controller, and these are 
at fixed addresses (and can't be removed).

And then there is the Q35 machinetype vs. fdc. Yeah, sure nobody in this 
age should be using a floppy disk (even emulated), but even within 
different versions of the q35 machinetype, a floppy disk controller may 
or may not be present (see qemuDominMachineNeedsFDC()).

You may say that libvirt could solve this problem when probing qemu 
capabilities by simply instantiating a virtual machine and then 
examining its devices, but (I've been told) this is too expensive 
(especially since we'd need to do it for every machinetype that was 
used, although admittedly we've been caching the results for quite 
awhile now, so the impact may not be as great as it once was).

> [1] Examples where machine-type names are hardcoded in libvirt:

Keep in mind that some of those places we're checking os.machine are 
actually utility functions whose only job is to check the machinetype 
and return true/false, and they're called from several other places. For 
example qemuDomainMachineIsQ35(), qemuDomainMachineIs440FX(), and 
qeuDomainMachineIsVirt() (which actually checks if the arch is armv7l or 
aarch64 *and* machinetype is "virt*").

Which points out - it's a slightly different issue (since in these cases 
at least it's a different qemu binary), but you may also want to look at 
places where we examine "os.arch" and make a decision based on that.

> src/qemu/qemu_capabilities.c:            STREQ(def->os.machine, "ppce500"))
> src/qemu/qemu_capabilities.c:            STREQ(def->os.machine, "prep"))
> src/qemu/qemu_capabilities.c:            STREQ(def->os.machine, "bamboo"))
> src/qemu/qemu_capabilities.c:        if (STREQ(def->os.machine, "mpc8544ds"))
> src/qemu/qemu_capabilities.c:        if (STREQ(machines[i]->name, "none"))
> src/qemu/qemu_capabilities.c:        STREQ(def->os.machine, "isapc");
> src/qemu/qemu_capabilities.c:        (STRNEQ(machine, "pseries") && !STRPREFIX(machine, "pseries-")))
> src/qemu/qemu_capabilities.c:        (STRNEQ(machine, "pseries") && !STRPREFIX(machine, "pseries-")))
> src/qemu/qemu_capabilities.c:    if (STRNEQ(domCaps->machine, "virt") &&
> src/qemu/qemu_capabilities.c:        !STRPREFIX(domCaps->machine, "virt-"))
> src/qemu/qemu_command.c:    if (STRPREFIX(def->os.machine, "s390-virtio") &&
> src/qemu/qemu_domain.c:        if (STREQ(def->os.machine, "isapc")) {
> src/qemu/qemu_domain.c:        if (STREQ(def->os.machine, "versatilepb"))
> src/qemu/qemu_domain.c:    return (STRPREFIX(def->os.machine, "pc-q35") ||
> src/qemu/qemu_domain.c:            STREQ(def->os.machine, "q35"));
> src/qemu/qemu_domain.c:    return (STREQ(def->os.machine, "pc") ||
> src/qemu/qemu_domain.c:            STRPREFIX(def->os.machine, "pc-0.") ||
> src/qemu/qemu_domain.c:            STRPREFIX(def->os.machine, "pc-1.") ||
> src/qemu/qemu_domain.c:            STRPREFIX(def->os.machine, "pc-i440") ||
> src/qemu/qemu_domain.c:            STRPREFIX(def->os.machine, "rhel"));
> src/qemu/qemu_domain.c:    char *p = STRSKIP(def->os.machine, "pc-q35-");
> src/qemu/qemu_domain.c:    return STRPREFIX(def->os.machine, "s390-ccw");
> src/qemu/qemu_domain.c:    if (STRNEQ(def->os.machine, "virt") &&
> src/qemu/qemu_domain.c:        !STRPREFIX(def->os.machine, "virt-"))
> src/qemu/qemu_domain.c:    if (STRNEQ(def->os.machine, "pseries") &&
> src/qemu/qemu_domain.c:        !STRPREFIX(def->os.machine, "pseries-"))
> src/qemu/qemu_domain.c:        STREQ(def->os.machine, "malta") ||
> src/qemu/qemu_domain.c:        STREQ(def->os.machine, "sun4u") ||
> src/qemu/qemu_domain.c:        STREQ(def->os.machine, "g3beige");
> src/qemu/qemu_domain_address.c:    if (!(STRPREFIX(def->os.machine, "vexpress-") ||
> src/qemu/qemu_domain_address.c:    if (STREQ(def->os.machine, "versatilepb"))

More information about the libvir-list mailing list