[libvirt] [PATCH 00/15] support for pxb and pxb-pcie controllers

These two controllers are used to create a new root bus on a 440fx (pxb) or q35 (pxb-pie) virtual machine. There may be other use cases, but the main reason for me taking the time to support a separate root bus is to have assigned devices be visible in the guest on a different NUMA node, so that the guest can be aware of the locality of the device wrt CPU and memory that are on different NUMA nodes - although you aren't required to, you can add a <node>N</node> subelement to the bus' <target> element to indicate which NUMA node it is on (it's up to the management application to place devices on that bus that really are on the given NUMA node in the host). There are several differences between pxb and pxb-pcie, which are detailed in the individual commit log messages, but in short: 1) pxb is for 440fx, pxb-pcie for q35 (they *might* work on other arches/machinetypes that have a PCI or PCIe bus, but I haven't enabled that) 2) pxb has an integrate d pci-bridge with 32 slots that are (should be) hotplug-capable, while pxb-pcie supplies only a single slot, and it will only accept a pcie-root-port (which will then accept a single device, hotplug-capable) or a pcie-switch-upstream-port. Along the way I encountered a few minor problems/ugliness that I took care of in patches 01/15 - 09/15. pxb support is in 10-12, and pxb-pcie is in 13-15 There is a bugzilla record associated with this: https://bugzilla.redhat.com/show_bug.cgi?id=1103314 Laine Stump (15): schema: make pci slot and function optional schema: rename uint8range/uint24range to uint8/uint24 schema: new basic type - uint16 schema: allow pci address attributes to be in decimal conf: use #define instead of literal for highest slot in upstream port conf: allow use of slot 0 in a dmi-to-pci-bridge conf/qemu: change the way VIR_PCI_CONNECT_TYPE_* flags work conf: utility function to convert PCI controller model into connect type qemu: set PCI controller default modelName in a separate function qemu: add capabilities bit for device "pxb" conf: new pci controller model pci-expander-bus qemu: support new pci controller model "pci-expander-bus" qemu: add capabilities bit for device "pxb-pcie" conf: new pci controller model pcie-expander-bus qemu: support new pci controller model "pcie-expander-bus" docs/formatdomain.html.in | 74 +++- docs/schemas/basictypes.rng | 63 ++-- docs/schemas/domaincommon.rng | 23 +- docs/schemas/networkcommon.rng | 12 +- docs/schemas/nwfilter.rng | 16 +- src/bhyve/bhyve_device.c | 10 +- src/conf/domain_addr.c | 119 +++++-- src/conf/domain_addr.h | 68 ++-- src/conf/domain_conf.c | 61 +++- src/conf/domain_conf.h | 11 +- src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 74 ++++ src/qemu/qemu_domain.c | 42 +++ src/qemu/qemu_domain_address.c | 305 +++++++++------- tests/qemucapabilitiesdata/caps_2.4.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.5.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 2 + tests/qemucapabilitiesdata/caps_2.6.0-1.replies | 3 + .../qemuxml2argv-aarch64-virtio-pci-default.args | 2 +- ...l2argv-aarch64-virtio-pci-manual-addresses.args | 2 +- .../qemuxml2argv-pci-expander-bus-bad-machine.xml | 167 +++++++++ .../qemuxml2argv-pci-expander-bus-bad-node.xml | 160 +++++++++ .../qemuxml2argv-pci-expander-bus.args | 87 +++++ .../qemuxml2argv-pci-expander-bus.xml | 167 +++++++++ .../qemuxml2argv-pcie-expander-bus-bad-machine.xml | 36 ++ .../qemuxml2argv-pcie-expander-bus.args | 123 +++++++ .../qemuxml2argv-pcie-expander-bus.xml | 247 +++++++++++++ .../qemuxml2argv-pcie-root-port.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 2 +- .../qemuxml2argv-pcie-switch-downstream-port.args | 2 +- .../qemuxml2argv-pcie-switch-upstream-port.args | 2 +- .../qemuxml2argv-pcihole64-q35.args | 2 +- .../qemuxml2argv-q35-pm-disable-fallback.args | 2 +- .../qemuxml2argv-q35-pm-disable.args | 2 +- .../qemuxml2argv-q35-usb2-multi.args | 2 +- .../qemuxml2argv-q35-usb2-reorder.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +- .../qemuxml2argv-usb-controller-default-q35.args | 2 +- .../qemuxml2argv-usb-controller-explicit-q35.args | 2 +- tests/qemuxml2argvtest.c | 25 ++ .../qemuxml2xmlout-aarch64-virtio-pci-default.xml | 2 +- ...2xmlout-aarch64-virtio-pci-manual-addresses.xml | 2 +- .../qemuxml2xmlout-pci-expander-bus.xml | 207 +++++++++++ .../qemuxml2xmlout-pcie-expander-bus.xml | 384 +++++++++++++++++++++ .../qemuxml2xmlout-pcie-root-port.xml | 2 +- .../qemuxml2xmlout-pcie-root.xml | 2 +- .../qemuxml2xmlout-pcie-switch-downstream-port.xml | 2 +- .../qemuxml2xmlout-pcie-switch-upstream-port.xml | 2 +- .../qemuxml2xmlout-pcihole64-q35.xml | 2 +- .../qemuxml2xmlout-q35-usb2-multi.xml | 2 +- .../qemuxml2xmlout-q35-usb2-reorder.xml | 2 +- .../qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml | 2 +- tests/qemuxml2xmltest.c | 10 + 57 files changed, 2296 insertions(+), 261 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml -- 2.5.5

The pcie-switch-downstream-port and pcie-root-port controllers have only a single slot, numbered 0, and the greate majority of all guest PCI devices are plugged into function 0 of whatever slot they're using. The parser makes these optional, setting them to 0 when not specified, and it's logical for the schema to also make them optional. --- docs/schemas/basictypes.rng | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index a83063a..084d403 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -75,12 +75,16 @@ <attribute name="bus"> <ref name="pciBus"/> </attribute> - <attribute name="slot"> - <ref name="pciSlot"/> - </attribute> - <attribute name="function"> - <ref name="pciFunc"/> - </attribute> + <optional> + <attribute name="slot"> + <ref name="pciSlot"/> + </attribute> + </optional> + <optional> + <attribute name="function"> + <ref name="pciFunc"/> + </attribute> + </optional> <optional> <attribute name="multifunction"> <ref name="virOnOff"/> -- 2.5.5

On 24.03.2016 20:25, Laine Stump wrote:
The pcie-switch-downstream-port and pcie-root-port controllers have only a single slot, numbered 0, and the greate majority of all guest
s/greate/great/
PCI devices are plugged into function 0 of whatever slot they're using. The parser makes these optional, setting them to 0 when not specified, and it's logical for the schema to also make them optional. --- docs/schemas/basictypes.rng | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index a83063a..084d403 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -75,12 +75,16 @@ <attribute name="bus"> <ref name="pciBus"/> </attribute> - <attribute name="slot"> - <ref name="pciSlot"/> - </attribute> - <attribute name="function"> - <ref name="pciFunc"/> - </attribute> + <optional> + <attribute name="slot"> + <ref name="pciSlot"/> + </attribute> + </optional> + <optional> + <attribute name="function"> + <ref name="pciFunc"/> + </attribute> + </optional> <optional> <attribute name="multifunction"> <ref name="virOnOff"/>
Well, looking into our PCI address parser, all of the attributes are optional, even domain and bus. None of my guests have non-zero domain actually ;-). Your call whether to loosen schema even more or stick with your approach. ACK Michal

On 03/30/2016 05:05 AM, Michal Privoznik wrote:
On 24.03.2016 20:25, Laine Stump wrote:
The pcie-switch-downstream-port and pcie-root-port controllers have only a single slot, numbered 0, and the greate majority of all guest s/greate/great/
PCI devices are plugged into function 0 of whatever slot they're using. The parser makes these optional, setting them to 0 when not specified, and it's logical for the schema to also make them optional. --- docs/schemas/basictypes.rng | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index a83063a..084d403 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -75,12 +75,16 @@ <attribute name="bus"> <ref name="pciBus"/> </attribute> - <attribute name="slot"> - <ref name="pciSlot"/> - </attribute> - <attribute name="function"> - <ref name="pciFunc"/> - </attribute> + <optional> + <attribute name="slot"> + <ref name="pciSlot"/> + </attribute> + </optional> + <optional> + <attribute name="function"> + <ref name="pciFunc"/> + </attribute> + </optional> <optional> <attribute name="multifunction"> <ref name="virOnOff"/>
Well, looking into our PCI address parser, all of the attributes are optional, even domain and bus.
Right. It's only virsh's validation against the schema that causes problems.
None of my guests have non-zero domain actually ;-).
Yep. I'm not sure why we waste so much imaginary ink formatting all those "domain='0x0000'" attributes, especially since there isn't even a way to specify a non-0 domain for the guest-side PCI address of a device. The only thing we (or qemu) support it for is the *host* side PCI address of devices that are being assigned with vfio or legacy KVM device assignment. Of course it's always possible that it may be supported in the future, but even if that happens, "0" seems like a pretty safe default that could be omitted from the stored/displayed config.
Your call whether to loosen schema even more or stick with your approach.
I had done it that way initially (made bus optional as well), then backed off but I don't remember why now. I guess because I couldn't think of a valid reason why someone would need to specify slot or function but leave out bus (and slot 0 of bus 0 is reserved, so can't be used. And Cole used a different method of allowing plain "<address type='pci'/>" in his series to force PCI addresses for devices that may otherwise use virtio-mmio (although he may want to do it by simply making bus optional as you suggest).

nwfilter.rng defines uint16range and uint32range, but in a different manner (it also allows a variable name as the value, rather than just a decimal or hex number). I wanted to add uint16range to basictypes.rng, but my desired definition was parallel to those for uint8range and uint24range which are defined in basictypes.rng - they *don't* allow a variable name for the value. The simplest path to make everyone happy is to make the "plain" versions in basictypes.rng have simpler names - "uint8", "uint16", and "uint24". This patch renames uint8range and uint24range to uint8 and uint24, while the next patch will add uint16. --- docs/schemas/basictypes.rng | 4 ++-- docs/schemas/domaincommon.rng | 6 +++--- docs/schemas/networkcommon.rng | 12 ++++++------ docs/schemas/nwfilter.rng | 16 ++++++++-------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index 084d403..cfbf40d 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -32,7 +32,7 @@ </data> </define> - <define name="uint8range"> + <define name="uint8"> <choice> <data type="string"> <param name="pattern">0x[0-9a-fA-F]{1,2}</param> @@ -43,7 +43,7 @@ </data> </choice> </define> - <define name="uint24range"> + <define name="uint24"> <choice> <data type="string"> <param name="pattern">0x[0-9a-fA-F]{1,6}</param> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index da6de40..236a2ba 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1768,17 +1768,17 @@ <element name="target"> <optional> <attribute name='chassisNr'> - <ref name='uint8range'/> + <ref name='uint8'/> </attribute> </optional> <optional> <attribute name="chassis"> - <ref name='uint8range'/> + <ref name='uint8'/> </attribute> </optional> <optional> <attribute name="port"> - <ref name='uint8range'/> + <ref name='uint8'/> </attribute> </optional> <empty/> diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng index 09691dc..fb69f7c 100644 --- a/docs/schemas/networkcommon.rng +++ b/docs/schemas/networkcommon.rng @@ -19,17 +19,17 @@ <element name="parameters"> <optional> <attribute name="managerid"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> <attribute name="typeid"> - <ref name="uint24range"/> + <ref name="uint24"/> </attribute> </optional> <optional> <attribute name="typeidversion"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> @@ -97,17 +97,17 @@ <element name="parameters"> <optional> <attribute name="managerid"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> <attribute name="typeid"> - <ref name="uint24range"/> + <ref name="uint24"/> </attribute> </optional> <optional> <attribute name="typeidversion"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> diff --git a/docs/schemas/nwfilter.rng b/docs/schemas/nwfilter.rng index 9df39c0..dbe6af7 100644 --- a/docs/schemas/nwfilter.rng +++ b/docs/schemas/nwfilter.rng @@ -578,12 +578,12 @@ <interleave> <optional> <attribute name="type"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> <attribute name="code"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> </interleave> @@ -593,22 +593,22 @@ <interleave> <optional> <attribute name="type"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> <attribute name="typeend"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> <attribute name="code"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> <attribute name="codeend"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> </interleave> @@ -642,12 +642,12 @@ <define name="stp-attributes"> <optional> <attribute name="type"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> <attribute name="flags"> - <ref name="uint8range"/> + <ref name="uint8"/> </attribute> </optional> <optional> -- 2.5.5

This is a number between 0 and 65535 (or 0x0000 - 0xffff if specified in hexadecimal). --- docs/schemas/basictypes.rng | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index cfbf40d..64babaf 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -43,6 +43,17 @@ </data> </choice> </define> + <define name="uint16"> + <choice> + <data type="string"> + <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param> + </data> + <data type='int'> + <param name="minInclusive">0</param> + <param name="maxInclusive">65535</param> + </data> + </choice> + </define> <define name="uint24"> <choice> <data type="string"> -- 2.5.5

This is especially useful for "bus", since the bus of a device's pci address is matched to the "index" of a controller to determine which bus it will be connected to, and "index" is always specified in decimal - being able to specify both in decimal at least makes it easier to assure a device is being assigned to the correct bus when it is added. For the other attributes, it is just a convenience. (MB: the parser already allows for any of these attributes to be given in decimal, and there are even examples floating around on the internet that give them in decimal rather than hex (written in the days before virsh did schema validation on all XML). This only updates the schema to match the parser.) --- docs/schemas/basictypes.rng | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index 64babaf..e2936d8 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -282,24 +282,32 @@ </define> <define name="pciDomain"> - <data type="string"> - <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param> - </data> + <ref name="uint16"/> </define> <define name="pciBus"> - <data type="string"> - <param name="pattern">(0x)?[0-9a-fA-F]{1,2}</param> - </data> + <ref name="uint8"/> </define> <define name="pciSlot"> - <data type="string"> - <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param> - </data> + <choice> + <data type="string"> + <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">31</param> + </data> + </choice> </define> <define name="pciFunc"> - <data type="string"> - <param name="pattern">(0x)?[0-7]</param> - </data> + <choice> + <data type="string"> + <param name="pattern">(0x)?[0-7]</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">7</param> + </data> + </choice> </define> <define name='wwn'> -- 2.5.5

On 24.03.2016 20:25, Laine Stump wrote:
This is especially useful for "bus", since the bus of a device's pci address is matched to the "index" of a controller to determine which bus it will be connected to, and "index" is always specified in decimal - being able to specify both in decimal at least makes it easier to assure a device is being assigned to the correct bus when it is added. For the other attributes, it is just a convenience.
(MB: the parser already allows for any of these attributes to be given in decimal, and there are even examples floating around on the internet that give them in decimal rather than hex (written in the days before virsh did schema validation on all XML). This only updates the schema to match the parser.) --- docs/schemas/basictypes.rng | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index 64babaf..e2936d8 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -282,24 +282,32 @@ </define>
<define name="pciDomain"> - <data type="string"> - <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param> - </data> + <ref name="uint16"/> </define> <define name="pciBus"> - <data type="string"> - <param name="pattern">(0x)?[0-9a-fA-F]{1,2}</param> - </data> + <ref name="uint8"/> </define> <define name="pciSlot"> - <data type="string"> - <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param> - </data> + <choice> + <data type="string"> + <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">31</param> + </data> + </choice> </define> <define name="pciFunc"> - <data type="string"> - <param name="pattern">(0x)?[0-7]</param> - </data> + <choice> + <data type="string"> + <param name="pattern">(0x)?[0-7]</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">7</param> + </data> + </choice> </define>
<define name='wwn'>
Okay, but we can never format them in decimal as '12' in decimal is something different than in hexadecimal. Michal

On 03/30/2016 05:05 AM, Michal Privoznik wrote:
On 24.03.2016 20:25, Laine Stump wrote:
This is especially useful for "bus", since the bus of a device's pci address is matched to the "index" of a controller to determine which bus it will be connected to, and "index" is always specified in decimal - being able to specify both in decimal at least makes it easier to assure a device is being assigned to the correct bus when it is added. For the other attributes, it is just a convenience.
(MB: the parser already allows for any of these attributes to be given in decimal, and there are even examples floating around on the internet that give them in decimal rather than hex (written in the days before virsh did schema validation on all XML). This only updates the schema to match the parser.) --- docs/schemas/basictypes.rng | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index 64babaf..e2936d8 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -282,24 +282,32 @@ </define>
<define name="pciDomain"> - <data type="string"> - <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param> - </data> + <ref name="uint16"/> </define> <define name="pciBus"> - <data type="string"> - <param name="pattern">(0x)?[0-9a-fA-F]{1,2}</param> - </data> + <ref name="uint8"/> </define> <define name="pciSlot"> - <data type="string"> - <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param> - </data> + <choice> + <data type="string"> + <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">31</param> + </data> + </choice> </define> <define name="pciFunc"> - <data type="string"> - <param name="pattern">(0x)?[0-7]</param> - </data> + <choice> + <data type="string"> + <param name="pattern">(0x)?[0-7]</param> + </data> + <data type="int"> + <param name="minInclusive">0</param> + <param name="maxInclusive">7</param> + </data> + </choice> </define>
<define name='wwn'>
Okay, but we can never format them in decimal as '12' in decimal is something different than in hexadecimal.
Correct. I think we're stuck with formatting the way it is (actually, since it's so common for PCI addresses to be in hex, if we were going to change anything it would be to format the index in hex, but even that would probably confuse some people).

