mirror of https://gitee.com/openkylin/libvirt.git
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:
parent
61ea9c89c5
commit
e7f38d96f0
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue