Add API for issuing 'pci_add host' monitor command

* 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
This commit is contained in:
Daniel P. Berrange 2009-09-23 16:15:51 +01:00
parent 61ea9c89c5
commit e7f38d96f0
3 changed files with 140 additions and 38 deletions

View File

@ -4903,8 +4903,6 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
virDomainDeviceDefPtr dev) virDomainDeviceDefPtr dev)
{ {
virDomainHostdevDefPtr hostdev = dev->data.hostdev; virDomainHostdevDefPtr hostdev = dev->data.hostdev;
char *cmd, *reply;
unsigned domain, bus, slot;
pciDevice *pci; pciDevice *pci;
if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) { if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
@ -4931,51 +4929,23 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
return -1; return -1;
} }
cmd = reply = NULL; if (qemuMonitorAddPCIHostDevice(vm,
hostdev->source.subsys.u.pci.domain,
if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x", hostdev->source.subsys.u.pci.bus,
hostdev->source.subsys.u.pci.bus, hostdev->source.subsys.u.pci.slot,
hostdev->source.subsys.u.pci.slot, hostdev->source.subsys.u.pci.function,
hostdev->source.subsys.u.pci.function) < 0) { &hostdev->source.subsys.u.pci.guest_addr.domain,
virReportOOMError(conn); &hostdev->source.subsys.u.pci.guest_addr.bus,
&hostdev->source.subsys.u.pci.guest_addr.slot) < 0)
goto error; goto error;
}
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("cannot attach host pci device"));
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; vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
VIR_FREE(reply);
VIR_FREE(cmd);
return 0; return 0;
error: error:
pciDeviceListDel(conn, driver->activePciHostdevs, pci); pciDeviceListDel(conn, driver->activePciHostdevs, pci);
VIR_FREE(reply);
VIR_FREE(cmd);
return -1; return -1;
} }

View File

@ -1315,3 +1315,124 @@ int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm,
VIR_FREE(addr); VIR_FREE(addr);
return ret; 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;
}

View File

@ -147,4 +147,15 @@ int qemuMonitorAddUSBDeviceMatch(const virDomainObjPtr vm,
int vendor, int vendor,
int product); 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 */ #endif /* QEMU_MONITOR_TEXT_H */