Every other maxSlot was either set to 0 or to VIR_PCI_ADDRESS_SLOT_LAST, but this one was for some reason set to the literal value 31 (which is the same as VIR_PCI_ADDRESS_SLOT_LAST). This makes them all consistent. --- src/conf/domain_addr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 9883c4f..342c7af 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -212,7 +212,7 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, /* 31 slots, can only accept pcie-switch-port, no hotplug */ bus->flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH; bus->minSlot = 0; - bus->maxSlot = 31; + bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; default: virReportError(VIR_ERR_INTERNAL_ERROR, -- 2.5.5

When support for dmi-to-pci-bridge was added, it was assumed that, just as with the pci-root bus, slot 0 was reserved. This is not the case - it can be used to connect a device just like any other slot, so remove the restriction and update the test cases that auto-assign an address on a dmi-to-pci-bridge. --- src/conf/domain_addr.c | 4 ++-- tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args | 2 +- .../qemuxml2argv-aarch64-virtio-pci-manual-addresses.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-downstream-port.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable-fallback.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-multi.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-reorder.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-usb-controller-default-q35.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-usb-controller-explicit-q35.args | 2 +- .../qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml | 2 +- .../qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml | 2 +- .../qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-downstream-port.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-pcihole64-q35.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-multi.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-reorder.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml | 2 +- 27 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 342c7af..722bf8e 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -190,10 +190,10 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - /* slots 1 - 31, standard PCI slots, + /* slots 0 - 31, standard PCI slots, * but *not* hot-pluggable */ bus->flags = VIR_PCI_CONNECT_TYPE_PCI; - bus->minSlot = 1; + bus->minSlot = 0; bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args index a7a996e..9aaed4b 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-default.args @@ -22,7 +22,7 @@ QEMU_AUDIO_DRV=none \ -append 'earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait' \ -dtb /aarch64.dtb \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1 \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -device virtio-serial-device,id=virtio-serial0 \ -usb \ -drive file=/aarch64.raw,format=raw,if=none,id=drive-virtio-disk0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args index e3e962b..2dfcd1e 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-virtio-pci-manual-addresses.args @@ -22,7 +22,7 @@ QEMU_AUDIO_DRV=none \ -append 'earlyprintk console=ttyAMA0,115200n8 rw root=/dev/vda rootwait' \ -dtb /aarch64.dtb \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1 \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -device virtio-scsi-pci,id=scsi0,bus=pcie.0,addr=0x3 \ -usb \ -drive file=/aarch64.raw,format=raw,if=none,id=drive-scsi0-0-0-0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args index 7fd84f1..8031ebc 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args @@ -17,7 +17,7 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ -device ioh3420,port=0x1a,chassis=40,id=pci.4,bus=pcie.0,addr=0x3 \ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-sata0-0-0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args index 230d13c..d6b139f 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args @@ -17,4 +17,4 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-downstream-port.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-downstream-port.args index 9d55621..d94dc23 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-downstream-port.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-downstream-port.args @@ -17,7 +17,7 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ -device x3130-upstream,id=pci.4,bus=pci.3,addr=0x0 \ -device xio3130-downstream,port=0x0,chassis=5,id=pci.5,bus=pci.4,addr=0x0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args index d8aa44b..ba2bba7 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args @@ -17,7 +17,7 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ -device ioh3420,port=0x18,chassis=4,id=pci.4,bus=pcie.0,addr=0x3 \ -device x3130-upstream,id=pci.5,bus=pci.3,addr=0x0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args index b6ccda2..7d3a070 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args @@ -18,7 +18,7 @@ QEMU_AUDIO_DRV=none \ -boot c \ -global q35-pcihost.pci-hole64-size=1048576K \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-sata0-0-0 \ -device ide-drive,bus=ide.0,drive=drive-sata0-0-0,id=sata0-0-0 \ -vga qxl \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable-fallback.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable-fallback.args index e439b49..c7eafc5 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable-fallback.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable-fallback.args @@ -19,5 +19,5 @@ QEMU_AUDIO_DRV=none \ -global PIIX4_PM.disable_s4=1 \ -boot n \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable.args index 73cf967..ec90851 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-pm-disable.args @@ -19,5 +19,5 @@ QEMU_AUDIO_DRV=none \ -global ICH9-LPC.disable_s4=1 \ -boot n \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ -device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-multi.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-multi.args index 26c4d3c..9da845b 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-multi.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-multi.args @@ -17,7 +17,7 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x0 \ -device ich9-usb-ehci1,id=usb,bus=pcie.0,addr=0x1d.0x7 \ -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pcie.0,multifunction=on,\ addr=0x1d \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-reorder.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-reorder.args index ba0e7fa..bd0cd55 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-reorder.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2-reorder.args @@ -17,7 +17,7 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x0 \ -device ich9-usb-ehci1,id=usb,bus=pcie.0,addr=0x1d.0x7 \ -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pcie.0,multifunction=on,\ addr=0x1d \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args index 98287e6..5cca714 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args @@ -17,7 +17,7 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x0 \ -device ich9-usb-ehci1,id=usb,bus=pcie.0,addr=0x1d.0x7 \ -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pcie.0,multifunction=on,\ addr=0x1d \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args index 98287e6..5cca714 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.args @@ -17,7 +17,7 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ --device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x0 \ -device ich9-usb-ehci1,id=usb,bus=pcie.0,addr=0x1d.0x7 \ -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pcie.0,multifunction=on,\ addr=0x1d \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-default-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-default-q35.args index 8cfa371..7c33da2 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-default-q35.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-default-q35.args @@ -16,6 +16,6 @@ QEMU_AUDIO_DRV=none \ -monitor unix:/tmp/lib/domain--1-q35-test/monitor.sock,server,nowait \ -no-acpi \ -boot c \ --device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x0 \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ -device piix3-usb-uhci,id=usb,bus=pcie.0,addr=0x1 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-explicit-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-explicit-q35.args index 020f159..d24f9cd 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-explicit-q35.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-controller-explicit-q35.args @@ -16,6 +16,6 @@ QEMU_AUDIO_DRV=none \ -monitor unix:/tmp/lib/domain--1-q35-test/monitor.sock,server,nowait \ -no-acpi \ -boot c \ --device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x1 \ +-device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x0 \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ -device nec-usb-xhci,id=usb,bus=pcie.0,addr=0x1 diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml index 415d041..be2e113 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-default.xml @@ -40,7 +40,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='virtio-serial' index='0'> <address type='virtio-mmio'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml index 0ee40f5..0d69169 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-virtio-pci-manual-addresses.xml @@ -43,7 +43,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <interface type='user'> <mac address='52:54:00:09:a4:37'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml index ea61bcf..a4ff820 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml @@ -27,7 +27,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='pci' index='3' model='pcie-root-port'> <model name='ioh3420'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml index 013cbc4..7f2e21a 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml @@ -25,7 +25,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-downstream-port.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-downstream-port.xml index 22cfeaa..beb6ca8 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-downstream-port.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-downstream-port.xml @@ -27,7 +27,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='pci' index='3' model='pcie-root-port'> <model name='ioh3420'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml index 813ba97..53e10d0 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml @@ -27,7 +27,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='pci' index='3' model='pcie-root-port'> <model name='ioh3420'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcihole64-q35.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcihole64-q35.xml index 7e9a366..dad7d1a 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcihole64-q35.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcihole64-q35.xml @@ -29,7 +29,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='2'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='sata' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-multi.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-multi.xml index 35e8fed..06c0699 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-multi.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-multi.xml @@ -27,7 +27,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='56'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='usb' index='0' model='ich9-ehci1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x7'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-reorder.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-reorder.xml index 914c7f8..1007095 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-reorder.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2-reorder.xml @@ -27,7 +27,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='56'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='usb' index='0' model='ich9-ehci1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x7'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml index 3fd2c0e..58c7fab 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml @@ -27,7 +27,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='56'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='usb' index='0' model='ich9-ehci1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x7'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml index 3fd2c0e..58c7fab 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml @@ -27,7 +27,7 @@ <controller type='pci' index='2' model='pci-bridge'> <model name='pci-bridge'/> <target chassisNr='56'/> - <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> <controller type='usb' index='0' model='ich9-ehci1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x7'/> -- 2.5.5

The flags used to determine which devices could be plugged into which controllers were quite confusing, as they tried to create classes of connections, then put particular devices into possibly multiple classes, while sometimes setting multiple flags for the controllers themselves. The attempt to have a single flag indicate, e.g. that a root-port or a switch-downstream-port could connect was not only confusing, it was leading to a situation where it would be impossible to specify exactly the right combinations for a new controller. The solution is for the VIR_PCI_CONNECT_TYPE_* flags to have a 1:1 correspondence with each type of PCI controller, plus a flag for a PCI endpoint device and another for a PCIe endpoint device (the only exception to this is that pci-bridge and pcie-expander-bus controllers have their upstream connection classified as VIR_PCI_CONNECT_TYPE_PCI_DEVICE since they can be plugged into *exactly* the same ports as any endpoint device). Each device then has a single flag for connect type (plus the HOTPLUG flag if that device can e hotplugged), and each controller sets the CONNECT bits for all controllers that can be plugged into it, as well as for either type of endpoint device that can be plugged in (and the HOTPLUG flag if it can accept hotplugged devices). With this change, it is *slightly* easier to understand the matching of connections (as long as you remember that the flag for a device/upstream-facing connection of a controller is the same as that device's type, while the flags for a controller's downstream connections is the OR of all device types that can be plugged into that controller). More importantly, it will be possible to correctly specify what can be plugged into a pcie-switch-expander-bus, when support for it is added. --- src/bhyve/bhyve_device.c | 10 +-- src/conf/domain_addr.c | 42 ++++++------ src/conf/domain_addr.h | 64 +++++++++---------- src/qemu/qemu_domain_address.c | 141 +++++++++++++++++++++++------------------ 4 files changed, 136 insertions(+), 121 deletions(-) diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c index b458275..fe1c567 100644 --- a/src/bhyve/bhyve_device.c +++ b/src/bhyve/bhyve_device.c @@ -53,7 +53,7 @@ bhyveCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, } } - if (virDomainPCIAddressReserveSlot(addrs, addr, VIR_PCI_CONNECT_TYPE_PCI) < 0) + if (virDomainPCIAddressReserveSlot(addrs, addr, VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) goto cleanup; ret = 0; @@ -94,7 +94,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def, memset(&lpc_addr, 0, sizeof(lpc_addr)); lpc_addr.slot = 0x1; - if (virDomainPCIAddressReserveSlot(addrs, &lpc_addr, VIR_PCI_CONNECT_TYPE_PCI) < 0) + if (virDomainPCIAddressReserveSlot(addrs, &lpc_addr, VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) goto error; for (i = 0; i < def->nnets; i++) { @@ -102,7 +102,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def, continue; if (virDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info, - VIR_PCI_CONNECT_TYPE_PCI) < 0) + VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) goto error; } @@ -112,7 +112,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def, continue; if (virDomainPCIAddressReserveNextSlot(addrs, &def->disks[i]->info, - VIR_PCI_CONNECT_TYPE_PCI) < 0) + VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) goto error; } @@ -125,7 +125,7 @@ bhyveAssignDevicePCISlots(virDomainDefPtr def, if (virDomainPCIAddressReserveNextSlot(addrs, &def->controllers[i]->info, - VIR_PCI_CONNECT_TYPE_PCI) < 0) + VIR_PCI_CONNECT_TYPE_PCI_DEVICE) < 0) goto error; } diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 722bf8e..4408c4a 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1,7 +1,7 @@ /* * domain_addr.c: helper APIs for managing domain device addresses * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2016 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -64,13 +64,13 @@ virDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr, */ if (!(devFlags & busFlags & VIR_PCI_CONNECT_TYPES_MASK)) { if (reportError) { - if (devFlags & VIR_PCI_CONNECT_TYPE_PCI) { + if (devFlags & VIR_PCI_CONNECT_TYPE_PCI_DEVICE) { virReportError(errType, _("PCI bus is not compatible with the device " "at %s. Device requires a standard PCI slot, " "which is not provided by bus %.4x:%.2x"), addrStr, addr->domain, addr->bus); - } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCIE) { + } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCIE_DEVICE) { virReportError(errType, _("PCI bus is not compatible with the device " "at %s. Device requires a PCI Express slot, " @@ -172,45 +172,51 @@ int virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, virDomainControllerModelPCI model) { + /* set flags for what can be connected *downstream* from each + * bus. + */ switch (model) { case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE | - VIR_PCI_CONNECT_TYPE_PCI); + VIR_PCI_CONNECT_TYPE_PCI_DEVICE); bus->minSlot = 1; bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: - /* slots 1 - 31, no hotplug, PCIe only unless the address was - * specified in user config *and* the particular device being - * attached also allows it. + /* slots 1 - 31, no hotplug, PCIe endpoint device or + * pcie-root-port only, unless the address was specified in + * user config *and* the particular device being attached also + * allows it. */ - bus->flags = VIR_PCI_CONNECT_TYPE_PCIE | VIR_PCI_CONNECT_TYPE_PCIE_ROOT; + bus->flags = (VIR_PCI_CONNECT_TYPE_PCIE_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT); bus->minSlot = 1; bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: /* slots 0 - 31, standard PCI slots, * but *not* hot-pluggable */ - bus->flags = VIR_PCI_CONNECT_TYPE_PCI; + bus->flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; bus->minSlot = 0; bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - /* provides one slot which is pcie, can be used by devices - * that must connect to some type of "pcie-*-port", and - * is hotpluggable + /* provides one slot which is pcie, can be used by endpoint + * devices and pcie-switch-upstream-ports, and is hotpluggable */ - bus->flags = VIR_PCI_CONNECT_TYPE_PCIE - | VIR_PCI_CONNECT_TYPE_PCIE_PORT + bus->flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT | VIR_PCI_CONNECT_HOTPLUGGABLE; bus->minSlot = 0; bus->maxSlot = 0; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - /* 31 slots, can only accept pcie-switch-port, no hotplug */ - bus->flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH; + /* 32 slots, can only accept pcie-switch-downstrean-ports, + * no hotplug + */ + bus->flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; bus->minSlot = 0; bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; @@ -249,7 +255,7 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, return 0; /* auto-grow only works when we're adding plain PCI devices */ - if (!(flags & VIR_PCI_CONNECT_TYPE_PCI)) { + if (!(flags & VIR_PCI_CONNECT_TYPE_PCI_DEVICE)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot automatically add a new PCI bus for a " "device requiring a slot other than standard PCI.")); @@ -388,7 +394,7 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs, * only supported for standard PCI devices, so we can safely use * the setting below */ virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE | - VIR_PCI_CONNECT_TYPE_PCI); + VIR_PCI_CONNECT_TYPE_PCI_DEVICE); if (!(addrStr = virDomainPCIAddressAsString(&dev->addr.pci))) goto cleanup; diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 208635c..b5cb0ee 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -1,7 +1,7 @@ /* * domain_addr.h: helper APIs for managing domain device addresses * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2016 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -30,32 +30,42 @@ # define VIR_PCI_ADDRESS_FUNCTION_LAST 7 typedef enum { - VIR_PCI_CONNECT_HOTPLUGGABLE = 1 << 0, - /* This bus supports hot-plug */ - VIR_PCI_CONNECT_SINGLESLOT = 1 << 1, - /* This "bus" has only a single downstream slot/port */ - - VIR_PCI_CONNECT_TYPE_PCI = 1 << 2, - /* PCI devices can connect to this bus */ - VIR_PCI_CONNECT_TYPE_PCIE = 1 << 3, - /* PCI Express devices can connect to this bus */ - VIR_PCI_CONNECT_TYPE_PCIE_ROOT = 1 << 4, - /* for devices that can only connect to pcie-root (i.e. root-port) */ - VIR_PCI_CONNECT_TYPE_PCIE_PORT = 1 << 5, - /* devices that can only connect to a pcie-root-port - * or pcie-downstream-switch-port + VIR_PCI_CONNECT_HOTPLUGGABLE = 1 << 0, /* is hotplug needed/supported */ + + /* kinds of devices as a bitmap so they can be combined (some PCI + * controllers permit connecting multiple types of devices) */ - VIR_PCI_CONNECT_TYPE_PCIE_SWITCH = 1 << 6, - /* devices that can only connect to a pcie-switch */ + VIR_PCI_CONNECT_TYPE_PCI_DEVICE = 1 << 1, + VIR_PCI_CONNECT_TYPE_PCIE_DEVICE = 1 << 2, + VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT = 1 << 3, + VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT = 1 << 4, + VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT = 1 << 5, } virDomainPCIConnectFlags; +/* a combination of all bits that describe the type of connections + * allowed, e.g. PCI, PCIe, switch + */ +# define VIR_PCI_CONNECT_TYPES_MASK \ + (VIR_PCI_CONNECT_TYPE_PCI_DEVICE | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE | \ + VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT | \ + VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT | \ + VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT) + +/* combination of all bits that could be used to connect a normal + * endpoint device (i.e. excluding the connection possible between an + * upstream and downstream switch port, or a PCIe root port and a PCIe + * port) + */ +# define VIR_PCI_CONNECT_TYPES_ENDPOINT \ + (VIR_PCI_CONNECT_TYPE_PCI_DEVICE | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE) + typedef struct { virDomainControllerModelPCI model; - /* flags an min/max can be computed from model, but + /* flags and min/max can be computed from model, but * having them ready makes life easier. */ virDomainPCIConnectFlags flags; - size_t minSlot, maxSlot; /* usually 0,0 or 1,31 */ + size_t minSlot, maxSlot; /* usually 0,0 or 0,31, or 1,31 */ /* Each bit in a slot represents one function on that slot. If the * bit is set, that function is in use by a device. */ @@ -74,22 +84,6 @@ struct _virDomainPCIAddressSet { typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet; typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr; -/* a combination of all bits that describe the type of connections - * allowed, e.g. PCI, PCIe, switch - */ -# define VIR_PCI_CONNECT_TYPES_MASK \ - (VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE | \ - VIR_PCI_CONNECT_TYPE_PCIE_ROOT | VIR_PCI_CONNECT_TYPE_PCIE_PORT | \ - VIR_PCI_CONNECT_TYPE_PCIE_SWITCH) - -/* combination of all bits that could be used to connect a normal - * endpoint device (i.e. excluding the connection possible between an - * upstream and downstream switch port, or a PCIe root port and a PCIe - * port) - */ -# define VIR_PCI_CONNECT_TYPES_ENDPOINT \ - (VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE) - char *virDomainPCIAddressAsString(virDevicePCIAddressPtr addr) ATTRIBUTE_NONNULL(1); diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 4f31484..c6e694e 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -427,7 +427,7 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, bool entireSlot; /* flags may be changed from default below */ virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE | - VIR_PCI_CONNECT_TYPE_PCI); + VIR_PCI_CONNECT_TYPE_PCI_DEVICE); if ((info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) || ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) && @@ -451,31 +451,30 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, /* pci-bridge needs a PCI slot, but it isn't * hot-pluggable, so it doesn't need a hot-pluggable slot. */ - flags = VIR_PCI_CONNECT_TYPE_PCI; + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: /* pci-bridge needs a PCIe slot, but it isn't * hot-pluggable, so it doesn't need a hot-pluggable slot. */ - flags = VIR_PCI_CONNECT_TYPE_PCIE; + flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - /* pcie-root-port can only connect to pcie-root, isn't - * hot-pluggable + /* pcie-root-port isn't hot-pluggable, and + * is unique in what it can connect to, so + * it has its own flag. */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT; + flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - /* pcie-switch can only connect to a true - * pcie bus, and can't be hot-plugged. + /* pcie-switch-upstream-port is also unique, and + * not hot-pluggable... */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_PORT; + flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - /* pcie-switch-downstream-port can only connect to a - * pcie-switch-upstream-port, and can't be hot-plugged. - */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH; + /* ... same for pcie-switch-downstream-port */ + flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; break; default: break; @@ -486,34 +485,36 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, /* SATA controllers aren't hot-plugged, and can be put in * either a PCI or PCIe slot */ - flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE; + flags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); break; case VIR_DOMAIN_CONTROLLER_TYPE_USB: - /* allow UHCI and EHCI controllers to be manually placed on - * the PCIe bus (but don't put them there automatically) - */ - switch (device->data.controller->model) { - case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI: - case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1: - case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1: - case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2: - case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3: - case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI: - flags = VIR_PCI_CONNECT_TYPE_PCI; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI: - /* should this be PCIE-only? Or do we need to allow PCI - * for backward compatibility? - */ - flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI: - case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI: - case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI: - /* Allow these for PCI only */ - break; - } + /* allow UHCI and EHCI controllers to be manually placed on + * the PCIe bus (but don't put them there automatically) + */ + switch (device->data.controller->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI: + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI: + /* should this be PCIE-only? Or do we need to allow PCI + * for backward compatibility? + */ + flags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); + break; + case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI: + /* Allow these for PCI only */ + break; + } } break; @@ -521,7 +522,7 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, switch (device->data.sound->model) { case VIR_DOMAIN_SOUND_MODEL_ICH6: case VIR_DOMAIN_SOUND_MODEL_ICH9: - flags = VIR_PCI_CONNECT_TYPE_PCI; + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; break; } break; @@ -530,7 +531,8 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, /* video cards aren't hot-plugged, and can be put in either a * PCI or PCIe slot */ - flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE; + flags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); break; } @@ -562,7 +564,7 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, * commandline, but that don't really care if a PCI bus * actually exists. */ if (addrs->nbuses > 0 && - !(addrs->buses[0].flags & VIR_PCI_CONNECT_TYPE_PCI)) { + !(addrs->buses[0].flags & VIR_PCI_CONNECT_TYPE_PCI_DEVICE)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Bus 0 must be PCI for integrated PIIX3 " "USB or IDE controllers")); @@ -653,7 +655,8 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, virDevicePCIAddress tmp_addr; bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); char *addrStr = NULL; - virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI; + virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE + | VIR_PCI_CONNECT_TYPE_PCI_DEVICE); /* Verify that first IDE and USB controllers (if any) is on the PIIX3, fn 1 */ for (i = 0; i < def->ncontrollers; i++) { @@ -786,7 +789,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, virDevicePCIAddress tmp_addr; bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); char *addrStr = NULL; - virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCIE; + virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; for (i = 0; i < def->ncontrollers; i++) { switch (def->controllers[i]->type) { @@ -1049,7 +1052,7 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, virDomainPCIAddressSetPtr addrs) { size_t i, j; - virDomainPCIConnectFlags flags; + virDomainPCIConnectFlags flags = 0; /* initialize to quiet gcc warning */ virDevicePCIAddress tmp_addr; /* PCI controllers */ @@ -1057,41 +1060,48 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) continue; - switch (def->controllers[i]->model) { + + /* convert the type of controller into a "CONNECT_TYPE" + * flag to use when searching for the proper + * controller/bus to connect it to on the upstream side. + */ + switch ((virDomainControllerModelPCI)def->controllers[i]->model) { case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: /* pci-root and pcie-root are implicit in the machine, - * and needs no address */ + * and need no address */ continue; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: /* pci-bridge doesn't require hot-plug * (although it does provide hot-plug in its slots) */ - flags = VIR_PCI_CONNECT_TYPE_PCI; + flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - /* dmi-to-pci-bridge requires a non-hotplug PCIe - * slot + /* dmi-to-pci-bridge is treated like a + * non-hotplug-capable PCIe device (e.g. it can be + * plugged directly into pcie-root) */ - flags = VIR_PCI_CONNECT_TYPE_PCIE; + flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - /* pcie-root-port can only plug into pcie-root */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT; + flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - /* pcie-switch really does need a real PCIe - * port, but it doesn't need to be pcie-root - */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_PORT; + flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - /* pcie-switch-port can only plug into pcie-switch */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH; - break; - default: - flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI; + flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; break; + + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + /* if this happens, there is an error in the code. A + * PCI controller should always have a proper model + * set + */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("PCI controller model icorrectly set to 'last'")); + goto error; } if (virDomainPCIAddressReserveNextSlot(addrs, &def->controllers[i]->info, @@ -1100,7 +1110,12 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, } } - flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI; + /* all other devices that plug into a PCI slot are treated as a + * PCI endpoint devices that require a hotplug-capable slot + * (except for some special cases which have specific handling + * below) + */ + flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI_DEVICE; for (i = 0; i < def->nfss; i++) { if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) @@ -1414,7 +1429,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, int rv; bool buses_reserved = true; - virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI; + virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; for (i = 0; i < def->ncontrollers; i++) { if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { -- 2.5.5

There are two places in qemu_domain_address.c where we have a switch statement to convert PCI controller models (VIR_DOMAIN_CONTROLLER_MODEL_PCI*) into the connection type flag that is matched when looking for an upstream connection for that model of controller (VIR_PCI_CONNECT_TYPE_*). This patch makes a utility function in conf/domain_addr.c to do that, so that when a new PCI controller is added, we only need to add the new model-->connect-type in a single place. --- src/conf/domain_addr.c | 47 +++++++++++++++++++++++++ src/conf/domain_addr.h | 4 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 80 +++++------------------------------------- 4 files changed, 61 insertions(+), 71 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 4408c4a..1bf2c9a 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -32,6 +32,53 @@ VIR_LOG_INIT("conf.domain_addr"); +int +virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model, + virDomainPCIConnectFlags *connectType) +{ + /* given a VIR_DOMAIN_CONTROLLER_MODEL_PCI*, set connectType to + * the equivalent VIR_PCI_CONNECT_TYPE_*. return 0 on success, -1 + * if the model wasn't recognized. + */ + switch (model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + /* pci-root and pcie-root are implicit in the machine, + * and have no upstream connection + */ + *connectType = 0; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + /* pci-bridge is treated like a standard PCI endpoint device, */ + *connectType = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + /* dmi-to-pci-bridge is treated like a PCIe device + * (e.g. it can be plugged directly into pcie-root) + */ + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + /* if this happens, there is an error in the code. A + * PCI controller should always have a proper model + * set + */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("PCI controller model incorrectly set to 'last'")); + return -1; + } + return 0; +} + bool virDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr, const char *addrStr, diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index b5cb0ee..eadfaf1 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -59,6 +59,10 @@ typedef enum { # define VIR_PCI_CONNECT_TYPES_ENDPOINT \ (VIR_PCI_CONNECT_TYPE_PCI_DEVICE | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE) +int +virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model, + virDomainPCIConnectFlags *connectType); + typedef struct { virDomainControllerModelPCI model; /* flags and min/max can be computed from model, but diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index af133c5..6642f3a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -107,6 +107,7 @@ virDomainPCIAddressSetFree; virDomainPCIAddressSetGrow; virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; +virDomainPCIControllerModelToConnectType; virDomainVirtioSerialAddrAssign; virDomainVirtioSerialAddrAutoAssign; virDomainVirtioSerialAddrIsComplete; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index c6e694e..7d3e441 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -446,39 +446,9 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, case VIR_DOMAIN_DEVICE_CONTROLLER: switch (device->data.controller->type) { case VIR_DOMAIN_CONTROLLER_TYPE_PCI: - switch (device->data.controller->model) { - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: - /* pci-bridge needs a PCI slot, but it isn't - * hot-pluggable, so it doesn't need a hot-pluggable slot. - */ - flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - /* pci-bridge needs a PCIe slot, but it isn't - * hot-pluggable, so it doesn't need a hot-pluggable slot. - */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - /* pcie-root-port isn't hot-pluggable, and - * is unique in what it can connect to, so - * it has its own flag. - */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - /* pcie-switch-upstream-port is also unique, and - * not hot-pluggable... - */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - /* ... same for pcie-switch-downstream-port */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; - break; - default: - break; - } + if (virDomainPCIControllerModelToConnectType(device->data.controller->model, + &flags) < 0) + return -1; break; case VIR_DOMAIN_CONTROLLER_TYPE_SATA: @@ -1058,51 +1028,19 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, /* PCI controllers */ for (i = 0; i < def->ncontrollers; i++) { if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { - if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + virDomainControllerModelPCI model = def->controllers[i]->model; + + if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || + model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || + model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) continue; /* convert the type of controller into a "CONNECT_TYPE" * flag to use when searching for the proper * controller/bus to connect it to on the upstream side. */ - switch ((virDomainControllerModelPCI)def->controllers[i]->model) { - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: - /* pci-root and pcie-root are implicit in the machine, - * and need no address */ - continue; - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: - /* pci-bridge doesn't require hot-plug - * (although it does provide hot-plug in its slots) - */ - flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - /* dmi-to-pci-bridge is treated like a - * non-hotplug-capable PCIe device (e.g. it can be - * plugged directly into pcie-root) - */ - flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; - break; - - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: - /* if this happens, there is an error in the code. A - * PCI controller should always have a proper model - * set - */ - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("PCI controller model icorrectly set to 'last'")); + if (virDomainPCIControllerModelToConnectType(model, &flags) < 0) goto error; - } if (virDomainPCIAddressReserveNextSlot(addrs, &def->controllers[i]->info, flags) < 0) -- 2.5.5

On Thu, Mar 24, 2016 at 03:25:43PM -0400, Laine Stump wrote:
There are two places in qemu_domain_address.c where we have a switch statement to convert PCI controller models (VIR_DOMAIN_CONTROLLER_MODEL_PCI*) into the connection type flag that is matched when looking for an upstream connection for that model of controller (VIR_PCI_CONNECT_TYPE_*). This patch makes a utility function in conf/domain_addr.c to do that, so that when a new PCI controller is added, we only need to add the new model-->connect-type in a single place. --- src/conf/domain_addr.c | 47 +++++++++++++++++++++++++ src/conf/domain_addr.h | 4 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 80 +++++------------------------------------- 4 files changed, 61 insertions(+), 71 deletions(-)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 4408c4a..1bf2c9a 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -32,6 +32,53 @@
VIR_LOG_INIT("conf.domain_addr");
+int +virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model, + virDomainPCIConnectFlags *connectType) +{ + /* given a VIR_DOMAIN_CONTROLLER_MODEL_PCI*, set connectType to + * the equivalent VIR_PCI_CONNECT_TYPE_*. return 0 on success, -1 + * if the model wasn't recognized. + */ + switch (model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + /* pci-root and pcie-root are implicit in the machine, + * and have no upstream connection + */ + *connectType = 0; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + /* pci-bridge is treated like a standard PCI endpoint device, */ + *connectType = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + /* dmi-to-pci-bridge is treated like a PCIe device + * (e.g. it can be plugged directly into pcie-root) + */ + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + /* if this happens, there is an error in the code. A + * PCI controller should always have a proper model + * set + */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("PCI controller model incorrectly set to 'last'")); + return -1;
This is dead code. The function can just return virDomainPCIConnectFlags directly. Jan

On 04/05/2016 08:33 AM, Ján Tomko wrote:
On Thu, Mar 24, 2016 at 03:25:43PM -0400, Laine Stump wrote:
There are two places in qemu_domain_address.c where we have a switch statement to convert PCI controller models (VIR_DOMAIN_CONTROLLER_MODEL_PCI*) into the connection type flag that is matched when looking for an upstream connection for that model of controller (VIR_PCI_CONNECT_TYPE_*). This patch makes a utility function in conf/domain_addr.c to do that, so that when a new PCI controller is added, we only need to add the new model-->connect-type in a single place. --- src/conf/domain_addr.c | 47 +++++++++++++++++++++++++ src/conf/domain_addr.h | 4 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 80 +++++------------------------------------- 4 files changed, 61 insertions(+), 71 deletions(-)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 4408c4a..1bf2c9a 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -32,6 +32,53 @@
VIR_LOG_INIT("conf.domain_addr");
+int +virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model, + virDomainPCIConnectFlags *connectType) +{ + /* given a VIR_DOMAIN_CONTROLLER_MODEL_PCI*, set connectType to + * the equivalent VIR_PCI_CONNECT_TYPE_*. return 0 on success, -1 + * if the model wasn't recognized. + */ + switch (model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + /* pci-root and pcie-root are implicit in the machine, + * and have no upstream connection + */ + *connectType = 0; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + /* pci-bridge is treated like a standard PCI endpoint device, */ + *connectType = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + /* dmi-to-pci-bridge is treated like a PCIe device + * (e.g. it can be plugged directly into pcie-root) + */ + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + *connectType = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + /* if this happens, there is an error in the code. A + * PCI controller should always have a proper model + * set + */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("PCI controller model incorrectly set to 'last'")); + return -1; This is dead code. The function can just return virDomainPCIConnectFlags directly.
I was originally going to do that, but since the switch is over an enum, all possible values must have cases. I suppose I could just hand-wave over that case saying "This will never happen" and have it return 0. Actually, I think I *will* do that; it would be reasonable to think that someone would screw up by failing to set the model (in which case it would be 0, i.e. "...PCI_ROOT"), but it would take some serious ill intent to set it to "...PCI_LAST"

Since every PCI controller model has to have a default model name set, put it in a separate function to clean up qemuDomainAssignPCIAddresses a bit. --- src/qemu/qemu_domain_address.c | 54 +++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 7d3e441..e120ab4 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1351,6 +1351,38 @@ qemuDomainSupportsPCI(virDomainDefPtr def, } +static void +qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) +{ + int *modelName = &cont->opts.pciopts.modelName; + + /* make sure it's not already set */ + if (*modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) + return; + switch ((virDomainControllerModelPCI)cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + break; + } +} + + static int qemuDomainAssignPCIAddresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, @@ -1451,41 +1483,35 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, addr = &cont->info.addr.pci; options = &cont->opts.pciopts; + /* set default model name (the actual name of the + * device in qemu) for any controller that doesn't yet + * have it set. + */ + qemuDomainPCIControllerSetDefaultModelName(cont); + /* set defaults for any other auto-generated config * options for this controller that haven't been * specified in config. */ switch ((virDomainControllerModelPCI)cont->model) { case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: - if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) - options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE; if (options->chassisNr == -1) options->chassisNr = cont->idx; break; - case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) - options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE; - break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) - options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420; if (options->chassis == -1) options->chassis = cont->idx; if (options->port == -1) options->port = (addr->slot << 3) + addr->function; break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) - options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM; - break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) - options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM; if (options->chassis == -1) options->chassis = cont->idx; if (options->port == -1) options->port = addr->slot; break; + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: -- 2.5.5

