generated by libvirt. <span class="since">Since 1.2.19 (QEMU
only).</span>
</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
+ 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
+ to a controller, nor should you modify the values in the those
+ that are automatically generated by
+ libvirt. <span class="since">Since 1.2.19 (QEMU only).</span>
+ </p>
+ <dl>
+ <dt><code>chassisNr</code></dt>
+ <dd>
+ PCI controllers that have attribute model="pci-bridge", can
+ also have a <code>chassisNr</code> attribute in
+ the <code><target></code> subelement, which is used to
+ control QEMU's "chassis_nr" option for the pci-bridge device
+ (normally libvirt automatically sets this to the same value as
+ the index attribute of the pci controller). If set, chassisNr
+ must be between 0 and 255.
+ </dd>
+ </dl>
<p>
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.
def->opts.vioserial.vectors = -1;
break;
case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
+ def->opts.pciopts.chassisNr = -1;
+ break;
case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
char *max_sectors = NULL;
bool processedModel = false;
char *modelName = NULL;
+ bool processedTarget = false;
+ char *chassisNr = NULL;
xmlNodePtr saved = ctxt->node;
int rc;
}
modelName = virXMLPropString(cur, "name");
processedModel = true;
+ } else if (xmlStrEqual(cur->name, BAD_CAST "target")) {
+ if (processedTarget) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Multiple <target> elements in "
+ "controller definition not allowed"));
+ goto error;
+ }
+ chassisNr = virXMLPropString(cur, "chassisNr");
+ processedTarget = true;
}
}
cur = cur->next;
modelName);
goto error;
}
+ if (chassisNr) {
+ if (virStrToLong_i(chassisNr, NULL, 0,
+ &def->opts.pciopts.chassisNr) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid chassisNr '%s' in PCI controller"),
+ chassisNr);
+ goto error;
+ }
+ if (def->opts.pciopts.chassisNr < 0 ||
+ def->opts.pciopts.chassisNr > 255) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("PCI controller chassisNr '%s' out of range "
+ "- must be 0-255"),
+ chassisNr);
+ goto error;
+ }
+ }
break;
default:
VIR_FREE(cmd_per_lun);
VIR_FREE(max_sectors);
VIR_FREE(modelName);
+ VIR_FREE(chassisNr);
return def;
const char *type = virDomainControllerTypeToString(def->type);
const char *model = NULL;
const char *modelName = NULL;
- bool pcihole64 = false, pciModel = false;
+ bool pcihole64 = false, pciModel = false, pciTarget = false;
if (!type) {
virReportError(VIR_ERR_INTERNAL_ERROR,
pcihole64 = true;
if (def->opts.pciopts.modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
pciModel = true;
+ if (def->opts.pciopts.chassisNr != -1)
+ pciTarget = true;
break;
default:
break;
}
- if (pciModel ||
+ if (pciModel || pciTarget ||
def->queues || def->cmd_per_lun || def->max_sectors ||
virDomainDeviceInfoNeedsFormat(&def->info, flags) || pcihole64) {
virBufferAddLit(buf, ">\n");
virBufferAsprintf(buf, "<model name='%s'/>\n", modelName);
}
+ if (pciTarget) {
+ virBufferAddLit(buf, "<target");
+ if (def->opts.pciopts.chassisNr != -1)
+ virBufferAsprintf(buf, " chassisNr='%d'",
+ def->opts.pciopts.chassisNr);
+ virBufferAddLit(buf, "/>\n");
+ }
+
if (def->queues || def->cmd_per_lun || def->max_sectors) {
virBufferAddLit(buf, "<driver");
if (def->queues)