[libvirt] [RFC v2 00/20] qmp: Report bus information on 'query-machines'

Eduardo Habkost ehabkost at redhat.com
Fri Nov 25 22:05:36 UTC 2016


Changes v1 -> v2:
* v1 series subject was:
  "qmp: Report supported device types on 'query-machines'"
* Now we return additional bus information: bus ID, bus type,
  and the list of accepted device types on each bus
* Now hotplug can be covered because accepted-device-types can
  be set by individual bus instances if necessary
* Now the new field is optional, and every machine having the
  new field are now validated in "strict mode" on test code
  (meaning all buses must be present on the list)
  * TODO: only PC was converted, machines from other
    architectures don't include the field yet
* Legacy-PCI vs PCIe is now handled:
  * PCIDeviceClass::is_express field was removed
  * Defined INTERFACE_LEGACY_PCI_DEVICE and INTERFACE_PCIE_DEVICE,
    buses and devices now report appropriate interface names
  * Now PCIe buses can return the right information
    because each bus instance can set its own
    accepted-device-types list
  * TODO: PCIe pci-bridge classes need to be changed to not include
    INTERFACE_LEGACY_PCI_DEVICE
  * TODO: replace q35 hack with appropriate code that set
    Legacy-PCI rules in PCI code
* Removed patches from v1:
  * pc: Initialize default bus lists
  * s390x: Initialize default bus lists
  * arm: Initialize default bus lists
  * mips: Initialize default bus lists
  * ppc: Initialize default bus lists
  * qdev: Add device_class_set_bus_type() function
    (validation is more difficult with the PCI/PCIe rules, plan
    is to try to remove DeviceClass::bus_type field, se
    "Limitations" below)
* See individual patches for additional details

The Problem
===========

Currently management software has no way to find out which device
types can be plugged in a machine, unless the machine is already
initialized.

Even after the machine is initialized, there's no way to map
existing bus types to supported device types unless management
software hardcodes the mapping between bus types and device
types.

Example: floppy support on q35 vs i440fx
----------------------------------------

There's no way for libvirt to find out that there's no floppy
controller on pc-q35-* machine-types by default.

With this series, pc-i440fx-* will report "floppy" as a supported
device type, but pc-q35-* will not.

Example: Legacy PCI vs vs PCIe devices
--------------------------------------

Some devices require a PCIe bus to be available, others work on
both legacy PCI and PCIe, while others work only on a legacy PCI
bus.

Currently management software has no way to know which devices
can be added to a given machine, unless it hardcodes machine-type
names and device-types names.

Example: spapr and PCIe root bus
--------------------------------

See the thread at:
  Subject: [RFC PATCH qemu] spapr_pci: Create PCI-express root bus by default

If we make new spapr machine-type versions create a PCIe root
bus, management software will need a way to find out:

1) The type of the default bus for the machine type;
2) The ID of the default bus for the machine type.

Otherwise, management software will have to hardcode it based on
machine-type version. The proposed interface should solve this
problem.

The Proposed Interface
======================

Bus info on query-machines
--------------------------

This series adds a new field to the output of 'query-machines':
'always-available-buses'. It will contain a a list of
MachineBusInfo structs. MachineBusInfo will contain:
* bus-id: The bus ID
* bus-type: The bus type
* accepted-device-types: A list of accepted device types for the bus.

bus-id can be used to find out what's the right "bus" argument to
be used when adding a device to the machine configuration (e.g.
when using -device and device_add).

accepted-device-types can be used as the 'implements' argument on
the 'qom-list-types' command, to find out which device types can
be plugged on the bus.

accepted-device-types property on bus objects
---------------------------------------------

This series also adds a 'accepted-device-types' property to bus
objects, so management software can check which kinds of devices
can be plugged at runtime.

Example output
--------------

TODO: update it.

Considered alternatives
=======================

Indirect mapping (machine => bus => device)
-------------------------------------------

This RFC implements a mechanism to implement ax
  machine-type => accepted-device-types
mapping. An alternative solution I considered was to expose an
indirect mapping:
  machine-type => default-bus-types
followed by
  bus-type => accepted-device-types.

But some buses have no correct bus-type => accepted-device-types
mapping. PCIe buses, for example, may or may not accept legacy
PCI buses, depending on the machine and  the bus topology.

imposes less restrictions on how the device and bus type
hierarchy is implemented inside QEMU. There's still a
  machine-type => bus-type => device-type