The pxb device is a PCI expander bus that can be added to any 440fx-based machinetype. The PCI bus that is created has 32 standard PCI slots (hotpluggable). It can have a NUMA node number associated with it, as well as a bus number. --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.4.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.5.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 1 + 5 files changed, 6 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b223837..b85a157 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -321,6 +321,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "qxl-vga.vram64_size_mb", /* 215 */ "chardev-logfile", "debug-threads", + "pxb", ); @@ -1575,6 +1576,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "virtio-input-host-device", QEMU_CAPS_VIRTIO_INPUT_HOST }, { "virtio-input-host-pci", QEMU_CAPS_VIRTIO_INPUT_HOST }, { "mptsas1068", QEMU_CAPS_SCSI_MPTSAS1068 }, + { "pxb", QEMU_CAPS_DEVICE_PXB }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index caf3d1b..738adb8 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -351,6 +351,7 @@ typedef enum { QEMU_CAPS_QXL_VGA_VRAM64, /* -device qxl-vga.vram64_size_mb */ QEMU_CAPS_CHARDEV_LOGFILE, /* -chardev logfile=xxxx */ QEMU_CAPS_NAME_DEBUG_THREADS, /* Is -name debug-threads= available */ + QEMU_CAPS_DEVICE_PXB, /* -device pxb */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.4.0-1.caps b/tests/qemucapabilitiesdata/caps_2.4.0-1.caps index efbf9af..0423e9c 100644 --- a/tests/qemucapabilitiesdata/caps_2.4.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.4.0-1.caps @@ -174,4 +174,5 @@ <flag name='qxl.vram64_size_mb'/> <flag name='qxl-vga.vram64_size_mb'/> <flag name='debug-threads'/> + <flag name='pxb'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_2.5.0-1.caps b/tests/qemucapabilitiesdata/caps_2.5.0-1.caps index 5fd3bce..060ae25 100644 --- a/tests/qemucapabilitiesdata/caps_2.5.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.5.0-1.caps @@ -175,4 +175,5 @@ <flag name='qxl.vram64_size_mb'/> <flag name='qxl-vga.vram64_size_mb'/> <flag name='debug-threads'/> + <flag name='pxb'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-1.caps b/tests/qemucapabilitiesdata/caps_2.6.0-1.caps index 549759c..ebedb9c 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.6.0-1.caps @@ -178,4 +178,5 @@ <flag name='qxl.vram64_size_mb'/> <flag name='qxl-vga.vram64_size_mb'/> <flag name='debug-threads'/> + <flag name='pxb'/> </qemuCaps> -- 2.5.5

This is a standard PCI root bus (not a bridge) that can be added to a 440fx-based domain. Although it uses a PCI slot, this is *not* how it is connected into the PCI bus hierarchy, but is only used for control. Each pci-expander-bus provides 32 slots (0-31) that can accept hotplug of standard PCI devices. The usefulness of pci-expander-bus relative to a pci-bridge is that the NUMA node of the bus can be specified with the <node> subelement of <target>. This gives guest-side visibility to the NUMA node of attached devices (presuming that management apps only assign a device to a bus that has a NUMA node number matching the node number of the device on the host). Each pci-expander-bus also has a "busNr" attribute. The expander-bus itself will take the busNr specified, and all buses that are connected to this bus (including the pci-bridge that is automatically added to any expander bus of model "pxb" (see the next commit)) will use busNr+1, busNr+2, etc, and the pci-root (or the expander-bus with next lower busNr) will use bus numbers lower than busNr. --- docs/formatdomain.html.in | 44 ++++- docs/schemas/domaincommon.rng | 14 +- src/conf/domain_addr.c | 13 +- src/conf/domain_conf.c | 59 +++++- src/conf/domain_conf.h | 9 +- src/qemu/qemu_domain_address.c | 2 + .../qemuxml2argv-pci-expander-bus.xml | 167 +++++++++++++++++ .../qemuxml2xmlout-pci-expander-bus.xml | 206 +++++++++++++++++++++ tests/qemuxml2xmltest.c | 3 + 9 files changed, 503 insertions(+), 14 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 71ffe75..5552b90 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3043,12 +3043,13 @@ PCI controllers have an optional <code>model</code> attribute with possible values <code>pci-root</code>, <code>pcie-root</code>, <code>pcie-root-port</code>, <code>pci-bridge</code>, - <code>dmi-to-pci-bridge</code>, <code>pcie-switch-upstream-port</code>, or - <code>pcie-switch-downstream-port</code>. + <code>dmi-to-pci-bridge</code>, <code>pcie-switch-upstream-port</code>, + <code>pcie-switch-downstream-port</code>, or <code>pci-expander-bus</code>. (pci-root and pci-bridge <span class="since">since 1.0.5</span>, pcie-root and dmi-to-pci-bridge <span class="since">since - 1.1.2</span>, pcie-root-port, pcie-switch-upstream-port, and - pcie-switch-downstream-port <span class="since">since 1.2.19</span>) + 1.1.2</span>, pcie-root-port, pcie-switch-upstream-port, + pcie-switch-downstream-port <span class="since">since 1.2.19</span>, + and pci-expander-bus <span class="since">since 1.3.3</span>) The root controllers (<code>pci-root</code> and <code>pcie-root</code>) have an optional <code>pcihole64</code> element specifying how big (in kilobytes, or in the unit specified by <code>pcihole64</code>'s @@ -3072,9 +3073,9 @@ </p> <p> PCI controllers also have an optional - subelement <code><target></code> with the attributes - listed below. These are configurable items that 1) are visible - to the guest OS so must be preserved for guest ABI + subelement <code><target></code> with the attributes and + subelements listed below. These are configurable items that 1) + are visible to the guest OS so must be preserved for guest ABI compatibility, and 2) are usually left to default values or derived automatically by libvirt. In almost all cases, you should not manually add a <code><target></code> subelement @@ -3111,6 +3112,35 @@ which is visible to the virtual machine. If set, port must be between 0 and 255. </dd> + <dt><code>busNr</code></dt> + <dd> + pci-expander-bus controllers can have an + optional <code>busNr</code> attribute (1-254). This will be + the bus number of the new bus; All bus numbers between that + specified and 255 will be available only for assignment to + PCI/PCIe controllers plugged into the hierarchy starting with + this expander bus, and bus numbers less than the specified + value will be available to the next lower expander-bus (or the + root-bus if there are no lower expander buses). If you do not + specify a busNumber, libvirt will find the lowest existing + busNumber in all other expander buses (or use 256 if there are + no others) and auto-assign the busNr of that found bus - 2, + which provides one bus number for the pci-expander-bus and one + for the pci-bridge that is automatically attached to it (if + you plan on adding more pci-bridges to the hierarchy of the + bus, you should manually set busNr to a lower value). + </dd> + <dt><code><node></code></dt> + <dd> + pci-expander-bus controllers can have an + optional <code><node></code> subelement within + the <code><target></code> subelement, which is used to + set the NUMA node reported to the guest OS for that bus - the + guest OS will then know that all devices on that bus are a + part of the specified NUMA node (it is up to the user of the + libvirt API to attach host devices to the correct + pci-expander-bus when assigning them to the domain). + </dd> </dl> <p> For machine types which provide an implicit PCI bus, the pci-root diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 236a2ba..8827807 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1759,6 +1759,8 @@ <value>x3130-upstream</value> <!-- implementations of 'pcie-switch-downstream-port' --> <value>xio3130-downstream</value> + <!-- implementations of 'pci-expander-bus' --> + <value>pxb</value> </choice> </attribute> <empty/> @@ -1781,7 +1783,16 @@ <ref name='uint8'/> </attribute> </optional> - <empty/> + <optional> + <attribute name='busNr'> + <ref name='uint8'/> + </attribute> + </optional> + <optional> + <element name='node'> + <ref name='unsignedInt'/> + </element> + </optional> </element> </optional> <!-- *-root controllers have an optional element "pcihole64"--> @@ -1807,6 +1818,7 @@ <value>pcie-root-port</value> <value>pcie-switch-upstream-port</value> <value>pcie-switch-downstream-port</value> + <value>pci-expander-bus</value> </choice> </attribute> </group> diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 1bf2c9a..5293dc9 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -49,7 +49,11 @@ virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model, *connectType = 0; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: - /* pci-bridge is treated like a standard PCI endpoint device, */ + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + /* pci-bridge and pci-expander-bus are treated like a standard + * PCI endpoint device, because they can plug into any + * standard PCI slot. + */ *connectType = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: @@ -230,6 +234,13 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, bus->minSlot = 1; bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE | + VIR_PCI_CONNECT_TYPE_PCI_DEVICE); + bus->minSlot = 0; + bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: /* slots 1 - 31, no hotplug, PCIe endpoint device or * pcie-root-port only, unless the address was specified in diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d5d9ff7..1619517 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -314,7 +314,8 @@ VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST, "dmi-to-pci-bridge", "pcie-root-port", "pcie-switch-upstream-port", - "pcie-switch-downstream-port") + "pcie-switch-downstream-port", + "pci-expander-bus") VIR_ENUM_IMPL(virDomainControllerPCIModelName, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST, @@ -323,7 +324,8 @@ VIR_ENUM_IMPL(virDomainControllerPCIModelName, "i82801b11-bridge", "ioh3420", "x3130-upstream", - "xio3130-downstream") + "xio3130-downstream", + "pxb") VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST, "auto", @@ -1648,6 +1650,8 @@ virDomainControllerDefNew(virDomainControllerType type) def->opts.pciopts.chassisNr = -1; def->opts.pciopts.chassis = -1; def->opts.pciopts.port = -1; + def->opts.pciopts.busNr = -1; + def->opts.pciopts.numaNode = -1; break; case VIR_DOMAIN_CONTROLLER_TYPE_IDE: case VIR_DOMAIN_CONTROLLER_TYPE_FDC: @@ -7870,6 +7874,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, char *chassisNr = NULL; char *chassis = NULL; char *port = NULL; + char *busNr = NULL; + int numaNode = -1; char *ioeventfd = NULL; xmlNodePtr saved = ctxt->node; int rc; @@ -7934,12 +7940,23 @@ virDomainControllerDefParseXML(xmlNodePtr node, chassisNr = virXMLPropString(cur, "chassisNr"); chassis = virXMLPropString(cur, "chassis"); port = virXMLPropString(cur, "port"); + busNr = virXMLPropString(cur, "busNr"); processedTarget = true; } } cur = cur->next; } + /* node is parsed differently from target attributes because + * someone thought it should be a subelement instead... + */ + rc = virXPathInt("string(./target/node)", ctxt, &numaNode); + if (rc == -2 || (rc == 0 && numaNode < 0)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("invalid NUMA node in target")); + goto error; + } + if (queues && virStrToLong_ui(queues, NULL, 10, &def->queues) < 0) { virReportError(VIR_ERR_XML_ERROR, _("Malformed 'queues' value '%s'"), queues); @@ -8109,6 +8126,25 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; } } + if (busNr) { + if (virStrToLong_i(busNr, NULL, 0, + &def->opts.pciopts.busNr) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid busNr '%s' in PCI controller"), + busNr); + goto error; + } + if (def->opts.pciopts.busNr < 0 || + def->opts.pciopts.busNr > 254) { + virReportError(VIR_ERR_XML_ERROR, + _("PCI controller busNr '%s' out of range " + "- must be 0-254"), + busNr); + goto error; + } + } + if (numaNode >= 0) + def->opts.pciopts.numaNode = numaNode; break; default: @@ -8127,6 +8163,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, VIR_FREE(chassisNr); VIR_FREE(chassis); VIR_FREE(port); + VIR_FREE(busNr); VIR_FREE(ioeventfd); return def; @@ -19299,7 +19336,9 @@ virDomainControllerDefFormat(virBufferPtr buf, pciModel = true; if (def->opts.pciopts.chassisNr != -1 || def->opts.pciopts.chassis != -1 || - def->opts.pciopts.port != -1) + def->opts.pciopts.port != -1 || + def->opts.pciopts.busNr != -1 || + def->opts.pciopts.numaNode != -1) pciTarget = true; break; @@ -19335,7 +19374,19 @@ virDomainControllerDefFormat(virBufferPtr buf, if (def->opts.pciopts.port != -1) virBufferAsprintf(buf, " port='0x%x'", def->opts.pciopts.port); - virBufferAddLit(buf, "/>\n"); + if (def->opts.pciopts.busNr != -1) + virBufferAsprintf(buf, " busNr='%d'", + def->opts.pciopts.busNr); + if (def->opts.pciopts.numaNode == -1) { + virBufferAddLit(buf, "/>\n"); + } else { + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + virBufferAsprintf(buf, "<node>%d</node>\n", + def->opts.pciopts.numaNode); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</target>\n"); + } } if (def->queues || def->cmd_per_lun || diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 83bdd67..4757065 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1,7 +1,7 @@ /* * domain_conf.h: domain XML processing * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2016 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. * @@ -757,6 +757,7 @@ typedef enum { VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT, VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT, VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT, + VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST } virDomainControllerModelPCI; @@ -768,6 +769,7 @@ typedef enum { VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM, + VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST } virDomainControllerPCIModelName; @@ -832,6 +834,11 @@ struct _virDomainPCIControllerOpts { * pcie-root-port/pcie-switch-downstream-port, -1 = unspecified */ int chassis; int port; + int busNr; /* used by pci-expander-bus, -1 == unspecified */ + /* numaNode is a *subelement* of target (to match existing + * item in memory target config) -1 == unspecified + */ + int numaNode; }; /* Stores the virtual disk controller configuration */ diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index e120ab4..0aca829 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1375,6 +1375,7 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM; break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: @@ -1510,6 +1511,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, if (options->port == -1) options->port = addr->slot; break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml new file mode 100644 index 0000000..79c9593 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml @@ -0,0 +1,167 @@ +<domain type='qemu'> + <name>expander-test</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + </os> + <cpu> + <topology sockets='2' cores='4' threads='2'/> + <numa> + <cell cpus='0-7' memory='109550' unit='KiB'/> + <cell cpus='8-15' memory='109550' unit='KiB'/> + </numa> + </cpu> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='1' model='pci-expander-bus'> + <model name='pxb'/> + <target busNr='254'> + <node>1</node> + </target> + </controller> + <controller type='pci' index='2' model='pci-expander-bus'> + <model name='pxb'/> + </controller> + <interface type='user'> + <mac address='52:54:00:f1:95:51'/> + <model type='rtl8139'/> + </interface> + <interface type='user'> + <mac address='52:54:00:5c:c6:1a'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:39:97:ac'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:45:28:cb'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ee:b9:a8'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a9:f7:17'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:2b:f3'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:78:94:b4'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:6b:9b:06'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:17:df:bc'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:3b:d0:51'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8d:2d:17'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a7:66:af'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:54:ab:d7'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:1f:99:90'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c8:43:87'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:22:b2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:d2:9a:47'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:86:05:e2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8c:1c:c2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:48:58:92'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:99:e5:bf'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:b1:8c:25'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:60:e0:d0'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:37:00:6a'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c7:c8:ad'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:4e:a7:cf'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:00:79:69'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:47:00:6f'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:2a:8c:8b'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ec:d5:e3'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6e:c8'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml new file mode 100644 index 0000000..946e94f --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml @@ -0,0 +1,206 @@ +<domain type='qemu'> + <name>expander-test</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + <boot dev='hd'/> + </os> + <cpu> + <topology sockets='2' cores='4' threads='2'/> + <numa> + <cell id='0' cpus='0-7' memory='109550' unit='KiB'/> + <cell id='1' cpus='8-15' memory='109550' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='1' model='pci-expander-bus'> + <model name='pxb'/> + <target busNr='254'> + <node>1</node> + </target> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='2' model='pci-expander-bus'> + <model name='pxb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <interface type='user'> + <mac address='52:54:00:f1:95:51'/> + <model type='rtl8139'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:5c:c6:1a'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:39:97:ac'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:45:28:cb'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ee:b9:a8'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a9:f7:17'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:2b:f3'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:78:94:b4'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:6b:9b:06'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:17:df:bc'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:3b:d0:51'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x10' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8d:2d:17'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x11' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a7:66:af'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x12' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:54:ab:d7'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x13' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:1f:99:90'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x14' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c8:43:87'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x15' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:22:b2'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x16' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:d2:9a:47'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x17' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:86:05:e2'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x18' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8c:1c:c2'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x19' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:48:58:92'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1a' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:99:e5:bf'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1b' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:b1:8c:25'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1c' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:60:e0:d0'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1d' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:37:00:6a'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c7:c8:ad'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:4e:a7:cf'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:00:79:69'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:47:00:6f'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:2a:8c:8b'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x03' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ec:d5:e3'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x04' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6e:c8'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x05' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 0735677..016340b 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -641,6 +641,9 @@ mymain(void) QEMU_CAPS_ICH9_AHCI, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL); + DO_TEST_FULL("pci-expander-bus", WHEN_ACTIVE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_PXB); DO_TEST_FULL("hostdev-scsi-lsi", WHEN_ACTIVE, -- 2.5.5

This is backed by the qemu device "pxb". The pxb device always includes a pci-bridge that is at the bus number of the pxb + 1. busNr and <node> from the <target> subelement are used to set the bus_nr and numa_node options for pxb. During post-parse we validate that the domain's machinetype is 440fx-based (since the pxb device only works on 440fx-based machines), and <node> also gets a sanity check to assure that the NUMA node specified for the pxb (if any - it's optional) actually exists on the guest. This patch and its prerequisites are part of the resolution for: https://bugzilla.redhat.com/show_bug.cgi?id=1103314 --- src/qemu/qemu_command.c | 37 +++++ src/qemu/qemu_domain.c | 33 ++++ src/qemu/qemu_domain_address.c | 82 ++++++++++ .../qemuxml2argv-pci-expander-bus-bad-machine.xml | 167 +++++++++++++++++++++ .../qemuxml2argv-pci-expander-bus-bad-node.xml | 160 ++++++++++++++++++++ .../qemuxml2argv-pci-expander-bus.args | 87 +++++++++++ tests/qemuxml2argvtest.c | 10 ++ .../qemuxml2xmlout-pci-expander-bus.xml | 1 + 8 files changed, 577 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 0331789..3908176 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2368,6 +2368,43 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, modelName, def->opts.pciopts.chassisNr, def->info.alias); break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + if (def->opts.pciopts.modelName + == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE || + def->opts.pciopts.busNr == -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("autogenerated pci-expander-bus options not set")); + goto error; + } + + modelName = virDomainControllerPCIModelNameTypeToString(def->opts.pciopts.modelName); + if (!modelName) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown pci-expander-bus model name value %d"), + def->opts.pciopts.modelName); + goto error; + } + if (def->opts.pciopts.modelName + != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("PCI controller model name '%s' " + "is not valid for a pci-expander-bus"), + modelName); + goto error; + } + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the pxb controller " + "is not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "%s,bus_nr=%d,id=%s", + modelName, def->opts.pciopts.busNr, + def->info.alias); + if (def->opts.pciopts.numaNode != -1) + virBufferAsprintf(&buf, ",numa_node=%d", + def->opts.pciopts.numaNode); + break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: if (def->opts.pciopts.modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) { diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 53cb2b6..3c00a13 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1619,6 +1619,39 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, dev->data.panic->model = VIR_DOMAIN_PANIC_MODEL_ISA; } + + if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { + virDomainControllerDefPtr cont = dev->data.controller; + + if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS) { + + if (!qemuDomainMachineIsI440FX(def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("pci-expander-bus controllers are only supported " + "on 440fx-based machinetypes")); + goto cleanup; + } + + /* if a PCI expander bus has a NUMA node set, make sure + * that NUMA node is configured in the guest <cpu><numa> + * array. NUMA cell id's in this array are numbered + * from 0 .. size-1. + */ + if ((int) virDomainNumaGetNodeCount(def->numa) + <= cont->opts.pciopts.numaNode) { + virReportError(VIR_ERR_XML_ERROR, + _("pci-expander-bus with index %d is " + "configured for a NUMA node (%d) " + "not present in the domain's " + "<cpu><numa> array (%zu)"), + cont->idx, cont->opts.pciopts.numaNode, + virDomainNumaGetNodeCount(def->numa)); + goto cleanup; + } + } + } + ret = 0; cleanup: diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 0aca829..aaec7b5 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1376,6 +1376,8 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB; + break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: @@ -1385,6 +1387,74 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) static int +qemuDomainAddressFindNewBusNr(virDomainDefPtr def) +{ +/* Try to find a nice default for busNr for a new pci-expander-bus. + * This is a bit tricky, since you need to satisfy the following: + * + * 1) There need to be enough unused bus numbers between busNr of this + * bus and busNr of the next highest bus for the guest to assign a + * unique bus number to each PCI bus that is a child of this + * bus. Each PCI controller. On top of this, the pxb device (which + * implements the pci-extender-bus) includes a pci-bridge within + * it, and that bridge also uses one bus number (so each pxb device + * requires at least 2 bus numbers). + * + * 2) There need to be enough bus numbers *below* this for all the + * child controllers of the pci-expander-bus with the next lower + * busNr (or the pci-root bus if there are no lower + * pci-expander-buses). + * + * 3) If at all possible, we want to avoid needing to change the busNr + * of a bus in the future, as that changes the guest's device ABI, + * which could potentially lead to issues with a guest OS that is + * picky about such things. + * + * Due to the impossibility of predicting what might be added to the + * config in the future, we can't make a foolproof choice, but since + * a pci-expander-bus (pxb) has slots for 32 devices, and the only + * practical use for it is to assign real devices on a particular + * NUMA node in the host, it's reasonably safe to assume it should + * never need any additional child buses (probably only a few of the + * 32 will ever be used). So for pci-expander-bus we find the lowest + * existing busNr, and set this one to the current lowest - 2 (one + * for the pxb, one for the intergrated pci-bridge), thus leaving the + * maximum possible bus numbers available for other buses plugged + * into pci-root (i.e. pci-bridges and other + * pci-expander-buses). Anyone who needs more than 32 devices + * descended from one pci-expander-bus should set the busNr manually + * in the config. + * + * There is room for more error checking here - in particular we + * can/should determine the ultimate parent (root-bus) of each PCI + * controller and determine if there is enough space for all the + * buses within the current range allotted to the bus just prior to + * this one. + */ + size_t i; + int lowestBusNr = 256; + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { + int thisBusNr = def->controllers[i]->opts.pciopts.busNr; + + if (thisBusNr >= 0 && thisBusNr < lowestBusNr) + lowestBusNr = thisBusNr; + } + } + + /* If we already have a busNR = 1, then we can't auto-assign (0 is + * the pci[e]-root, and the others may have been assigned + * purposefully). + */ + if (lowestBusNr <= 2) + return -1; + + return lowestBusNr - 2; +} + + +static int qemuDomainAssignPCIAddresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, virDomainObjPtr obj) @@ -1512,6 +1582,18 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, options->port = addr->slot; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + if (options->busNr == -1) + options->busNr = qemuDomainAddressFindNewBusNr(def); + if (options->busNr == -1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("No free busNr lower than current " + "lowest busNr is available to " + "auto-assign to bus %d. Must be " + "manually assigned"), + addr->bus); + goto cleanup; + } + break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml new file mode 100644 index 0000000..606ddfd --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml @@ -0,0 +1,167 @@ +<domain type='qemu'> + <name>expander-test</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + </os> + <cpu> + <topology sockets='2' cores='4' threads='2'/> + <numa> + <cell cpus='0-7' memory='109550' unit='KiB'/> + <cell cpus='8-15' memory='109550' unit='KiB'/> + </numa> + </cpu> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='1' model='pci-expander-bus'> + <model name='pxb'/> + <target busNr='254'> + <node>1</node> + </target> + </controller> + <controller type='pci' index='2' model='pci-expander-bus'> + <model name='pxb'/> + </controller> + <interface type='user'> + <mac address='52:54:00:f1:95:51'/> + <model type='rtl8139'/> + </interface> + <interface type='user'> + <mac address='52:54:00:5c:c6:1a'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:39:97:ac'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:45:28:cb'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ee:b9:a8'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a9:f7:17'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:2b:f3'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:78:94:b4'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:6b:9b:06'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:17:df:bc'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:3b:d0:51'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8d:2d:17'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a7:66:af'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:54:ab:d7'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:1f:99:90'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c8:43:87'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:22:b2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:d2:9a:47'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:86:05:e2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8c:1c:c2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:48:58:92'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:99:e5:bf'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:b1:8c:25'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:60:e0:d0'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:37:00:6a'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c7:c8:ad'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:4e:a7:cf'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:00:79:69'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:47:00:6f'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:2a:8c:8b'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ec:d5:e3'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6e:c8'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml new file mode 100644 index 0000000..2c390ea --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml @@ -0,0 +1,160 @@ +<domain type='qemu'> + <name>expander-test</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='1' model='pci-expander-bus'> + <model name='pxb'/> + <target busNr='254'> + <node>1</node> + </target> + </controller> + <controller type='pci' index='2' model='pci-expander-bus'> + <model name='pxb'/> + </controller> + <interface type='user'> + <mac address='52:54:00:f1:95:51'/> + <model type='rtl8139'/> + </interface> + <interface type='user'> + <mac address='52:54:00:5c:c6:1a'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:39:97:ac'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:45:28:cb'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ee:b9:a8'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a9:f7:17'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:2b:f3'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:78:94:b4'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:6b:9b:06'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:17:df:bc'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:3b:d0:51'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8d:2d:17'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a7:66:af'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:54:ab:d7'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:1f:99:90'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c8:43:87'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:22:b2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:d2:9a:47'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:86:05:e2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8c:1c:c2'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:48:58:92'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:99:e5:bf'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:b1:8c:25'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:60:e0:d0'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:37:00:6a'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c7:c8:ad'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:4e:a7:cf'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:00:79:69'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:47:00:6f'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:2a:8c:8b'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ec:d5:e3'/> + <model type='e1000'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6e:c8'/> + <model type='e1000'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args new file mode 100644 index 0000000..268a301 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args @@ -0,0 +1,87 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name expander-test \ +-S \ +-M pc-i440fx-2.5 \ +-m 214 \ +-smp 16 \ +-numa node,nodeid=0,cpus=0-7,mem=107 \ +-numa node,nodeid=1,cpus=8-15,mem=107 \ +-uuid 3ec6cbe1-b5a2-4515-b800-31a61855df41 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-expander-test/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-device pxb,bus_nr=254,id=pci.1,numa_node=1,bus=pci.0,addr=0x3 \ +-device pxb,bus_nr=252,id=pci.2,bus=pci.0,addr=0x4 \ +-device rtl8139,vlan=0,id=net0,mac=52:54:00:f1:95:51,bus=pci.0,addr=0x5 \ +-net user,vlan=0,name=hostnet0 \ +-device e1000,vlan=1,id=net1,mac=52:54:00:5c:c6:1a,bus=pci.0,addr=0x7 \ +-net user,vlan=1,name=hostnet1 \ +-device e1000,vlan=2,id=net2,mac=52:54:00:39:97:ac,bus=pci.0,addr=0x8 \ +-net user,vlan=2,name=hostnet2 \ +-device e1000,vlan=3,id=net3,mac=52:54:00:45:28:cb,bus=pci.0,addr=0x9 \ +-net user,vlan=3,name=hostnet3 \ +-device e1000,vlan=4,id=net4,mac=52:54:00:ee:b9:a8,bus=pci.0,addr=0xa \ +-net user,vlan=4,name=hostnet4 \ +-device e1000,vlan=5,id=net5,mac=52:54:00:a9:f7:17,bus=pci.0,addr=0xb \ +-net user,vlan=5,name=hostnet5 \ +-device e1000,vlan=6,id=net6,mac=52:54:00:df:2b:f3,bus=pci.0,addr=0xc \ +-net user,vlan=6,name=hostnet6 \ +-device e1000,vlan=7,id=net7,mac=52:54:00:78:94:b4,bus=pci.0,addr=0xd \ +-net user,vlan=7,name=hostnet7 \ +-device e1000,vlan=8,id=net8,mac=52:54:00:6b:9b:06,bus=pci.0,addr=0xe \ +-net user,vlan=8,name=hostnet8 \ +-device e1000,vlan=9,id=net9,mac=52:54:00:17:df:bc,bus=pci.0,addr=0xf \ +-net user,vlan=9,name=hostnet9 \ +-device e1000,vlan=10,id=net10,mac=52:54:00:3b:d0:51,bus=pci.0,addr=0x10 \ +-net user,vlan=10,name=hostnet10 \ +-device e1000,vlan=11,id=net11,mac=52:54:00:8d:2d:17,bus=pci.0,addr=0x11 \ +-net user,vlan=11,name=hostnet11 \ +-device e1000,vlan=12,id=net12,mac=52:54:00:a7:66:af,bus=pci.0,addr=0x12 \ +-net user,vlan=12,name=hostnet12 \ +-device e1000,vlan=13,id=net13,mac=52:54:00:54:ab:d7,bus=pci.0,addr=0x13 \ +-net user,vlan=13,name=hostnet13 \ +-device e1000,vlan=14,id=net14,mac=52:54:00:1f:99:90,bus=pci.0,addr=0x14 \ +-net user,vlan=14,name=hostnet14 \ +-device e1000,vlan=15,id=net15,mac=52:54:00:c8:43:87,bus=pci.0,addr=0x15 \ +-net user,vlan=15,name=hostnet15 \ +-device e1000,vlan=16,id=net16,mac=52:54:00:df:22:b2,bus=pci.0,addr=0x16 \ +-net user,vlan=16,name=hostnet16 \ +-device e1000,vlan=17,id=net17,mac=52:54:00:d2:9a:47,bus=pci.0,addr=0x17 \ +-net user,vlan=17,name=hostnet17 \ +-device e1000,vlan=18,id=net18,mac=52:54:00:86:05:e2,bus=pci.0,addr=0x18 \ +-net user,vlan=18,name=hostnet18 \ +-device e1000,vlan=19,id=net19,mac=52:54:00:8c:1c:c2,bus=pci.0,addr=0x19 \ +-net user,vlan=19,name=hostnet19 \ +-device e1000,vlan=20,id=net20,mac=52:54:00:48:58:92,bus=pci.0,addr=0x1a \ +-net user,vlan=20,name=hostnet20 \ +-device e1000,vlan=21,id=net21,mac=52:54:00:99:e5:bf,bus=pci.0,addr=0x1b \ +-net user,vlan=21,name=hostnet21 \ +-device e1000,vlan=22,id=net22,mac=52:54:00:b1:8c:25,bus=pci.0,addr=0x1c \ +-net user,vlan=22,name=hostnet22 \ +-device e1000,vlan=23,id=net23,mac=52:54:00:60:e0:d0,bus=pci.0,addr=0x1d \ +-net user,vlan=23,name=hostnet23 \ +-device e1000,vlan=24,id=net24,mac=52:54:00:37:00:6a,bus=pci.0,addr=0x1e \ +-net user,vlan=24,name=hostnet24 \ +-device e1000,vlan=25,id=net25,mac=52:54:00:c7:c8:ad,bus=pci.0,addr=0x1f \ +-net user,vlan=25,name=hostnet25 \ +-device e1000,vlan=26,id=net26,mac=52:54:00:4e:a7:cf,bus=pci.1,addr=0x0 \ +-net user,vlan=26,name=hostnet26 \ +-device e1000,vlan=27,id=net27,mac=52:54:00:00:79:69,bus=pci.1,addr=0x1 \ +-net user,vlan=27,name=hostnet27 \ +-device e1000,vlan=28,id=net28,mac=52:54:00:47:00:6f,bus=pci.1,addr=0x2 \ +-net user,vlan=28,name=hostnet28 \ +-device e1000,vlan=29,id=net29,mac=52:54:00:2a:8c:8b,bus=pci.1,addr=0x3 \ +-net user,vlan=29,name=hostnet29 \ +-device e1000,vlan=30,id=net30,mac=52:54:00:ec:d5:e3,bus=pci.1,addr=0x4 \ +-net user,vlan=30,name=hostnet30 \ +-device e1000,vlan=31,id=net31,mac=52:54:00:7e:6e:c8,bus=pci.1,addr=0x5 \ +-net user,vlan=31,name=hostnet31 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index e9b8d64..65be98f 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1580,6 +1580,16 @@ mymain(void) QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL); + DO_TEST("pci-expander-bus", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_PXB); + DO_TEST_PARSE_ERROR("pci-expander-bus-bad-node", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_PXB); + DO_TEST_PARSE_ERROR("pci-expander-bus-bad-machine", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_PXB); + DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_DEVICE_SCSI_GENERIC); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml index 946e94f..e0d787e 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml @@ -35,6 +35,7 @@ </controller> <controller type='pci' index='2' model='pci-expander-bus'> <model name='pxb'/> + <target busNr='252'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </controller> <interface type='user'> -- 2.5.5

The pxb device is a PCIe expander bus that can be added to any Q35-based machinetype. A single PCIe port (*not* hotpluggable) is provided; if more than one device is desired, or if hotplug support is needed, either a pcie-root-port, or some combination of pcie-switch-upstream-port and pcie-swith-downstream-ports must be added to it. It can have a NUMA node number associated with it, as well as a bus number. --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.replies | 3 +++ 4 files changed, 7 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b85a157..8c4583f 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -322,6 +322,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "chardev-logfile", "debug-threads", "pxb", + "pxb-pcie", ); @@ -1577,6 +1578,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "virtio-input-host-pci", QEMU_CAPS_VIRTIO_INPUT_HOST }, { "mptsas1068", QEMU_CAPS_SCSI_MPTSAS1068 }, { "pxb", QEMU_CAPS_DEVICE_PXB }, + { "pxb-pcie", QEMU_CAPS_DEVICE_PXB_PCIE }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 738adb8..e37ef70 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -352,6 +352,7 @@ typedef enum { QEMU_CAPS_CHARDEV_LOGFILE, /* -chardev logfile=xxxx */ QEMU_CAPS_NAME_DEBUG_THREADS, /* Is -name debug-threads= available */ QEMU_CAPS_DEVICE_PXB, /* -device pxb */ + QEMU_CAPS_DEVICE_PXB_PCIE, /* -device pxb-pcie */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-1.caps b/tests/qemucapabilitiesdata/caps_2.6.0-1.caps index ebedb9c..3a758b4 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_2.6.0-1.caps @@ -179,4 +179,5 @@ <flag name='qxl-vga.vram64_size_mb'/> <flag name='debug-threads'/> <flag name='pxb'/> + <flag name='pxb-pcie'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-1.replies b/tests/qemucapabilitiesdata/caps_2.6.0-1.replies index d2b58b5..5840b3e 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-1.replies +++ b/tests/qemucapabilitiesdata/caps_2.6.0-1.replies @@ -1320,6 +1320,9 @@ "name": "pxb" }, { + "name": "pxb-pcie" + }, + { "name": "kvm64-x86_64-cpu" }, { -- 2.5.5

This controller provides a single PCIe port on a new root. It is similar to pci-expander-bus, intended to provide a bus that can be associated with a guest-identifiable NUMA node, but is for machinetypes with PCIe rather than PCI (e.g. q35-based machinetypes). Aside from PCIe vs. PCI, the other main difference is that a pci-expander-bus has a companion pci-bridge that is automatically attached along with it, but pcie-expander-bus has only a single port, and that port will only connect to a pcie-root-port, or to a pcie-switch-upstream-port. In order for the bus to be of any use in the guest, it must have either a pcie-root-port or a pcie-switch-upstream-port attached (and one or more pcie-switch-downstream-ports attached to the pcie-switch-upstream-port). --- docs/formatdomain.html.in | 40 ++- docs/schemas/domaincommon.rng | 3 + src/conf/domain_addr.c | 17 +- src/conf/domain_conf.c | 6 +- src/conf/domain_conf.h | 2 + src/qemu/qemu_domain_address.c | 2 + .../qemuxml2argv-pcie-expander-bus.xml | 247 +++++++++++++ .../qemuxml2xmlout-pcie-expander-bus.xml | 384 +++++++++++++++++++++ tests/qemuxml2xmltest.c | 7 + 9 files changed, 694 insertions(+), 14 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 5552b90..2a315dd 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3044,15 +3044,18 @@ possible values <code>pci-root</code>, <code>pcie-root</code>, <code>pcie-root-port</code>, <code>pci-bridge</code>, <code>dmi-to-pci-bridge</code>, <code>pcie-switch-upstream-port</code>, - <code>pcie-switch-downstream-port</code>, or <code>pci-expander-bus</code>. - (pci-root and pci-bridge <span class="since">since 1.0.5</span>, - pcie-root and dmi-to-pci-bridge <span class="since">since - 1.1.2</span>, pcie-root-port, pcie-switch-upstream-port, - pcie-switch-downstream-port <span class="since">since 1.2.19</span>, - and pci-expander-bus <span class="since">since 1.3.3</span>) - The root controllers (<code>pci-root</code> and <code>pcie-root</code>) - have an optional <code>pcihole64</code> element specifying how big - (in kilobytes, or in the unit specified by <code>pcihole64</code>'s + <code>pcie-switch-downstream-port</code>, <code>pci-expander-bus</code>, + or <code>pcie-expander-bus</code>. (pci-root and + pci-bridge <span class="since">since 1.0.5</span>, pcie-root and + dmi-to-pci-bridge <span class="since">since 1.1.2</span>, + pcie-root-port, pcie-switch-upstream-port, + pcie-switch-downstream-port <span class="since">since + 1.2.19</span>, and pci-expander-bus and + pcie-expander-bus <span class="since">since 1.3.3</span>) The + root controllers (<code>pci-root</code> + and <code>pcie-root</code>) have an + optional <code>pcihole64</code> element specifying how big (in + kilobytes, or in the unit specified by <code>pcihole64</code>'s <code>unit</code> attribute) the 64-bit PCI hole should be. Some guests (like Windows XP or Windows Server 2003) might crash when QEMU and Seabios are recent enough to support 64-bit PCI holes, unless this is disabled @@ -3114,7 +3117,7 @@ </dd> <dt><code>busNr</code></dt> <dd> - pci-expander-bus controllers can have an + pci-expander-bus and pcie-expander-bus controllers can have an optional <code>busNr</code> attribute (1-254). This will be the bus number of the new bus; All bus numbers between that specified and 255 will be available only for assignment to @@ -3129,6 +3132,23 @@ for the pci-bridge that is automatically attached to it (if you plan on adding more pci-bridges to the hierarchy of the bus, you should manually set busNr to a lower value). + <p> + A similar algorithm is used for automatically determining + the busNr attribute for pcie-expander-bus, but since the + pcie-expander-bus doesn't have any built-in pci-bridge, the + 2nd bus-number is just being reserved for the pcie-root-port + that must necessarily be connected to the bus in order to + actually plug in an endpoint device. If you intend to plug + multiple devices into a pcie-expander-bus, you must instead + connect a pcie-switch-upstream-port to the + pcie-expander-bus, and multiple pcie-switch-downstream-ports + to the pcie-switch-downstream-port, and of course for this + to work properly, you will need to decrease the + pcie-expander-bus' busNr accordingly so that there are + enough unused bus numbers above it to accomodate giving out + one bus number for the upstream-port and one for each + downstream-port). + </p> </dd> <dt><code><node></code></dt> <dd> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 8827807..fd9d5a2 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1761,6 +1761,8 @@ <value>xio3130-downstream</value> <!-- implementations of 'pci-expander-bus' --> <value>pxb</value> + <!-- implementations of 'pcie-expander-bus' --> + <value>pxb-pcie</value> </choice> </attribute> <empty/> @@ -1819,6 +1821,7 @@ <value>pcie-switch-upstream-port</value> <value>pcie-switch-downstream-port</value> <value>pci-expander-bus</value> + <value>pcie-expander-bus</value> </choice> </attribute> </group> diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 5293dc9..23d671c 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -57,8 +57,11 @@ virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model, *connectType = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; break; case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - /* dmi-to-pci-bridge is treated like a PCIe device - * (e.g. it can be plugged directly into pcie-root) + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + /* dmi-to-pci-bridge and pcie-expander-bus are treated like + * PCIe devices (the part of pcie-expander-bus that is plugged + * in isn't the expander bus itself, but a companion device + * used for setting it up). */ *connectType = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; break; @@ -278,6 +281,16 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, bus->minSlot = 0; bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + /* single slot, no hotplug, only accepts pcie-root-port or + * pcie-switch-upstream-port. + */ + bus->flags = (VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT + | VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT); + bus->minSlot = 0; + bus->maxSlot = 0; + break; + default: virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid PCI controller model %d"), model); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1619517..b7cffd8 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -315,7 +315,8 @@ VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST, "pcie-root-port", "pcie-switch-upstream-port", "pcie-switch-downstream-port", - "pci-expander-bus") + "pci-expander-bus", + "pcie-expander-bus") VIR_ENUM_IMPL(virDomainControllerPCIModelName, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST, @@ -325,7 +326,8 @@ VIR_ENUM_IMPL(virDomainControllerPCIModelName, "ioh3420", "x3130-upstream", "xio3130-downstream", - "pxb") + "pxb", + "pxb-pcie") VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST, "auto", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 4757065..673ddd0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -758,6 +758,7 @@ typedef enum { VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT, VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT, VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS, + VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST } virDomainControllerModelPCI; @@ -770,6 +771,7 @@ typedef enum { VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB, + VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE, VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST } virDomainControllerPCIModelName; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index aaec7b5..9006643 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1378,6 +1378,7 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB; break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: @@ -1582,6 +1583,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, options->port = addr->slot; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: if (options->busNr == -1) options->busNr = qemuDomainAddressFindNewBusNr(def); if (options->busNr == -1) { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml b/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml new file mode 100644 index 0000000..72681ce --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml @@ -0,0 +1,247 @@ +<domain type='qemu'> + <name>pcie-expander-bus-test</name> + <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <cpu> + <topology sockets='2' cores='4' threads='2'/> + <numa> + <cell cpus='0-7' memory='109550' unit='KiB'/> + <cell cpus='8-15' memory='109550' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='sda' bus='sata'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='dmi-to-pci-bridge'> + <model name='i82801b11-bridge'/> + </controller> + <controller type='pci' index='2' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='56'/> + </controller> + <controller type='pci' index='3' model='pcie-expander-bus'> + <model name='pxb-pcie'/> + <target busNr='254'> + <node>0</node> + </target> + <address type='pci' bus='0x00' slot='4'/> + </controller> + <controller type='pci' index='4' model='pcie-root-port'> + <target busNr='220'> + <node>1</node> + </target> + <address type='pci' bus='0x03'/> + </controller> + <controller type='pci' index='5' model='pcie-switch-upstream-port'> + <address type='pci' bus='0x04'/> + </controller> + <controller type='pci' index='6' model='pcie-switch-downstream-port'/> + <controller type='pci' index='7' model='pcie-switch-downstream-port'/> + <controller type='pci' index='8' model='pcie-switch-downstream-port'/> + <controller type='pci' index='9' model='pcie-switch-downstream-port'/> + <controller type='pci' index='10' model='pcie-switch-downstream-port'/> + <controller type='pci' index='11' model='pcie-switch-downstream-port'/> + <controller type='pci' index='12' model='pcie-switch-downstream-port'/> + <controller type='pci' index='13' model='pcie-switch-downstream-port'/> + <controller type='pci' index='14' model='pcie-switch-downstream-port'/> + <controller type='pci' index='15' model='pcie-switch-downstream-port'/> + <controller type='pci' index='16' model='pcie-switch-downstream-port'/> + <controller type='pci' index='17' model='pcie-switch-downstream-port'/> + <controller type='pci' index='18' model='pcie-switch-downstream-port'/> + <controller type='pci' index='19' model='pcie-switch-downstream-port'/> + <controller type='pci' index='20' model='pcie-switch-downstream-port'/> + <controller type='pci' index='21' model='pcie-switch-downstream-port'/> + <controller type='pci' index='22' model='pcie-switch-downstream-port'/> + <controller type='pci' index='23' model='pcie-switch-downstream-port'/> + <controller type='pci' index='24' model='pcie-switch-downstream-port'/> + <controller type='pci' index='25' model='pcie-switch-downstream-port'/> + <controller type='pci' index='26' model='pcie-switch-downstream-port'/> + <controller type='pci' index='27' model='pcie-switch-downstream-port'/> + <controller type='pci' index='28' model='pcie-switch-downstream-port'/> + <controller type='pci' index='29' model='pcie-switch-downstream-port'/> + <controller type='pci' index='30' model='pcie-switch-downstream-port'/> + <controller type='pci' index='31' model='pcie-switch-downstream-port'/> + <controller type='pci' index='32' model='pcie-switch-downstream-port'/> + <controller type='pci' index='33' model='pcie-switch-downstream-port'/> + <controller type='pci' index='34' model='pcie-switch-downstream-port'/> + <controller type='pci' index='35' model='pcie-switch-downstream-port'/> + <controller type='pci' index='36' model='pcie-switch-downstream-port'/> + <controller type='pci' index='37' model='pcie-switch-downstream-port'/> + <interface type='user'> + <mac address='52:54:00:f1:95:51'/> + <model type='rtl8139'/> + <address type='pci' bus='6'/> + </interface> + <interface type='user'> + <mac address='52:54:00:5c:c6:1a'/> + <model type='e1000'/> + <address type='pci' bus='07'/> + </interface> + <interface type='user'> + <mac address='52:54:00:39:97:ac'/> + <model type='e1000'/> + <address type='pci' bus='8'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ee:b9:a8'/> + <model type='e1000'/> + <address type='pci' bus='9'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a9:f7:17'/> + <model type='e1000'/> + <address type='pci' bus='10'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:2b:f3'/> + <model type='e1000'/> + <address type='pci' bus='11'/> + </interface> + <interface type='user'> + <mac address='52:54:00:78:94:b4'/> + <model type='e1000'/> + <address type='pci' bus='12'/> + </interface> + <interface type='user'> + <mac address='52:54:00:6b:9b:06'/> + <model type='e1000'/> + <address type='pci' bus='13'/> + </interface> + <interface type='user'> + <mac address='52:54:00:17:df:bc'/> + <model type='e1000'/> + <address type='pci' bus='14'/> + </interface> + <interface type='user'> + <mac address='52:54:00:3b:d0:51'/> + <model type='e1000'/> + <address type='pci' bus='15'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8d:2d:17'/> + <model type='e1000'/> + <address type='pci' bus='16'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a7:66:af'/> + <model type='e1000'/> + <address type='pci' bus='17'/> + </interface> + <interface type='user'> + <mac address='52:54:00:54:ab:d7'/> + <model type='e1000'/> + <address type='pci' bus='18'/> + </interface> + <interface type='user'> + <mac address='52:54:00:1f:99:90'/> + <model type='e1000'/> + <address type='pci' bus='19'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c8:43:87'/> + <model type='e1000'/> + <address type='pci' bus='20'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:22:b2'/> + <model type='e1000'/> + <address type='pci' bus='21'/> + </interface> + <interface type='user'> + <mac address='52:54:00:d2:9a:47'/> + <model type='e1000'/> + <address type='pci' bus='22'/> + </interface> + <interface type='user'> + <mac address='52:54:00:86:05:e2'/> + <model type='e1000'/> + <address type='pci' bus='23'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8c:1c:c2'/> + <model type='e1000'/> + <address type='pci' bus='24'/> + </interface> + <interface type='user'> + <mac address='52:54:00:48:58:92'/> + <model type='e1000'/> + <address type='pci' bus='25'/> + </interface> + <interface type='user'> + <mac address='52:54:00:99:e5:bf'/> + <model type='e1000'/> + <address type='pci' bus='26'/> + </interface> + <interface type='user'> + <mac address='52:54:00:b1:8c:25'/> + <model type='e1000'/> + <address type='pci' bus='27'/> + </interface> + <interface type='user'> + <mac address='52:54:00:60:e0:d0'/> + <model type='e1000'/> + <address type='pci' bus='28'/> + </interface> + <interface type='user'> + <mac address='52:54:00:37:00:6a'/> + <model type='e1000'/> + <address type='pci' bus='29'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c7:c8:ad'/> + <model type='e1000'/> + <address type='pci' bus='30'/> + </interface> + <interface type='user'> + <mac address='52:54:00:4e:a7:cf'/> + <model type='e1000'/> + <address type='pci' bus='31'/> + </interface> + <interface type='user'> + <mac address='52:54:00:00:79:69'/> + <model type='e1000'/> + <address type='pci' bus='32'/> + </interface> + <interface type='user'> + <mac address='52:54:00:47:00:6f'/> + <model type='e1000'/> + <address type='pci' bus='33'/> + </interface> + <interface type='user'> + <mac address='52:54:00:2a:8c:8b'/> + <model type='e1000'/> + <address type='pci' bus='34'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ec:d5:e3'/> + <model type='e1000'/> + <address type='pci' bus='35'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6e:c8'/> + <model type='e1000'/> + <address type='pci' bus='36'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6d:c9'/> + <model type='e1000'/> + <address type='pci' bus='37'/> + </interface> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml new file mode 100644 index 0000000..7a37870 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml @@ -0,0 +1,384 @@ +<domain type='qemu'> + <name>pcie-expander-bus-test</name> + <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <cpu> + <topology sockets='2' cores='4' threads='2'/> + <numa> + <cell id='0' cpus='0-7' memory='109550' unit='KiB'/> + <cell id='1' cpus='8-15' memory='109550' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='sda' bus='sata'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='dmi-to-pci-bridge'> + <model name='i82801b11-bridge'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1e' function='0x0'/> + </controller> + <controller type='pci' index='2' model='pci-bridge'> + <model name='pci-bridge'/> + <target chassisNr='56'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='pci' index='3' model='pcie-expander-bus'> + <model name='pxb-pcie'/> + <target busNr='254'> + <node>0</node> + </target> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <controller type='pci' index='4' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='4' port='0x0' busNr='220'> + <node>1</node> + </target> + <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> + </controller> + <controller type='pci' index='5' model='pcie-switch-upstream-port'> + <model name='x3130-upstream'/> + <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> + </controller> + <controller type='pci' index='6' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='6' port='0x0'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/> + </controller> + <controller type='pci' index='7' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='7' port='0x1'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='8' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='8' port='0x2'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x02' function='0x0'/> + </controller> + <controller type='pci' index='9' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='9' port='0x3'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='10' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='10' port='0x4'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x04' function='0x0'/> + </controller> + <controller type='pci' index='11' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='11' port='0x5'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x05' function='0x0'/> + </controller> + <controller type='pci' index='12' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='12' port='0x6'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x06' function='0x0'/> + </controller> + <controller type='pci' index='13' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='13' port='0x7'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x07' function='0x0'/> + </controller> + <controller type='pci' index='14' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='14' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x08' function='0x0'/> + </controller> + <controller type='pci' index='15' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='15' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x09' function='0x0'/> + </controller> + <controller type='pci' index='16' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='16' port='0xa'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x0a' function='0x0'/> + </controller> + <controller type='pci' index='17' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='17' port='0xb'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x0b' function='0x0'/> + </controller> + <controller type='pci' index='18' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='18' port='0xc'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x0c' function='0x0'/> + </controller> + <controller type='pci' index='19' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='19' port='0xd'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x0d' function='0x0'/> + </controller> + <controller type='pci' index='20' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='20' port='0xe'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x0e' function='0x0'/> + </controller> + <controller type='pci' index='21' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='21' port='0xf'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x0f' function='0x0'/> + </controller> + <controller type='pci' index='22' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='22' port='0x10'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x10' function='0x0'/> + </controller> + <controller type='pci' index='23' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='23' port='0x11'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x11' function='0x0'/> + </controller> + <controller type='pci' index='24' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='24' port='0x12'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x12' function='0x0'/> + </controller> + <controller type='pci' index='25' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='25' port='0x13'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x13' function='0x0'/> + </controller> + <controller type='pci' index='26' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='26' port='0x14'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x14' function='0x0'/> + </controller> + <controller type='pci' index='27' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='27' port='0x15'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x15' function='0x0'/> + </controller> + <controller type='pci' index='28' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='28' port='0x16'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x16' function='0x0'/> + </controller> + <controller type='pci' index='29' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='29' port='0x17'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x17' function='0x0'/> + </controller> + <controller type='pci' index='30' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='30' port='0x18'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x18' function='0x0'/> + </controller> + <controller type='pci' index='31' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='31' port='0x19'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x19' function='0x0'/> + </controller> + <controller type='pci' index='32' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='32' port='0x1a'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x1a' function='0x0'/> + </controller> + <controller type='pci' index='33' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='33' port='0x1b'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x1b' function='0x0'/> + </controller> + <controller type='pci' index='34' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='34' port='0x1c'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x1c' function='0x0'/> + </controller> + <controller type='pci' index='35' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='35' port='0x1d'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x1d' function='0x0'/> + </controller> + <controller type='pci' index='36' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='36' port='0x1e'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x1e' function='0x0'/> + </controller> + <controller type='pci' index='37' model='pcie-switch-downstream-port'> + <model name='xio3130-downstream'/> + <target chassis='37' port='0x1f'/> + <address type='pci' domain='0x0000' bus='0x05' slot='0x1f' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <interface type='user'> + <mac address='52:54:00:f1:95:51'/> + <model type='rtl8139'/> + <address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:5c:c6:1a'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:39:97:ac'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ee:b9:a8'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x09' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a9:f7:17'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x0a' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:2b:f3'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x0b' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:78:94:b4'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x0c' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:6b:9b:06'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x0d' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:17:df:bc'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x0e' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:3b:d0:51'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x0f' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8d:2d:17'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x10' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:a7:66:af'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x11' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:54:ab:d7'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x12' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:1f:99:90'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x13' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c8:43:87'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x14' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:df:22:b2'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x15' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:d2:9a:47'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x16' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:86:05:e2'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x17' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:8c:1c:c2'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x18' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:48:58:92'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x19' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:99:e5:bf'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x1a' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:b1:8c:25'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x1b' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:60:e0:d0'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x1c' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:37:00:6a'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x1d' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:c7:c8:ad'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x1e' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:4e:a7:cf'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x1f' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:00:79:69'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x20' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:47:00:6f'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x21' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:2a:8c:8b'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x22' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:ec:d5:e3'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x23' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6e:c8'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x24' slot='0x00' function='0x0'/> + </interface> + <interface type='user'> + <mac address='52:54:00:7e:6d:c9'/> + <model type='e1000'/> + <address type='pci' domain='0x0000' bus='0x25' slot='0x00' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 016340b..e986205 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -644,6 +644,13 @@ mymain(void) DO_TEST_FULL("pci-expander-bus", WHEN_ACTIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_PXB); + DO_TEST_FULL("pcie-expander-bus", WHEN_ACTIVE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_X3130_UPSTREAM, + QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM, + QEMU_CAPS_DEVICE_PXB_PCIE); DO_TEST_FULL("hostdev-scsi-lsi", WHEN_ACTIVE, -- 2.5.5

