* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add new API qemuMonitorAddPCIHostDevice() * src/qemu/qemu_driver.c: Switch to using qemuMonitorAddPCIHostDevice() for PCI host device hotplug --- src/qemu/qemu_driver.c | 46 +++------------- src/qemu/qemu_monitor_text.c | 121 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_text.h | 11 ++++ 3 files changed, 140 insertions(+), 38 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f33c24e..e9e7543 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4903,8 +4903,6 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn, virDomainDeviceDefPtr dev) { virDomainHostdevDefPtr hostdev = dev->data.hostdev; - char *cmd, *reply; - unsigned domain, bus, slot; pciDevice *pci; if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) { @@ -4931,51 +4929,23 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn, return -1; } - cmd = reply = NULL; - - if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x", - hostdev->source.subsys.u.pci.bus, - hostdev->source.subsys.u.pci.slot, - hostdev->source.subsys.u.pci.function) < 0) { - virReportOOMError(conn); - goto error; - } - - if (qemudMonitorCommand(vm, cmd, &reply) < 0) { - qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - "%s", _("cannot attach host pci device")); + if (qemuMonitorAddPCIHostDevice(vm, + hostdev->source.subsys.u.pci.domain, + hostdev->source.subsys.u.pci.bus, + hostdev->source.subsys.u.pci.slot, + hostdev->source.subsys.u.pci.function, + &hostdev->source.subsys.u.pci.guest_addr.domain, + &hostdev->source.subsys.u.pci.guest_addr.bus, + &hostdev->source.subsys.u.pci.guest_addr.slot) < 0) goto error; - } - - if (strstr(reply, "invalid type: host")) { - qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", - _("PCI device assignment is not supported by this version of qemu")); - goto error; - } - - if (qemudParsePciAddReply(vm, reply, &domain, &bus, &slot) < 0) { - qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - _("parsing pci_add reply failed: %s"), reply); - goto error; - } - - hostdev->source.subsys.u.pci.guest_addr.domain = domain; - hostdev->source.subsys.u.pci.guest_addr.bus = bus; - hostdev->source.subsys.u.pci.guest_addr.slot = slot; vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; - VIR_FREE(reply); - VIR_FREE(cmd); - return 0; error: pciDeviceListDel(conn, driver->activePciHostdevs, pci); - VIR_FREE(reply); - VIR_FREE(cmd); - return -1; } diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index 0e0334c..ca84fc6 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1315,3 +1315,124 @@ int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm, VIR_FREE(addr); return ret; } + + +static int +qemuMonitorParsePciAddReply(virDomainObjPtr vm, + const char *reply, + unsigned *domain, + unsigned *bus, + unsigned *slot) +{ + char *s, *e; + + DEBUG("%s: pci_add reply: %s", vm->def->name, reply); + + /* If the command succeeds qemu prints: + * OK bus 0, slot XXX... + * or + * OK domain 0, bus 0, slot XXX + */ + if (!(s = strstr(reply, "OK "))) + return -1; + + s += 3; + + if (STRPREFIX(s, "domain ")) { + s += strlen("domain "); + + if (virStrToLong_ui(s, &e, 10, domain) == -1) { + VIR_WARN(_("Unable to parse domain number '%s'\n"), s); + return -1; + } + + if (!STRPREFIX(e, ", ")) { + VIR_WARN(_("Expected ', ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s = e + 2; + } + + if (!STRPREFIX(s, "bus ")) { + VIR_WARN(_("Expected 'bus ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s += strlen("bus "); + + if (virStrToLong_ui(s, &e, 10, bus) == -1) { + VIR_WARN(_("Unable to parse bus number '%s'\n"), s); + return -1; + } + + if (!STRPREFIX(e, ", ")) { + VIR_WARN(_("Expected ', ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s = e + 2; + + if (!STRPREFIX(s, "slot ")) { + VIR_WARN(_("Expected 'slot ' parsing pci_add reply '%s'\n"), s); + return -1; + } + s += strlen("slot "); + + if (virStrToLong_ui(s, &e, 10, slot) == -1) { + VIR_WARN(_("Unable to parse slot number '%s'\n"), s); + return -1; + } + + return 0; +} + + +int qemuMonitorAddPCIHostDevice(const virDomainObjPtr vm, + unsigned hostDomain ATTRIBUTE_UNUSED, + unsigned hostBus, + unsigned hostSlot, + unsigned hostFunction, + unsigned *guestDomain, + unsigned *guestBus, + unsigned *guestSlot) +{ + char *cmd; + char *reply = NULL; + int ret = -1; + + *guestDomain = *guestBus = *guestSlot = 0; + + /* XXX hostDomain */ + if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x", + hostBus, hostSlot, hostFunction) < 0) { + virReportOOMError(NULL); + goto cleanup; + } + + if (qemudMonitorCommand(vm, cmd, &reply) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("cannot attach host pci device")); + goto cleanup; + } + + if (strstr(reply, "invalid type: host")) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s", + _("PCI device assignment is not supported by this version of qemu")); + goto cleanup; + } + + if (qemuMonitorParsePciAddReply(vm, reply, + guestDomain, + guestBus, + guestSlot) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("parsing pci_add reply failed: %s"), reply); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(cmd); + VIR_FREE(reply); + return ret; +} + diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h index 4153090..0e1b27b 100644 --- a/src/qemu/qemu_monitor_text.h +++ b/src/qemu/qemu_monitor_text.h @@ -147,4 +147,15 @@ int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm, int vendor, int product); + +int qemuMonitorAddPCIHostDevice(const virDomainObjPtr vm, + unsigned hostDomain, + unsigned hostBus, + unsigned hostSlot, + unsigned hostFunction, + unsigned *guestDomain, + unsigned *guestBus, + unsigned *guestSlot); + + #endif /* QEMU_MONITOR_TEXT_H */ -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list