mapping implemented internally, but it is an implementation
detail on the current version, and not part of the
externally-visible interface.

The Implementation
==================

This add a new field to MachineClass: always_available_buses, a
new field to BusState: accepted_device_types, and a new field to
BusClass: device_type.

On most cases, the normal QOM type hierarchy is used to define
the set of accepted devices for a bus. On the case of PCI buses,
INTERFACE_PCIE_DEVICE and INTERFACE_LEGACY_PCI_DEVICE interface
names were introduced, to indicate the set of devices accepted by
PCI buses.

That means we are duplicating information:
MachineClass::always_available_buses duplicates knowledge that is
already encoded in the machine init function.

To make sure the information is correct, a qmp-machine-info.py
test case is added, that will validate the supported-device-types
field based on the buses created by the machine.

Test Code
---------

qdev-based test code for the new field was implemented in a
Python script.  Some extra support was implemented in
tests/Makefile.include, scripts/qemu.py and scripts/qtest.py to
allow the test to be implemented.

Limitations
===========

TODO: "slots" vs "buses"
------------------------

The current interface is returning information about "available
buses". Future versions might return more detailed information
about "slots" where devices can be plugged. This would make the
proposed mechanism more flexible, and cover cases like CPU
hotplug (in other words, the new interface could replace
query-hotpluggable-cpus in a generic way).

"default defaults" vs "-nodefault defaults"
-------------------------------------------

libvirt use -nodefaults when starting QEMU, so knowing which
buses are available when using -nodefaults is more interesting
for them.

Other software, on the other hand, might be interested in the
results without -nodefaults.

The new 'always-available-bus' field won't cover the more general
cases, where "-nodefaults" is not used, or when there are extra
QEMU options that create more buses (e.g.  "-machine usb=on", or
explicit -device options that would create additional buses).

Additional mechanisms may be added to let management software to
ask which buses are created when extra options are used, but
maybe thoses cases would be more easily solved if management
software checks the bus list at runtime (after the machine was
actually created).

TYPE_SYS_BUS_DEVICE is too generic
----------------------------------

Currently all machines have a TYPE_SYS_BUS bus, and all
TYPE_SYS_BUS_DEVICE subclasses are reported as supported by that
bus.

On the other hand, omitting sysbus would make query-machines lie
about supporting sysbus devices, and would require management
software to add special cases for sysbus devices. For this
reason, sysbus is being included in the output of query-machines,
although its accepted-device-types info is less useful than the
information about other buses.

Future versions of QEMU can keep the same interface, but make it
include more useful information, e.g., return more specific bus
info, with type names that exclude sysbus devices that can't
possibly work with the machine.

PCI vs PCIe
-----------

This was a limitation on v1, but I believe the problem was
addressed on v2.

This series defines two new interface names:
INTERFACE_LEGACY_PCI_DEVICE and INTERFACE_PCIE_DEVICE.

* Legacy PCI devices will implement INTERFACE_LEGACY_PCI_DEVICE.
* PCIe devices will implement INTERFACE_PCIE_DEVICE.
* Hybrid devices that support both will implement both
* interfaces.

Buses will have accepted-device-types set accordingly:

* Legacy PCI buses will report INTERFACE_LEGACY_PCI_DEVICE on
  accepted-device-types.
* PCIe buses that accept only PCIe devices will report
  INTERFACE_PCIE_DEVICE on accepted-device-types.
* PCIe buses that accept both PCIe and legacy PCI devices will
  report both INTERFACE_PCIE_DEVICE and
  INTERFACE_LEGACY_PCI_DEVICE on accepted-device-types.

The Q35 root bus is the only existing example of a hybrid bus.
See the next section about the hack where this is implemented.

Q35 root bus hack
-----------------

This series includes a hack on Q35 code to add
INTERFACE_LEGACY_PCI_DEVICE to accepted-device-types on the root
PCIe bus. Suggestions on where this information should be encoded
are welcome.

Only PC is covered
------------------

This series sets always-available-buses only on the PC
machine-types, by now. Future versions might have the field added
to other machines. sPAPR is an obvious candidate, as there are
plans to change new spapr machine-type versions to use PCIe as
the root bus.

Out of scope: Configurable buses
--------------------------------

There's no way to map machine options like "usb=on|off" to
device-types or buses. This is not on the scope of this series.

