Eduardo Habkost <ehabkost(a)redhat.com> writes:
This adds a new command to QMP: query-device-slots. It will allow
management software to query possible slots where devices can be
plugged.
This implementation of the command will return:
* Multiple PCI slots per bus, in the case of PCI buses;
* One slot per bus for the other buses (that don't
implement slot enumeration yet);
* One slot for each entry from query-hotpluggable-cpus.
Git tree
--------
This patch needs the previous query-machines series I am working
on. The full tree can be found on the git tree at:
git://github.com/ehabkost/qemu-hacks.git work/query-machines-bus-info
Example output
--------------
The following output was returned by QEMU when running it as:
$ qemu-system-x86_64 -machine q35 \
-readconfig docs/q35-chipset.cfg \
-smp 4,maxcpus=8,sockets=2,cores=2,threads=2
{
"return": [
{
"available": false,
"hotpluggable": false,
"props": {
"bus": "i2c"
Missing: bus "i2c-bus" device address, property name "address", value
0..255.
},
"type": "non-slot",
I guess "non-slot" means "props" is incomplete, but the rest should
be
okay.
"accepted-device-types": [
"i2c-slave"
]
},
{
"available": false,
"hotpluggable": false,
"props": {
"bus": "ide.4"
Bus "IDE" device address property "unit", value 0 (because this is
SATA,
for PATA it would be 0..1).
},
"type": "non-slot",
>
"accepted-device-types": [
> "ide-device"
> ]
> },
[...]
> {
> "available": false,
> "hotpluggable": false,
> "props": {
> "bus": "main-system-bus"
},
"type": "non-slot",
>
"accepted-device-types": [
> "sys-bus-device"
> ]
> },
Can't give guidance on this one, I'm afraid.
> {
> "available": false,
> "hotpluggable": false,
> "props": {
> "bus": "isa.0"
},
"type": "non-slot",
>
"accepted-device-types": [
> "isa-device"
> ]
> },
Bus "ISA" is iffy, too.
{
"available": false,
"hotpluggable": false,
"props": {
"bus": "pcie.0",
"device-number": 0
Really? "device_add e1000e,help" shows now property "device-number".
Oh, I see, you're adding it in this patch, along with "function".
},
"type": "pci",
"accepted-device-types": [
"legacy-pci-device",
"pci-express-device"
]
},
{
"available": false,
"hotpluggable": false,
"props": {
"bus": "pcie.0",
"device-number": 1
},
"type": "pci",
"accepted-device-types": [
"legacy-pci-device",
"pci-express-device"
]
},
[...]
{
"available": false,
"hotpluggable": false,
"props": {
"bus": "pcie.0",
"device-number": 31
},
"type": "pci",
"accepted-device-types": [
"legacy-pci-device",
"pci-express-device"
]
},
Design question: do we need to describe the bus with 32 separate
objects, or would a single object do? The objects only differ in the
value of props.device-number...
For a hypothetical bus with uint32_t device addresses, separate objects
would be impossible. So we probably need to describe slot sets, anyway.
{
"available": true,
"hotpluggable": true,
"props": {
"bus": "ich9-pcie-port-1",
"device-number": 0
},
"type": "pci",
"accepted-device-types": [
"pci-express-device"
]
},
{
"available": true,
"hotpluggable": true,
"props": {
"bus": "ich9-pcie-port-2",
"device-number": 0
},
"type": "pci",
"accepted-device-types": [
"pci-express-device"
]
},
{
"available": true,
"hotpluggable": true,
"props": {
"bus": "ich9-pcie-port-3",
"device-number": 0
},
"type": "pci",
"accepted-device-types": [
"pci-express-device"
]
},
{
"available": true,
"hotpluggable": true,
"props": {
"bus": "ich9-pcie-port-4",
"device-number": 0
},
"type": "pci",
"accepted-device-types": [
"pci-express-device"
]
},
{
"available": false,
"hotpluggable": false,
"props": {
"bus": "ich9-pci-bridge",
"device-number": 0
},
"type": "pci",
"accepted-device-types": [
"legacy-pci-device"
]
},
[...]
{
"available": false,
"hotpluggable": false,
"props": {
"bus": "ich9-pci-bridge",
"device-number": 31
},
"type": "pci",
"accepted-device-types": [
"legacy-pci-device"
]
},
Likewise.
> {
> "available": true,
> "hotpluggable": true,
> "props": {
> "bus": "ich9-ehci-1.0"
},
"type": "non-slot",
>
"accepted-device-types": [
> "usb-device"
> ]
> },
Okay, more bad news: bus "usb-bus" device address property is "port",
value is a sequence of port numbers separated by '.'. The reason is
"convenience"
A real USB host controller has a fixed number of ports, numbered 1..N.
This one has six.
A real USB hub device plugs into a port and in turn provides a fixed
number of ports, numbered 1..N. The USB hub device we model provides
eight.
An obvious way to model this would be to have the host controller
provide a bus with a fixed number of slots, and the usb-hub provide a
separate bus with eight. This is how we do PCI bridges. But it's not
how we do USB hubs.
Host software can treat the tree formed by USB host controller, hubs and
other devices as a single bus, and that's how we model it.
A "port" value that is a single number addresses that port on the host
controller.
A value containing '.' addresses something behind a hub. The leftmost
number addresses a host controller port. A hub must be plugged in
there. Recurse for the rest of the port string.
If you device_add an USB device without specifying a port, it picks an
unused one. When it has to pick the last port, it tries to add a
usb-hub device there, which provides eight ports, then picks a port for
your device. If adding the usb-hub succeeds, it'll get the new hub's
port 1. Else, it gets the last port. There's a hard-coded limit of
five on the depth of the hub chain. So, if you keep adding USB devices
to the bus provided by ich9-ehci, the first five go into ports "1", ...,
"5", the sixth goes into "6.1" (with usb-hub in port "6"),
and so forth,
until the 41st goes into "6.8.8.8.8.8". Adding hubs manually permits
more devices.
If you do specify "port", then that port must already exist.
I think the sanest way to represent the existing ports is enumerating
them, like this:
{
"available": true,
"hotpluggable": true,
"props": {
"bus": "ich9-ehci-1.0", "port":
"1"
},
"type": "usb",
"accepted-device-types": [
"usb-device"
]
},
[...]
{
"available": true,
"hotpluggable": true,
"props": {
"bus": "ich9-ehci-1.0", "port":
"6"
},
"type": "usb",
"accepted-device-types": [
"usb-device"
]
},
Plugging usb-hub into a port with port: "P" then flips that port's
"available" to false, and adds eight new ports with "port":
"P.1",
... "P.8".
So, plugging a device can not only add buses provided by the device, but
also, and less obviously, add slots to the bus it plugs into! Likewise
for unplug.
Perhaps we should emit events when slots come and go.
> {
> "available": true,
> "hotpluggable": true,
> "props": {
> "bus": "ich9-ehci-2.0"
},
"type": "non-slot",
>
"accepted-device-types": [
> "usb-device"
> ]
> },
> {
> "available": false,
> "hotpluggable": false,
> "props": {
> "bus": "ich9-hda-audio.0"
Bus "HDA" device address property is "cad", value 0..14.
},
"type": "non-slot",
>
"accepted-device-types": [
> "hda-codec"
> ]
> },
> {
> "available": true,
> "hotpluggable": true,
> "props": {
> "socket-id": 1,
> "core-id": 1,
> "thread-id": 1
> },
> "type": "cpu",
> "accepted-device-types": [
> "qemu64-x86_64-cpu"
> ]
> },
You know CPUs better than me.
[More of them...]
]
}
There's still more...
Bus "SCSI" device address property is "scsi-id", value 0..N, where N
depends on the SCSI HBA.
Bus "virtio-serial-bus" device address property is "nr", value 0..N,
where N is configurable, currenrly up to 511.
ccid-bus device address property is "slot", value 0..N, where N depends
on the device providing the bus (I think).
Buses not yet covered by docs/qdev-device-use.txt: "floppy-bus",
"apple-desktop-bus", "IndustryPack", "aux-bus",
"spapr-vio-bus",
"virtual-css-bus", "s390-sclp-events-bus", "s390-pcibus",
"sd-bus",
"SSI", "virtio-bus", "xen-sysbus". Grep for ".parent =
TYPE_BUS".
To find all buses in a certain build, use:
{ "execute": "qom-list-types", "arguments": {
"implements": "bus" } }
[No code review, yet]