(CCing people from the spapr PCI-express thread)
On Mon, Nov 21, 2016 at 11:11:58PM -0200, Eduardo Habkost wrote:
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.
Another 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 mak 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.
There are other comment below, at "Limitations" section:
The Proposed Interface
======================
This series adds a new field to the output of 'query-machines':
'supported-device-types'. It will contain a list of QOM type
names, that can be used to find the list of device types that can
be plugged in the machine by default. The type names reported on
the new field can then be used as the 'implements' argument on
the 'qom-list-types' command, to find out which device types can
be plugged on the machine.
Example output
--------------
(QEMU) query-machines
{
"return": [
[...]
{
"supported-device-types": [
"sys-bus-device"
],
"cpu-max": 1,
"hotpluggable-cpus": false,
"name": "none"
},
[...]
{
"supported-device-types": [
"sys-bus-device"
],
"cpu-max": 1,
"hotpluggable-cpus": false,
"name": "xenpv"
},
[...]
{
"supported-device-types": [
"sys-bus-device",
"floppy",
"i2c-slave",
"pci-device",
"isa-device",
"ide-device"
],
"name": "pc-i440fx-2.8",
"alias": "pc",
"is-default": true,
"cpu-max": 255,
"hotpluggable-cpus": true
},
[...]
{
"supported-device-types": [
"sys-bus-device",
"floppy",
"isa-device",
"ide-device"
],
"cpu-max": 1,
"hotpluggable-cpus": true,
"name": "isapc"
},
[...]
{
"supported-device-types": [
"sys-bus-device",
"floppy",
"i2c-slave",
"pci-device",
"isa-device",
"ide-device"
],
"cpu-max": 128,
"hotpluggable-cpus": true,
"name": "xenfv"
},
[...]
{
"alias": "q35",
"supported-device-types": [
"sys-bus-device",
"i2c-slave",
"PCIE-device",
"isa-device",
"ide-device"
],
"cpu-max": 288,
"hotpluggable-cpus": true,
"name": "pc-q35-2.8"
},
[...]
]
}
Considered alternatives
=======================
Indirect mapping (machine => bus => device)
-------------------------------------------
This RFC implements a mechanism to implement ax
machine-type => supported-device-types
mapping. An alternative solution I considered was to expose an
indirect mapping:
machine-type => default-bus-types
followed by
bus-type => supported-device-types.
But exposing only the resulting supported device-types list
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: default_bus_types, and a
new field to BusClass: supported_device_type.
The two fields are used to build the list of supported device
types for a given machine. On most cases, the normal QOM type
hierarchy is used to define the set of supported devices for a
bus. On the case of PCIe buses, a INTERFACE_PCIE_DEVICE interface
name was introduced, to indicate PCIe-capable devices.
This means we are duplicating information in some cases:
* BusClass::supported_device_type duplicates knowlege that is
already encoded in DeviceClass::bus_type.
To make sure both fields agree with each other, a new
device_class_set_bus_type() wrapper was added, to perform
additional validation.
* MachineClass::default_bus_type 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.
* PCIDeviceClass::is_express and INTERFACE_PCIE_DEVICE
both encode the same information about a PCI device class.
A future version of this series may include a
class_base_post_init hook that will allow TYPE_PCI_DEVICE to
validate/update is_express and the interface list to ensure
both are always consistent.
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
===========
"default defaults" vs "-nodefault defaults"
-------------------------------------------
Two bad news:
1) We need to differentiate buses created by the machine with
"-nodefaults" and buses that are created only without
"-nodefaults".
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.
We need to be able model both cases in the new interface.
Suggestions are welcome.
2) A lot of machine-types won't start if using
"-nodefaults -machine <machine>" without any extra devices or
drives.
Lots of machines require some drives or devices to be created
(especially ARM machines that require a SD drive to be
available).
Some machines will make QEMU exit, some of them simply segfault.
I am looking for ways to work around it so we can still validate
-nodefaults-based info on the test code.
Out of scope (in this version): bus IDs
---------------------------------------
This series only returns info about supported device-types, but I
plan to also report the bus IDs on a new version of this series.
Knowing the bus IDs for a machine is also important for
management software. (See spapr + PCIe root bus
example above.)
Additional comment about PCIe below:
TYPE_SYS_BUS_DEVICE is too generic
----------------------------------
Currently all machines have a TYPE_SYS_BUS bus, meaning all
TYPE_SYS_BUS_DEVICE subclasses are reported as supported.
The current solution in this series is to report
TYPE_SYS_BUS_DEVICE as supported by all machines. But we could
gradually add arch-specific or machine-family-specific interface
names that can be used on devices that are meant to work with
only a subset of TYPE_SYS_BUS_DEVICE subclasses.
A future version of this series may remove TYPE_SYS_BUS_DEVICE
from the supported-device-types output, and return a
arch-specific or machine-family-specific interface name to
restrict management software to a subset of TYPE_SYS_BUS_DEVICE
subclasses.
PCI vs PCIe
-----------
Machines with PCIe buses will report INTERFACE_PCIE_DEVICE on
supported-device-types.
Machines with legacy PCI buses will report TYPE_PCI_DEVICE on
supported-device-types.
The problem with the current approach is that PCIe devices are
TYPE_PCI_DEVICE subclasses. The allows PCI device classes to
indicate they are PCIe-capable, but there's no obvious way to
indicate that a device is PCIe-only. This needs to be addressed
in a future version of this series.
Suggestions are welcome.
I found out that this is a bit more complicated: not all
TYPE_PCIE_BUS instances are created equal. Some of them will
accept only PCIe devices, some of them can accept legacy PCI
devices.
The QMP interface I'm proposing shouldn't be affected by this,
but the implementation needs to be changed, as it is currently
based on an indirect
machine-type => bus-types => device-types
mapping, and a simple bus-type => device-type mapping won't work
for PCIe. Probably I will replace MachineClass::default_buses
with a MachineClass::default_device_types field. The
'device-type' QOM property behavior will probably change too, so
each PCIe bus can report an appropriate device type as supported.
Incomplete bus lists on some machines
-------------------------------------
With this series, not all machines classes are changed to add the
full list of device types on the 'supported-device-types'. To
allow the code to be updated gradually, qmp-machine-info.py has a
STRICT_ARCHES variable, that will make the test code require a
complete device type list only on some architectures.
Out of scope: Configurable buses
--------------------------------
There's no way to map machine options like "usb=on|off" to
device-types or buses. I plan to propose a new interface that
allows machine options to be mapped to buses/device-types later.
Out of scope: Deciding where to plug devices
--------------------------------------------
Once management software discovers which devices can be plugged
to a machine, it still has to discover or define where devices
can/should/will be plugged. This is out of the scope of this
series.
Out of scope: Hotplug
---------------------
The proposed interface is supposed to help management software
find which device types can be used when creating the VM. Device
hotplug is out of the scope of this series. However, the new
'device-types' QOM property on bus objects could be used to find
out which device types can be plugged on the existing buses.
---
Cc: libvir-list(a)redhat.com
Cc: Laine Stump <laine(a)redhat.com>
Eduardo Habkost (15):
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 device_type field to BusClass
machine: Add MachineClass::default_buses field
qmp: Add 'supported-device-types' field to 'query-machines'
pci: Introduce INTERFACE_PCIE_DEVICE interface name
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
hw/arm/aspeed.c | 2 +
hw/arm/collie.c | 1 +
hw/arm/cubieboard.c | 1 +
hw/arm/exynos4_boards.c | 5 ++
hw/arm/gumstix.c | 7 ++
hw/arm/highbank.c | 4 ++
hw/arm/imx25_pdk.c | 1 +
hw/arm/kzm.c | 1 +
hw/arm/musicpal.c | 1 +
hw/arm/nseries.c | 2 +
hw/arm/palm.c | 1 +
hw/arm/realview.c | 1 +
hw/arm/spitz.c | 10 +++
hw/arm/stellaris.c | 4 ++
hw/audio/intel-hda.c | 9 ++-
hw/block/fdc.c | 17 +++--
hw/block/nvme.c | 4 ++
hw/char/virtio-serial-bus.c | 3 +-
hw/core/bus.c | 9 +++
hw/core/machine.c | 18 ++++-
hw/core/qdev.c | 8 +++
hw/core/sysbus.c | 3 +-
hw/i2c/core.c | 9 ++-
hw/i386/pc_piix.c | 13 ++++
hw/i386/pc_q35.c | 4 ++
hw/ide/qdev.c | 3 +-
hw/input/adb.c | 9 ++-
hw/ipack/ipack.c | 9 ++-
hw/isa/isa-bus.c | 3 +-
hw/mips/mips_malta.c | 7 ++
hw/mips/mips_r4k.c | 2 +
hw/misc/auxbus.c | 3 +-
hw/net/e1000e.c | 4 ++
hw/net/vmxnet3.c | 4 ++
hw/pci-bridge/ioh3420.c | 4 ++
hw/pci-bridge/xio3130_downstream.c | 4 ++
hw/pci/pci.c | 16 ++++-
hw/ppc/e500plat.c | 3 +
hw/ppc/mac_newworld.c | 4 ++
hw/ppc/mac_oldworld.c | 3 +
hw/ppc/mpc8544ds.c | 4 ++
hw/ppc/ppc440_bamboo.c | 1 +
hw/ppc/prep.c | 4 ++
hw/ppc/spapr_vio.c | 3 +-
hw/s390x/css-bridge.c | 2 +
hw/s390x/event-facility.c | 3 +-
hw/s390x/s390-pci-bus.c | 9 ++-
hw/s390x/s390-virtio-ccw.c | 6 ++
hw/s390x/virtio-ccw.c | 2 +-
hw/scsi/megasas.c | 7 ++
hw/scsi/scsi-bus.c | 3 +-
hw/scsi/vmw_pvscsi.c | 1 +
hw/sd/core.c | 7 ++
hw/sd/sd.c | 2 +-
hw/ssi/ssi.c | 9 ++-
hw/usb/bus.c | 3 +-
hw/usb/dev-smartcard-reader.c | 9 ++-
hw/usb/hcd-xhci.c | 4 ++
hw/vfio/pci.c | 4 ++
hw/virtio/virtio-bus.c | 1 +
hw/virtio/virtio-pci.c | 4 ++
hw/virtio/virtio.c | 2 +-
include/hw/boards.h | 5 ++
include/hw/pci/pci.h | 3 +
include/hw/qdev-core.h | 4 ++
qapi-schema.json | 9 ++-
scripts/qemu.py | 25 +++++--
scripts/qtest.py | 15 +++-
tests/Makefile.include | 39 ++++++++++-
tests/qmp-machine-info.py | 138 +++++++++++++++++++++++++++++++++++++
vl.c | 11 +++
71 files changed, 518 insertions(+), 37 deletions(-)
create mode 100755 tests/qmp-machine-info.py
--
2.7.4
--
Eduardo