Additional mechanisms may be added to let management software to
ask which buses are created when extra options are used, but
maybe thoses cases would be more easily solved if management
software checks the bus list at runtime (after the machine was
actually created).

Existing DeviceClass::bus_type field
------------------------------------

The new BusClass::device_type and BusState::accepted_device_types
fields duplicate knowledge that is already encoded in
DeviceClass::bus_type.

v1 of this series included code that validated both fields to
ensure they are consistent with each other. But the PCI/PCIe
hierarchy makes validation more difficult, so the validation code
was removed on v2.

The DeviceClass::bus_type abstraction breaks in the case of
hybrid PCI buses, because only a bus type name is not enough
information to find the right bus to plug a device. This needs to
be addressed somehow (maybe DeviceClass::bus_type can be
completely removed), but I didn't look at the device_add code to
find out the best way to do that.

---
Cc: libvir-list at redhat.com
Cc: Laine Stump <laine at redhat.com>
Cc: Alexey Kardashevskiy <aik at ozlabs.ru>
Cc: Greg Kurz <groug at kaod.org>
Cc: David Gibson <david at gibson.dropbear.id.au>
Cc: Andrea Bolognani <abologna at redhat.com>,
Cc: Eric Blake <eblake at redhat.com>
Cc: Cornelia Huck <cornelia.huck at de.ibm.com>
Cc: David Hildenbrand <david at redhat.com>

