如果是Q35,PCIeRoot 默认就是 true。
修改machine=q35 <type arch='x86_64' machine='pc-q35-2.6'>hvm</type>
报如下错:
error: XML error: The PCI controller with index='0' must be model='pcie-root' for this machine type, but model='pci-root' was found instead
于是查看代码:
查找Controller,从def里的controllers里查找出符合 type和idx 的Controller的位置
int
virDomainControllerFind(const virDomainDef *def,
int type,
int idx)
{
size_t i;
for (i = 0; i < def->ncontrollers; i++) {
if ((def->controllers[i]->type == type) &&
(def->controllers[i]->idx == idx)) {
return i;
}
}
return -1;
}
pciRoot = virDomainControllerFind(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0); 查找VIR_DOMAIN_CONTROLLER_TYPE_PCI,索引是0的Controller
/* NB: any machine that sets addPCIRoot to true must also return
* true from the function qemuDomainSupportsPCI().
*/
if (addPCIRoot) {
if (pciRoot >= 0) {
if (def->controllers[pciRoot]->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
virReportError(VIR_ERR_XML_ERROR,
_("The PCI controller with index='0' must be "
"model='pci-root' for this machine type, "
"but model='%s' was found instead"),
virDomainControllerModelPCITypeToString(def->controllers[pciRoot]->model));
goto cleanup;
}
} else if (!virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)) {
goto cleanup;
}
}
/* When a machine has a pcie-root, make sure that there is always
* a dmi-to-pci-bridge controller added as bus 1, and a pci-bridge
* as bus 2, so that standard PCI devices can be connected
*
* NB: any machine that sets addPCIeRoot to true must also return
* true from the function qemuDomainSupportsPCI().
*/
if (addPCIeRoot) { #从这里就有bug了,如果是PCIeRoot,结果用的是pciRoot的索引去查找控制器,这样肯定查找到的就不是真正的PCIE控制器
if (pciRoot >= 0) {
if (def->controllers[pciRoot]->model != VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) { 大致判断在这里,如果这里pci的controller的model如果不是PCIE_ROOT 就会报错
virReportError(VIR_ERR_XML_ERROR,
_("The PCI controller with index='0' must be "
"model='pcie-root' for this machine type, "
"but model='%s' was found instead"),
virDomainControllerModelPCITypeToString(def->controllers[pciRoot]->model));
goto cleanup;
}
} else if (!virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)) {
goto cleanup;
}
/* Add a dmi-to-pci-bridge bridge if there are no PCI controllers
* other than the pcie-root. This is so that there will be hot-pluggable
* PCI slots available.
*
* We skip this step for aarch64 mach-virt guests, where we want to
* be able to have a pure virtio-mmio topology
*/
if (virDomainControllerFind(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1) < 0 &&
!qemuDomainMachineIsVirt(def) &&
!virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1,
VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE))
goto cleanup;
}
从以上代码分析,于是修改xml文件, 把pci的controller修改为 pcie-root
<controller type='pci' index='0' model='pci-root'/> 改为 <controller type='pci' index='0' model='pcie-root'/>
保存后,还是报错,不过这次报错和上次不同,报如下错:
error: internal error: Bus 0 must be PCI for integrated PIIX3 USB or IDE controllers
if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER && addr->domain == 0 &&
addr->bus == 0 && addr->slot == 1) {
virDomainControllerDefPtr cont = device->data.controller;
if ((cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && cont->idx == 0 &&
addr->function == 1) ||
(cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->idx == 0 && USB类型的controoler
(cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI || 如果是PIIX3_UHCI就会进入下面的判断
cont->model == -1) && addr->function == 2)) { 从以上条件可以看出如果是 PIIX3_UHCI 的USB基本会进入下面的代码
/* Note the check for nbuses > 0 - if there are no PCI
* buses, we skip this check. This is a quirk required for
* some machinetypes such as s390, which pretend to have a
* PCI bus for long enough to generate the "-usb" on the
* 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_DEVICE)) { 总线类型, 基本就是如果不是PIC的设置,基本就会进入报错
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Bus 0 must be PCI for integrated PIIX3 "
"USB or IDE controllers"));
return -1;
} else {
return 0;
}
}
}
从以上代码可以得出结论:
如果是PIIX3的必须是PCI设置,这个就很奇怪了,所以把 usb controller改成其它的,比如PIIX4、 ICH9就可以了
PIIX3_UHCI,
PIIX4_UHCI,
EHCI,
ICH9_EHCI1,
ICH9_UHCI1,
ICH9_UHCI2,
ICH9_UHCI3,
VT82C686B_UHCI,
PCI_OHCI,
NEC_XHCI,
NONE,
<controller type='usb' index='0' model='piix4-uhci'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
感觉是个bug, 难道PIIX3就只能是 PCI ,不能是PCIE?