This is backed by the qemu device pxb-pcie, which will be available in qemu 2.6.0. As with pci-expander-bus (which uses qemu's pxb device), the busNr attribute and <node> subelement of <target> are used to set the bus_nr and numa_node options. During post-parse we validate that the domain's machinetype is q35-based (since the device shows up for 440fx-based machinetypes, but is unusable), as well as checking that <node> specifies a node that is actually configured on the guest. This patch and its prerequisites are part of the resolution for: https://bugzilla.redhat.com/show_bug.cgi?id=1103314 --- src/qemu/qemu_command.c | 37 +++++++ src/qemu/qemu_domain.c | 21 +++- src/qemu/qemu_domain_address.c | 2 + .../qemuxml2argv-pcie-expander-bus-bad-machine.xml | 36 ++++++ .../qemuxml2argv-pcie-expander-bus.args | 123 +++++++++++++++++++++ tests/qemuxml2argvtest.c | 15 +++ 6 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3908176..f12c48c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2537,6 +2537,43 @@ qemuBuildControllerDevStr(const virDomainDef *domainDef, modelName, def->opts.pciopts.port, def->opts.pciopts.chassis, def->info.alias); break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + if (def->opts.pciopts.modelName + == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE || + def->opts.pciopts.busNr == -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("autogenerated pcie-expander-bus options not set")); + goto error; + } + + modelName = virDomainControllerPCIModelNameTypeToString(def->opts.pciopts.modelName); + if (!modelName) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown pcie-expander-bus model name value %d"), + def->opts.pciopts.modelName); + goto error; + } + if (def->opts.pciopts.modelName + != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("PCI controller model name '%s' " + "is not valid for a pcie-expander-bus"), + modelName); + goto error; + } + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PXB_PCIE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("the pxb-pcie controller " + "is not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "%s,bus_nr=%d,id=%s", + modelName, def->opts.pciopts.busNr, + def->info.alias); + if (def->opts.pciopts.numaNode != -1) + virBufferAsprintf(&buf, ",numa_node=%d", + def->opts.pciopts.numaNode); + break; } break; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 3c00a13..c9261cd 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1623,28 +1623,37 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { virDomainControllerDefPtr cont = dev->data.controller; - if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && - cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS) { - - if (!qemuDomainMachineIsI440FX(def)) { + if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS && + !qemuDomainMachineIsI440FX(def)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("pci-expander-bus controllers are only supported " "on 440fx-based machinetypes")); goto cleanup; } + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS && + !qemuDomainMachineIsQ35(def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("pcie-expander-bus controllers are only supported " + "on q35-based machinetypes")); + goto cleanup; + } /* if a PCI expander bus has a NUMA node set, make sure * that NUMA node is configured in the guest <cpu><numa> * array. NUMA cell id's in this array are numbered * from 0 .. size-1. */ - if ((int) virDomainNumaGetNodeCount(def->numa) + if ((cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS || + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS) && + (int) virDomainNumaGetNodeCount(def->numa) <= cont->opts.pciopts.numaNode) { virReportError(VIR_ERR_XML_ERROR, - _("pci-expander-bus with index %d is " + _("%s with index %d is " "configured for a NUMA node (%d) " "not present in the domain's " "<cpu><numa> array (%zu)"), + virDomainControllerModelPCITypeToString(cont->model), cont->idx, cont->opts.pciopts.numaNode, virDomainNumaGetNodeCount(def->numa)); goto cleanup; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 9006643..f5dc9c3 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1379,6 +1379,8 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE; + break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml b/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml new file mode 100644 index 0000000..dc64d97 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml @@ -0,0 +1,36 @@ +<domain type='qemu'> + <name>expander-test</name> + <uuid>3ec6cbe1-b5a2-4515-b800-31a61855df41</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>16</vcpu> + <os> + <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type> + </os> + <cpu> + <topology sockets='2' cores='4' threads='2'/> + <numa> + <cell cpus='0-7' memory='109550' unit='KiB'/> + <cell cpus='8-15' memory='109550' unit='KiB'/> + </numa> + </cpu> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='pci' index='1' model='pcie-expander-bus'> + <model name='pxb-pcie'/> + <target busNr='254'> + <node>1</node> + </target> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args new file mode 100644 index 0000000..13f546c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args @@ -0,0 +1,123 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/libexec/qemu-kvm \ +-name pcie-expander-bus-test \ +-S \ +-M q35 \ +-m 214 \ +-smp 16 \ +-numa node,nodeid=0,cpus=0-7,mem=107 \ +-numa node,nodeid=1,cpus=8-15,mem=107 \ +-uuid 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-pcie-expander-bus-te/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ +-device pci-bridge,chassis_nr=56,id=pci.2,bus=pci.1,addr=0x0 \ +-device pxb-pcie,bus_nr=254,id=pci.3,numa_node=0,bus=pcie.0,addr=0x4 \ +-device ioh3420,port=0x0,chassis=4,id=pci.4,bus=pci.3,addr=0x0 \ +-device x3130-upstream,id=pci.5,bus=pci.4,addr=0x0 \ +-device xio3130-downstream,port=0x0,chassis=6,id=pci.6,bus=pci.5,addr=0x0 \ +-device xio3130-downstream,port=0x1,chassis=7,id=pci.7,bus=pci.5,addr=0x1 \ +-device xio3130-downstream,port=0x2,chassis=8,id=pci.8,bus=pci.5,addr=0x2 \ +-device xio3130-downstream,port=0x3,chassis=9,id=pci.9,bus=pci.5,addr=0x3 \ +-device xio3130-downstream,port=0x4,chassis=10,id=pci.10,bus=pci.5,addr=0x4 \ +-device xio3130-downstream,port=0x5,chassis=11,id=pci.11,bus=pci.5,addr=0x5 \ +-device xio3130-downstream,port=0x6,chassis=12,id=pci.12,bus=pci.5,addr=0x6 \ +-device xio3130-downstream,port=0x7,chassis=13,id=pci.13,bus=pci.5,addr=0x7 \ +-device xio3130-downstream,port=0x8,chassis=14,id=pci.14,bus=pci.5,addr=0x8 \ +-device xio3130-downstream,port=0x9,chassis=15,id=pci.15,bus=pci.5,addr=0x9 \ +-device xio3130-downstream,port=0xa,chassis=16,id=pci.16,bus=pci.5,addr=0xa \ +-device xio3130-downstream,port=0xb,chassis=17,id=pci.17,bus=pci.5,addr=0xb \ +-device xio3130-downstream,port=0xc,chassis=18,id=pci.18,bus=pci.5,addr=0xc \ +-device xio3130-downstream,port=0xd,chassis=19,id=pci.19,bus=pci.5,addr=0xd \ +-device xio3130-downstream,port=0xe,chassis=20,id=pci.20,bus=pci.5,addr=0xe \ +-device xio3130-downstream,port=0xf,chassis=21,id=pci.21,bus=pci.5,addr=0xf \ +-device xio3130-downstream,port=0x10,chassis=22,id=pci.22,bus=pci.5,addr=0x10 \ +-device xio3130-downstream,port=0x11,chassis=23,id=pci.23,bus=pci.5,addr=0x11 \ +-device xio3130-downstream,port=0x12,chassis=24,id=pci.24,bus=pci.5,addr=0x12 \ +-device xio3130-downstream,port=0x13,chassis=25,id=pci.25,bus=pci.5,addr=0x13 \ +-device xio3130-downstream,port=0x14,chassis=26,id=pci.26,bus=pci.5,addr=0x14 \ +-device xio3130-downstream,port=0x15,chassis=27,id=pci.27,bus=pci.5,addr=0x15 \ +-device xio3130-downstream,port=0x16,chassis=28,id=pci.28,bus=pci.5,addr=0x16 \ +-device xio3130-downstream,port=0x17,chassis=29,id=pci.29,bus=pci.5,addr=0x17 \ +-device xio3130-downstream,port=0x18,chassis=30,id=pci.30,bus=pci.5,addr=0x18 \ +-device xio3130-downstream,port=0x19,chassis=31,id=pci.31,bus=pci.5,addr=0x19 \ +-device xio3130-downstream,port=0x1a,chassis=32,id=pci.32,bus=pci.5,addr=0x1a \ +-device xio3130-downstream,port=0x1b,chassis=33,id=pci.33,bus=pci.5,addr=0x1b \ +-device xio3130-downstream,port=0x1c,chassis=34,id=pci.34,bus=pci.5,addr=0x1c \ +-device xio3130-downstream,port=0x1d,chassis=35,id=pci.35,bus=pci.5,addr=0x1d \ +-device xio3130-downstream,port=0x1e,chassis=36,id=pci.36,bus=pci.5,addr=0x1e \ +-device xio3130-downstream,port=0x1f,chassis=37,id=pci.37,bus=pci.5,addr=0x1f \ +-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-sata0-0-0 \ +-device ide-drive,bus=ide.0,drive=drive-sata0-0-0,id=sata0-0-0 \ +-device rtl8139,vlan=0,id=net0,mac=52:54:00:f1:95:51,bus=pci.6,addr=0x0 \ +-net user,vlan=0,name=hostnet0 \ +-device e1000,vlan=1,id=net1,mac=52:54:00:5c:c6:1a,bus=pci.7,addr=0x0 \ +-net user,vlan=1,name=hostnet1 \ +-device e1000,vlan=2,id=net2,mac=52:54:00:39:97:ac,bus=pci.8,addr=0x0 \ +-net user,vlan=2,name=hostnet2 \ +-device e1000,vlan=3,id=net3,mac=52:54:00:ee:b9:a8,bus=pci.9,addr=0x0 \ +-net user,vlan=3,name=hostnet3 \ +-device e1000,vlan=4,id=net4,mac=52:54:00:a9:f7:17,bus=pci.10,addr=0x0 \ +-net user,vlan=4,name=hostnet4 \ +-device e1000,vlan=5,id=net5,mac=52:54:00:df:2b:f3,bus=pci.11,addr=0x0 \ +-net user,vlan=5,name=hostnet5 \ +-device e1000,vlan=6,id=net6,mac=52:54:00:78:94:b4,bus=pci.12,addr=0x0 \ +-net user,vlan=6,name=hostnet6 \ +-device e1000,vlan=7,id=net7,mac=52:54:00:6b:9b:06,bus=pci.13,addr=0x0 \ +-net user,vlan=7,name=hostnet7 \ +-device e1000,vlan=8,id=net8,mac=52:54:00:17:df:bc,bus=pci.14,addr=0x0 \ +-net user,vlan=8,name=hostnet8 \ +-device e1000,vlan=9,id=net9,mac=52:54:00:3b:d0:51,bus=pci.15,addr=0x0 \ +-net user,vlan=9,name=hostnet9 \ +-device e1000,vlan=10,id=net10,mac=52:54:00:8d:2d:17,bus=pci.16,addr=0x0 \ +-net user,vlan=10,name=hostnet10 \ +-device e1000,vlan=11,id=net11,mac=52:54:00:a7:66:af,bus=pci.17,addr=0x0 \ +-net user,vlan=11,name=hostnet11 \ +-device e1000,vlan=12,id=net12,mac=52:54:00:54:ab:d7,bus=pci.18,addr=0x0 \ +-net user,vlan=12,name=hostnet12 \ +-device e1000,vlan=13,id=net13,mac=52:54:00:1f:99:90,bus=pci.19,addr=0x0 \ +-net user,vlan=13,name=hostnet13 \ +-device e1000,vlan=14,id=net14,mac=52:54:00:c8:43:87,bus=pci.20,addr=0x0 \ +-net user,vlan=14,name=hostnet14 \ +-device e1000,vlan=15,id=net15,mac=52:54:00:df:22:b2,bus=pci.21,addr=0x0 \ +-net user,vlan=15,name=hostnet15 \ +-device e1000,vlan=16,id=net16,mac=52:54:00:d2:9a:47,bus=pci.22,addr=0x0 \ +-net user,vlan=16,name=hostnet16 \ +-device e1000,vlan=17,id=net17,mac=52:54:00:86:05:e2,bus=pci.23,addr=0x0 \ +-net user,vlan=17,name=hostnet17 \ +-device e1000,vlan=18,id=net18,mac=52:54:00:8c:1c:c2,bus=pci.24,addr=0x0 \ +-net user,vlan=18,name=hostnet18 \ +-device e1000,vlan=19,id=net19,mac=52:54:00:48:58:92,bus=pci.25,addr=0x0 \ +-net user,vlan=19,name=hostnet19 \ +-device e1000,vlan=20,id=net20,mac=52:54:00:99:e5:bf,bus=pci.26,addr=0x0 \ +-net user,vlan=20,name=hostnet20 \ +-device e1000,vlan=21,id=net21,mac=52:54:00:b1:8c:25,bus=pci.27,addr=0x0 \ +-net user,vlan=21,name=hostnet21 \ +-device e1000,vlan=22,id=net22,mac=52:54:00:60:e0:d0,bus=pci.28,addr=0x0 \ +-net user,vlan=22,name=hostnet22 \ +-device e1000,vlan=23,id=net23,mac=52:54:00:37:00:6a,bus=pci.29,addr=0x0 \ +-net user,vlan=23,name=hostnet23 \ +-device e1000,vlan=24,id=net24,mac=52:54:00:c7:c8:ad,bus=pci.30,addr=0x0 \ +-net user,vlan=24,name=hostnet24 \ +-device e1000,vlan=25,id=net25,mac=52:54:00:4e:a7:cf,bus=pci.31,addr=0x0 \ +-net user,vlan=25,name=hostnet25 \ +-device e1000,vlan=26,id=net26,mac=52:54:00:00:79:69,bus=pci.32,addr=0x0 \ +-net user,vlan=26,name=hostnet26 \ +-device e1000,vlan=27,id=net27,mac=52:54:00:47:00:6f,bus=pci.33,addr=0x0 \ +-net user,vlan=27,name=hostnet27 \ +-device e1000,vlan=28,id=net28,mac=52:54:00:2a:8c:8b,bus=pci.34,addr=0x0 \ +-net user,vlan=28,name=hostnet28 \ +-device e1000,vlan=29,id=net29,mac=52:54:00:ec:d5:e3,bus=pci.35,addr=0x0 \ +-net user,vlan=29,name=hostnet29 \ +-device e1000,vlan=30,id=net30,mac=52:54:00:7e:6e:c8,bus=pci.36,addr=0x0 \ +-net user,vlan=30,name=hostnet30 \ +-device e1000,vlan=31,id=net31,mac=52:54:00:7e:6d:c9,bus=pci.37,addr=0x0 \ +-net user,vlan=31,name=hostnet31 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 65be98f..7b62511 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1590,6 +1590,21 @@ mymain(void) QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_PXB); + DO_TEST("pcie-expander-bus", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_X3130_UPSTREAM, + QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM, + QEMU_CAPS_DEVICE_PXB_PCIE); + DO_TEST_PARSE_ERROR("pcie-expander-bus-bad-machine", + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_DEVICE_X3130_UPSTREAM, + QEMU_CAPS_DEVICE_XIO3130_DOWNSTREAM, + QEMU_CAPS_DEVICE_PXB_PCIE); + DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_DEVICE_SCSI_GENERIC); -- 2.5.5

On 24.03.2016 20:25, Laine Stump wrote:
These two controllers are used to create a new root bus on a 440fx (pxb) or q35 (pxb-pie) virtual machine. There may be other use cases, but the main reason for me taking the time to support a separate root bus is to have assigned devices be visible in the guest on a different NUMA node, so that the guest can be aware of the locality of the device wrt CPU and memory that are on different NUMA nodes - although you aren't required to, you can add a <node>N</node> subelement to the bus' <target> element to indicate which NUMA node it is on (it's up to the management application to place devices on that bus that really are on the given NUMA node in the host).
There are several differences between pxb and pxb-pcie, which are detailed in the individual commit log messages, but in short:
1) pxb is for 440fx, pxb-pcie for q35 (they *might* work on other arches/machinetypes that have a PCI or PCIe bus, but I haven't enabled that)
2) pxb has an integrate d pci-bridge with 32 slots that are (should be) hotplug-capable, while pxb-pcie supplies only a single slot, and it will only accept a pcie-root-port (which will then accept a single device, hotplug-capable) or a pcie-switch-upstream-port.
Along the way I encountered a few minor problems/ugliness that I took care of in patches 01/15 - 09/15. pxb support is in 10-12, and pxb-pcie is in 13-15
There is a bugzilla record associated with this:
https://bugzilla.redhat.com/show_bug.cgi?id=1103314
Laine Stump (15): schema: make pci slot and function optional schema: rename uint8range/uint24range to uint8/uint24 schema: new basic type - uint16 schema: allow pci address attributes to be in decimal conf: use #define instead of literal for highest slot in upstream port conf: allow use of slot 0 in a dmi-to-pci-bridge conf/qemu: change the way VIR_PCI_CONNECT_TYPE_* flags work conf: utility function to convert PCI controller model into connect type qemu: set PCI controller default modelName in a separate function qemu: add capabilities bit for device "pxb" conf: new pci controller model pci-expander-bus qemu: support new pci controller model "pci-expander-bus" qemu: add capabilities bit for device "pxb-pcie" conf: new pci controller model pcie-expander-bus qemu: support new pci controller model "pcie-expander-bus"
docs/formatdomain.html.in | 74 +++- docs/schemas/basictypes.rng | 63 ++-- docs/schemas/domaincommon.rng | 23 +- docs/schemas/networkcommon.rng | 12 +- docs/schemas/nwfilter.rng | 16 +- src/bhyve/bhyve_device.c | 10 +- src/conf/domain_addr.c | 119 +++++-- src/conf/domain_addr.h | 68 ++-- src/conf/domain_conf.c | 61 +++- src/conf/domain_conf.h | 11 +- src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 74 ++++ src/qemu/qemu_domain.c | 42 +++ src/qemu/qemu_domain_address.c | 305 +++++++++------- tests/qemucapabilitiesdata/caps_2.4.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.5.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 2 + tests/qemucapabilitiesdata/caps_2.6.0-1.replies | 3 + .../qemuxml2argv-aarch64-virtio-pci-default.args | 2 +- ...l2argv-aarch64-virtio-pci-manual-addresses.args | 2 +- .../qemuxml2argv-pci-expander-bus-bad-machine.xml | 167 +++++++++ .../qemuxml2argv-pci-expander-bus-bad-node.xml | 160 +++++++++ .../qemuxml2argv-pci-expander-bus.args | 87 +++++ .../qemuxml2argv-pci-expander-bus.xml | 167 +++++++++ .../qemuxml2argv-pcie-expander-bus-bad-machine.xml | 36 ++ .../qemuxml2argv-pcie-expander-bus.args | 123 +++++++ .../qemuxml2argv-pcie-expander-bus.xml | 247 +++++++++++++ .../qemuxml2argv-pcie-root-port.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 2 +- .../qemuxml2argv-pcie-switch-downstream-port.args | 2 +- .../qemuxml2argv-pcie-switch-upstream-port.args | 2 +- .../qemuxml2argv-pcihole64-q35.args | 2 +- .../qemuxml2argv-q35-pm-disable-fallback.args | 2 +- .../qemuxml2argv-q35-pm-disable.args | 2 +- .../qemuxml2argv-q35-usb2-multi.args | 2 +- .../qemuxml2argv-q35-usb2-reorder.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +- .../qemuxml2argv-usb-controller-default-q35.args | 2 +- .../qemuxml2argv-usb-controller-explicit-q35.args | 2 +- tests/qemuxml2argvtest.c | 25 ++ .../qemuxml2xmlout-aarch64-virtio-pci-default.xml | 2 +- ...2xmlout-aarch64-virtio-pci-manual-addresses.xml | 2 +- .../qemuxml2xmlout-pci-expander-bus.xml | 207 +++++++++++ .../qemuxml2xmlout-pcie-expander-bus.xml | 384 +++++++++++++++++++++ .../qemuxml2xmlout-pcie-root-port.xml | 2 +- .../qemuxml2xmlout-pcie-root.xml | 2 +- .../qemuxml2xmlout-pcie-switch-downstream-port.xml | 2 +- .../qemuxml2xmlout-pcie-switch-upstream-port.xml | 2 +- .../qemuxml2xmlout-pcihole64-q35.xml | 2 +- .../qemuxml2xmlout-q35-usb2-multi.xml | 2 +- .../qemuxml2xmlout-q35-usb2-reorder.xml | 2 +- .../qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml | 2 +- tests/qemuxml2xmltest.c | 10 + 57 files changed, 2296 insertions(+), 261 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml
ACK series. Unfortunately, this is after the freeze. So to obey the process we should not push this. But we broke the rule here and there. What's your opinion? Michal

On 03/30/2016 05:05 AM, Michal Privoznik wrote:
On 24.03.2016 20:25, Laine Stump wrote:
These two controllers are used to create a new root bus on a 440fx (pxb) or q35 (pxb-pie) virtual machine. There may be other use cases, but the main reason for me taking the time to support a separate root bus is to have assigned devices be visible in the guest on a different NUMA node, so that the guest can be aware of the locality of the device wrt CPU and memory that are on different NUMA nodes - although you aren't required to, you can add a <node>N</node> subelement to the bus' <target> element to indicate which NUMA node it is on (it's up to the management application to place devices on that bus that really are on the given NUMA node in the host).
There are several differences between pxb and pxb-pcie, which are detailed in the individual commit log messages, but in short:
1) pxb is for 440fx, pxb-pcie for q35 (they *might* work on other arches/machinetypes that have a PCI or PCIe bus, but I haven't enabled that)
2) pxb has an integrate d pci-bridge with 32 slots that are (should be) hotplug-capable, while pxb-pcie supplies only a single slot, and it will only accept a pcie-root-port (which will then accept a single device, hotplug-capable) or a pcie-switch-upstream-port.
Along the way I encountered a few minor problems/ugliness that I took care of in patches 01/15 - 09/15. pxb support is in 10-12, and pxb-pcie is in 13-15
There is a bugzilla record associated with this:
https://bugzilla.redhat.com/show_bug.cgi?id=1103314
Laine Stump (15): schema: make pci slot and function optional schema: rename uint8range/uint24range to uint8/uint24 schema: new basic type - uint16 schema: allow pci address attributes to be in decimal conf: use #define instead of literal for highest slot in upstream port conf: allow use of slot 0 in a dmi-to-pci-bridge conf/qemu: change the way VIR_PCI_CONNECT_TYPE_* flags work conf: utility function to convert PCI controller model into connect type qemu: set PCI controller default modelName in a separate function qemu: add capabilities bit for device "pxb" conf: new pci controller model pci-expander-bus qemu: support new pci controller model "pci-expander-bus" qemu: add capabilities bit for device "pxb-pcie" conf: new pci controller model pcie-expander-bus qemu: support new pci controller model "pcie-expander-bus"
docs/formatdomain.html.in | 74 +++- docs/schemas/basictypes.rng | 63 ++-- docs/schemas/domaincommon.rng | 23 +- docs/schemas/networkcommon.rng | 12 +- docs/schemas/nwfilter.rng | 16 +- src/bhyve/bhyve_device.c | 10 +- src/conf/domain_addr.c | 119 +++++-- src/conf/domain_addr.h | 68 ++-- src/conf/domain_conf.c | 61 +++- src/conf/domain_conf.h | 11 +- src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 74 ++++ src/qemu/qemu_domain.c | 42 +++ src/qemu/qemu_domain_address.c | 305 +++++++++------- tests/qemucapabilitiesdata/caps_2.4.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.5.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 2 + tests/qemucapabilitiesdata/caps_2.6.0-1.replies | 3 + .../qemuxml2argv-aarch64-virtio-pci-default.args | 2 +- ...l2argv-aarch64-virtio-pci-manual-addresses.args | 2 +- .../qemuxml2argv-pci-expander-bus-bad-machine.xml | 167 +++++++++ .../qemuxml2argv-pci-expander-bus-bad-node.xml | 160 +++++++++ .../qemuxml2argv-pci-expander-bus.args | 87 +++++ .../qemuxml2argv-pci-expander-bus.xml | 167 +++++++++ .../qemuxml2argv-pcie-expander-bus-bad-machine.xml | 36 ++ .../qemuxml2argv-pcie-expander-bus.args | 123 +++++++ .../qemuxml2argv-pcie-expander-bus.xml | 247 +++++++++++++ .../qemuxml2argv-pcie-root-port.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 2 +- .../qemuxml2argv-pcie-switch-downstream-port.args | 2 +- .../qemuxml2argv-pcie-switch-upstream-port.args | 2 +- .../qemuxml2argv-pcihole64-q35.args | 2 +- .../qemuxml2argv-q35-pm-disable-fallback.args | 2 +- .../qemuxml2argv-q35-pm-disable.args | 2 +- .../qemuxml2argv-q35-usb2-multi.args | 2 +- .../qemuxml2argv-q35-usb2-reorder.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +- .../qemuxml2argv-usb-controller-default-q35.args | 2 +- .../qemuxml2argv-usb-controller-explicit-q35.args | 2 +- tests/qemuxml2argvtest.c | 25 ++ .../qemuxml2xmlout-aarch64-virtio-pci-default.xml | 2 +- ...2xmlout-aarch64-virtio-pci-manual-addresses.xml | 2 +- .../qemuxml2xmlout-pci-expander-bus.xml | 207 +++++++++++ .../qemuxml2xmlout-pcie-expander-bus.xml | 384 +++++++++++++++++++++ .../qemuxml2xmlout-pcie-root-port.xml | 2 +- .../qemuxml2xmlout-pcie-root.xml | 2 +- .../qemuxml2xmlout-pcie-switch-downstream-port.xml | 2 +- .../qemuxml2xmlout-pcie-switch-upstream-port.xml | 2 +- .../qemuxml2xmlout-pcihole64-q35.xml | 2 +- .../qemuxml2xmlout-q35-usb2-multi.xml | 2 +- .../qemuxml2xmlout-q35-usb2-reorder.xml | 2 +- .../qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml | 2 +- tests/qemuxml2xmltest.c | 10 + 57 files changed, 2296 insertions(+), 261 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml
ACK series.
Unfortunately, this is after the freeze. So to obey the process we should not push this. But we broke the rule here and there. What's your opinion?
I mainly want to push it just to get it off my to-do list; there isn't any pressing schedule need for it. So rather than risk the embarrassment of a regression right before a release, I'll wait and push it after the release. Thanks for the review!

On 30.03.2016 16:48, Laine Stump wrote:
On 03/30/2016 05:05 AM, Michal Privoznik wrote:
On 24.03.2016 20:25, Laine Stump wrote:
These two controllers are used to create a new root bus on a 440fx (pxb) or q35 (pxb-pie) virtual machine. There may be other use cases, but the main reason for me taking the time to support a separate root bus is to have assigned devices be visible in the guest on a different NUMA node, so that the guest can be aware of the locality of the device wrt CPU and memory that are on different NUMA nodes - although you aren't required to, you can add a <node>N</node> subelement to the bus' <target> element to indicate which NUMA node it is on (it's up to the management application to place devices on that bus that really are on the given NUMA node in the host).
There are several differences between pxb and pxb-pcie, which are detailed in the individual commit log messages, but in short:
1) pxb is for 440fx, pxb-pcie for q35 (they *might* work on other arches/machinetypes that have a PCI or PCIe bus, but I haven't enabled that)
2) pxb has an integrate d pci-bridge with 32 slots that are (should be) hotplug-capable, while pxb-pcie supplies only a single slot, and it will only accept a pcie-root-port (which will then accept a single device, hotplug-capable) or a pcie-switch-upstream-port.
Along the way I encountered a few minor problems/ugliness that I took care of in patches 01/15 - 09/15. pxb support is in 10-12, and pxb-pcie is in 13-15
There is a bugzilla record associated with this:
https://bugzilla.redhat.com/show_bug.cgi?id=1103314
Laine Stump (15): schema: make pci slot and function optional schema: rename uint8range/uint24range to uint8/uint24 schema: new basic type - uint16 schema: allow pci address attributes to be in decimal conf: use #define instead of literal for highest slot in upstream port conf: allow use of slot 0 in a dmi-to-pci-bridge conf/qemu: change the way VIR_PCI_CONNECT_TYPE_* flags work conf: utility function to convert PCI controller model into connect type qemu: set PCI controller default modelName in a separate function qemu: add capabilities bit for device "pxb" conf: new pci controller model pci-expander-bus qemu: support new pci controller model "pci-expander-bus" qemu: add capabilities bit for device "pxb-pcie" conf: new pci controller model pcie-expander-bus qemu: support new pci controller model "pcie-expander-bus"
docs/formatdomain.html.in | 74 +++- docs/schemas/basictypes.rng | 63 ++-- docs/schemas/domaincommon.rng | 23 +- docs/schemas/networkcommon.rng | 12 +- docs/schemas/nwfilter.rng | 16 +- src/bhyve/bhyve_device.c | 10 +- src/conf/domain_addr.c | 119 +++++-- src/conf/domain_addr.h | 68 ++-- src/conf/domain_conf.c | 61 +++- src/conf/domain_conf.h | 11 +- src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 74 ++++ src/qemu/qemu_domain.c | 42 +++ src/qemu/qemu_domain_address.c | 305 +++++++++------- tests/qemucapabilitiesdata/caps_2.4.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.5.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_2.6.0-1.caps | 2 + tests/qemucapabilitiesdata/caps_2.6.0-1.replies | 3 + .../qemuxml2argv-aarch64-virtio-pci-default.args | 2 +- ...l2argv-aarch64-virtio-pci-manual-addresses.args | 2 +- .../qemuxml2argv-pci-expander-bus-bad-machine.xml | 167 +++++++++ .../qemuxml2argv-pci-expander-bus-bad-node.xml | 160 +++++++++ .../qemuxml2argv-pci-expander-bus.args | 87 +++++ .../qemuxml2argv-pci-expander-bus.xml | 167 +++++++++ .../qemuxml2argv-pcie-expander-bus-bad-machine.xml | 36 ++ .../qemuxml2argv-pcie-expander-bus.args | 123 +++++++ .../qemuxml2argv-pcie-expander-bus.xml | 247 +++++++++++++ .../qemuxml2argv-pcie-root-port.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args | 2 +- .../qemuxml2argv-pcie-switch-downstream-port.args | 2 +- .../qemuxml2argv-pcie-switch-upstream-port.args | 2 +- .../qemuxml2argv-pcihole64-q35.args | 2 +- .../qemuxml2argv-q35-pm-disable-fallback.args | 2 +- .../qemuxml2argv-q35-pm-disable.args | 2 +- .../qemuxml2argv-q35-usb2-multi.args | 2 +- .../qemuxml2argv-q35-usb2-reorder.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35-usb2.args | 2 +- tests/qemuxml2argvdata/qemuxml2argv-q35.args | 2 +- .../qemuxml2argv-usb-controller-default-q35.args | 2 +- .../qemuxml2argv-usb-controller-explicit-q35.args | 2 +- tests/qemuxml2argvtest.c | 25 ++ .../qemuxml2xmlout-aarch64-virtio-pci-default.xml | 2 +- ...2xmlout-aarch64-virtio-pci-manual-addresses.xml | 2 +- .../qemuxml2xmlout-pci-expander-bus.xml | 207 +++++++++++ .../qemuxml2xmlout-pcie-expander-bus.xml | 384 +++++++++++++++++++++ .../qemuxml2xmlout-pcie-root-port.xml | 2 +- .../qemuxml2xmlout-pcie-root.xml | 2 +- .../qemuxml2xmlout-pcie-switch-downstream-port.xml | 2 +- .../qemuxml2xmlout-pcie-switch-upstream-port.xml | 2 +- .../qemuxml2xmlout-pcihole64-q35.xml | 2 +- .../qemuxml2xmlout-q35-usb2-multi.xml | 2 +- .../qemuxml2xmlout-q35-usb2-reorder.xml | 2 +- .../qemuxml2xmloutdata/qemuxml2xmlout-q35-usb2.xml | 2 +- tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml | 2 +- tests/qemuxml2xmltest.c | 10 + 57 files changed, 2296 insertions(+), 261 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus-bad-node.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-expander-bus.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus-bad-machine.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-expander-bus.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-expander-bus.xml
ACK series.
Unfortunately, this is after the freeze. So to obey the process we should not push this. But we broke the rule here and there. What's your opinion?
I mainly want to push it just to get it off my to-do list; there isn't any pressing schedule need for it. So rather than risk the embarrassment of a regression right before a release, I'll wait and push it after the release.
Thanks for the review!
Okay. I'm terribly sorry for the review lag. Michal
participants (3)
-
Ján Tomko
-
Laine Stump
-
Michal Privoznik