Eduardo Habkost (20):
  qemu.py: Make logging optional
  qtest.py: Support QTEST_LOG environment variable
  qtest.py: make logging optional
  qtest.py: Make 'binary' parameter optional
  tests: Add rules to non-gtester qtest test cases
  qdev: Add 'accepted-device-types' property to BusClass
  qmp: Add 'always-available-buses' field to 'query-machines'
  virtio-pci: Set PCIDeviceClass::is_express=1
  vmxnet3: Set PCIDeviceClass::is_express=1
  pvscsi: Set PCIDeviceClass::is_express=1
  pci: INTERFACE_LEGACY_PCI_DEVICE and INTERFACE_PCIE_DEVICE interfaces
  pci: Replace is_express with INTERFACE_PCIE_DEVICE
  [trivial] edu: Move edu_info outside function
  [automated] Add INTERFACE_LEGACY_PCI_DEVICE to all PCI device
    subclasses
  eepro100: Add INTERFACE_LEGACY_PCI_DEVICE
  [incomplete] remove INTERFACE_LEGACY_PCI_DEVICE from PCIe-only devices
  pci: Set device_type on bus classes
  q35: Hack to make root bus accept legacy PCI devices
  pci: validate interfaces on base_class_init
  pc: Initialize default bus lists

 hw/acpi/piix4.c                     |   1 +
 hw/audio/ac97.c                     |   4 +
 hw/audio/es1370.c                   |   4 +
 hw/audio/intel-hda.c                |  11 +++
 hw/block/fdc.c                      |  15 +++-
 hw/block/nvme.c                     |   5 +-
 hw/char/serial-pci.c                |  12 +++
 hw/char/virtio-serial-bus.c         |   1 +
 hw/core/bus.c                       |  21 +++++
 hw/core/machine.c                   |  33 ++++++-
 hw/core/sysbus.c                    |   1 +
 hw/display/cirrus_vga.c             |   4 +
 hw/display/qxl.c                    |   4 +
 hw/display/vga-pci.c                |   4 +
 hw/display/vmware_vga.c             |   4 +
 hw/i2c/core.c                       |   7 ++
 hw/i2c/smbus_ich9.c                 |   4 +
 hw/i386/amd_iommu.c                 |   4 +
 hw/i386/kvm/pci-assign.c            |   4 +
 hw/i386/pc.c                        |   1 +
 hw/i386/pc_piix.c                   |  29 ++++++
 hw/i386/pc_q35.c                    |  21 +++++
 hw/i386/xen/xen_platform.c          |   4 +
 hw/i386/xen/xen_pvdevice.c          |   4 +
 hw/ide/ich.c                        |   4 +
 hw/ide/pci.c                        |   4 +
 hw/ide/qdev.c                       |   1 +
 hw/input/adb.c                      |   7 ++
 hw/ipack/ipack.c                    |   7 ++
 hw/ipack/tpci200.c                  |   4 +
 hw/isa/i82378.c                     |   4 +
 hw/isa/isa-bus.c                    |   1 +
 hw/isa/lpc_ich9.c                   |   1 +
 hw/isa/piix4.c                      |   4 +
 hw/isa/vt82c686.c                   |  16 ++++
 hw/mips/gt64xxx_pci.c               |   4 +
 hw/misc/auxbus.c                    |   1 +
 hw/misc/edu.c                       |  20 +++--
 hw/misc/ivshmem.c                   |   4 +
 hw/misc/macio/macio.c               |   4 +
 hw/misc/pci-testdev.c               |   4 +
 hw/net/e1000.c                      |   4 +
 hw/net/e1000e.c                     |   5 +-
 hw/net/eepro100.c                   |   5 ++
 hw/net/ne2000.c                     |   4 +
 hw/net/pcnet-pci.c                  |   4 +
 hw/net/rocker/rocker.c              |   4 +
 hw/net/rtl8139.c                    |   4 +
 hw/net/vmxnet3.c                    |  36 ++------
 hw/pci-bridge/dec.c                 |   4 +
 hw/pci-bridge/ioh3420.c             |   6 +-
 hw/pci-bridge/pci_expander_bridge.c |   8 ++
 hw/pci-bridge/xio3130_downstream.c  |   6 +-
 hw/pci-bridge/xio3130_upstream.c    |   6 +-
 hw/pci-host/apb.c                   |   4 +
 hw/pci-host/bonito.c                |   4 +
 hw/pci-host/gpex.c                  |   4 +
 hw/pci-host/grackle.c               |   4 +
 hw/pci-host/piix.c                  |   8 ++
 hw/pci-host/ppce500.c               |   4 +
 hw/pci-host/prep.c                  |   4 +
 hw/pci-host/q35.c                   |  14 +++
 hw/pci-host/uninorth.c              |  16 ++++
 hw/pci-host/versatile.c             |   4 +
 hw/pci/pci.c                        |  41 ++++++++-
 hw/pci/pci_bridge.c                 |   4 +
 hw/ppc/ppc4xx_pci.c                 |   4 +
 hw/ppc/spapr_vio.c                  |   1 +
 hw/s390x/css-bridge.c               |   2 +
 hw/s390x/event-facility.c           |   1 +
 hw/s390x/s390-pci-bus.c             |   7 ++
 hw/scsi/esp-pci.c                   |   4 +
 hw/scsi/lsi53c895a.c                |   4 +
 hw/scsi/megasas.c                   |  12 ++-
 hw/scsi/mptsas.c                    |   4 +
 hw/scsi/scsi-bus.c                  |   1 +
 hw/scsi/vmw_pvscsi.c                |  29 ++----
 hw/sd/core.c                        |   7 ++
 hw/sd/sdhci.c                       |   4 +
 hw/sh4/sh_pci.c                     |   4 +
 hw/sparc64/sun4u.c                  |   4 +
 hw/ssi/ssi.c                        |   7 ++
 hw/usb/bus.c                        |   1 +
 hw/usb/dev-smartcard-reader.c       |   7 ++
 hw/usb/hcd-ehci-pci.c               |   4 +
 hw/usb/hcd-ohci.c                   |   4 +
 hw/usb/hcd-uhci.c                   |   4 +
 hw/usb/hcd-xhci.c                   |   5 +-
 hw/vfio/pci-quirks.c                |   4 +
 hw/vfio/pci.c                       |   6 +-
 hw/virtio/virtio-bus.c              |   1 +
 hw/virtio/virtio-pci.c              |  27 +++---
 hw/watchdog/wdt_i6300esb.c          |   4 +
 hw/xen/xen_pt.c                     |   4 +
 include/hw/boards.h                 |   7 ++
 include/hw/pci/pci.h                |   9 +-
 include/hw/qdev-core.h              |   8 ++
 qapi-schema.json                    |  37 +++++++-
 scripts/qemu.py                     |  25 ++++--
 scripts/qtest.py                    |  15 +++-
 tests/Makefile.include              |  39 +++++++-
 tests/qmp-machine-info.py           | 173 ++++++++++++++++++++++++++++++++++++
 vl.c                                |   6 ++
 103 files changed, 882 insertions(+), 102 deletions(-)
 create mode 100755 tests/qmp-machine-info.py

-- 
2.7.4




More information about the libvir-list mailing list