conf: Introduce @memReserve to <controller/>

There are PCI devices with pretty large non-prefetchable memory,
for instance:

  Memory at 9d800000 (64-bit, non-prefetchable) [size=8M]
  Memory at a6800000 (64-bit, non-prefetchable) [size=16K]

For cold plugged devices this is not a problem, because firmware
sets PCI controllers in a way that make devices behind them just
work. Problem arises if such PCI device is to be hot plugged.
Since the PCI device wasn't present at cold boot, firmware could
not take it into calculations and the amount of reserved memory
is not sufficient.

Introduce a know that allows users overriding value computed by
FW and thus allow hot plug of such PCI devices.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
This commit is contained in:
Michal Privoznik 2023-09-11 14:33:18 +02:00
parent 753064963c
commit 05c256f51a
6 changed files with 25 additions and 2 deletions

View File

@ -4153,6 +4153,12 @@ generated by libvirt. :since:`Since 1.2.19 (QEMU only)`.
``index``
pci-root controllers for pSeries guests use this attribute to record the
order they will show up in the guest. :since:`Since 3.6.0`
``memReserve``
Some PCI devices have non-prefetchable memory bar larger than 2MiB. Use this
attribute to override value computed by firmware and thus make controller
reserve more memory (in KiB) so that such PCI device can be hot plugged.
For cold plugged PCI devices, the firmware will automatically reserve the
correct amount of memory. :since:`Since 10.3.0`
For machine types which provide an implicit PCI bus, the pci-root controller
with index=0 is auto-added and required to use PCI devices. pci-root has no

View File

@ -8528,6 +8528,11 @@ virDomainControllerDefParseXML(virDomainXMLOption *xmlopt,
&def->opts.pciopts.targetIndex,
def->opts.pciopts.targetIndex) < 0)
return NULL;
if (virXMLPropULongLong(targetNodes[0], "memReserve", 0,
VIR_XML_PROP_NONZERO,
&def->opts.pciopts.memReserve) < 0)
return NULL;
}
}
@ -23095,6 +23100,10 @@ virDomainControllerDefFormatPCI(virBuffer *buf,
virBufferAsprintf(&targetAttrBuf, " hotplug='%s'",
virTristateSwitchTypeToString(def->opts.pciopts.hotplug));
}
if (def->opts.pciopts.memReserve) {
virBufferAsprintf(&targetAttrBuf, " memReserve='%llu'",
def->opts.pciopts.memReserve);
}
if (def->opts.pciopts.numaNode != -1)
virBufferAsprintf(&targetChildBuf, "<node>%d</node>\n", def->opts.pciopts.numaNode);

View File

@ -738,6 +738,9 @@ struct _virDomainPCIControllerOpts {
*/
int numaNode;
virTristateSwitch hotplug; /* 'off' to prevent hotplug/unplug, default 'on' */
unsigned long long memReserve; /* used by pci-bridge and pcie-root-port,
0 == undef, KiB */
};
struct _virDomainUSBControllerOpts {

View File

@ -2897,6 +2897,11 @@
<ref name="unsignedInt"/>
</element>
</optional>
<optional>
<attribute name="memReserve">
<ref name="unsignedLong"/>
</attribute>
</optional>
</element>
</optional>
<!-- *-root controllers have an optional element "pcihole64"-->

View File

@ -30,7 +30,7 @@
</controller>
<controller type='pci' index='2' model='pci-bridge'>
<model name='pci-bridge'/>
<target chassisNr='56'/>
<target chassisNr='56' memReserve='8196'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</controller>
<controller type='usb' index='0' model='ich9-ehci1'>

View File

@ -25,7 +25,7 @@
</controller>
<controller type='pci' index='2' model='pci-bridge'>
<model name='pci-bridge'/>
<target chassisNr='56'/>
<target chassisNr='56' memReserve='8196'/>
</controller>
<controller type='usb' index='0' model='ich9-ehci1'/>
<controller type='usb' index='0' model='ich9-uhci1'/>