}
-int
-qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon,
- virDevicePCIAddress *hostAddr,
- virDevicePCIAddress *guestAddr)
-{
- VIR_DEBUG("domain=%d bus=%d slot=%d function=%d",
- hostAddr->domain, hostAddr->bus, hostAddr->slot, hostAddr->function);
-
- QEMU_CHECK_MONITOR(mon);
-
- if (mon->json)
- return qemuMonitorJSONAddPCIHostDevice(mon, hostAddr, guestAddr);
- else
- return qemuMonitorTextAddPCIHostDevice(mon, hostAddr, guestAddr);
-}
-
-
-int
-qemuMonitorAddPCIDisk(qemuMonitorPtr mon,
- const char *path,
- const char *bus,
- virDevicePCIAddress *guestAddr)
-{
- VIR_DEBUG("path=%s bus=%s", path, bus);
-
- QEMU_CHECK_MONITOR(mon);
-
- if (mon->json)
- return qemuMonitorJSONAddPCIDisk(mon, path, bus, guestAddr);
- else
- return qemuMonitorTextAddPCIDisk(mon, path, bus, guestAddr);
-}
-
-
-int
-qemuMonitorAddPCINetwork(qemuMonitorPtr mon,
- const char *nicstr,
- virDevicePCIAddress *guestAddr)
-{
- VIR_DEBUG("nicstr=%s", nicstr);
-
- QEMU_CHECK_MONITOR(mon);
-
- if (mon->json)
- return qemuMonitorJSONAddPCINetwork(mon, nicstr, guestAddr);
- else
- return qemuMonitorTextAddPCINetwork(mon, nicstr, guestAddr);
-}
-
-
-int
-qemuMonitorRemovePCIDevice(qemuMonitorPtr mon,
- virDevicePCIAddress *guestAddr)
-{
- VIR_DEBUG("domain=%d bus=%d slot=%d function=%d",
- guestAddr->domain, guestAddr->bus, guestAddr->slot,
- guestAddr->function);
-
- QEMU_CHECK_MONITOR(mon);
-
- if (mon->json)
- return qemuMonitorJSONRemovePCIDevice(mon, guestAddr);
- else
- return qemuMonitorTextRemovePCIDevice(mon, guestAddr);
-}
-
-
int
qemuMonitorSendFileHandle(qemuMonitorPtr mon,
const char *fdname,
}
-int
-qemuMonitorAttachPCIDiskController(qemuMonitorPtr mon,
- const char *bus,
- virDevicePCIAddress *guestAddr)
-{
- VIR_DEBUG("type=%s", bus);
-
- QEMU_CHECK_MONITOR(mon);
-
- if (mon->json)
- return qemuMonitorJSONAttachPCIDiskController(mon, bus, guestAddr);
- else
- return qemuMonitorTextAttachPCIDiskController(mon, bus, guestAddr);
-}
-
-
int
qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon,
qemuMonitorPCIAddress **addrs)
}
-int qemuMonitorJSONAddPCIHostDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
- virDevicePCIAddress *hostAddr ATTRIBUTE_UNUSED,
- virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("pci_add not supported in JSON mode"));
- return -1;
-}
-
-
-int qemuMonitorJSONAddPCIDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
- const char *path ATTRIBUTE_UNUSED,
- const char *bus ATTRIBUTE_UNUSED,
- virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("pci_add not supported in JSON mode"));
- return -1;
-}
-
-
-int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
- const char *nicstr ATTRIBUTE_UNUSED,
- virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("pci_add not supported in JSON mode"));
- return -1;
-}
-
-
-int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
- virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("pci_del not supported in JSON mode"));
- return -1;
-}
-
-
int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
const char *fdname,
int fd)
}
-int qemuMonitorJSONAttachPCIDiskController(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
- const char *bus ATTRIBUTE_UNUSED,
- virDevicePCIAddress *guestAddr ATTRIBUTE_UNUSED)
-{
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("pci_add not supported in JSON mode"));
- return -1;
-}
-
-
int qemuMonitorJSONGetAllPCIAddresses(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
qemuMonitorPCIAddress **addrs ATTRIBUTE_UNUSED)
{
}
-static int
-qemuMonitorTextParsePCIAddReply(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
- const char *reply,
- virDevicePCIAddress *addr)
-{
- char *s, *e;
-
- /* 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, &addr->domain) == -1) {
- VIR_WARN("Unable to parse domain number '%s'", s);
- return -1;
- }
-
- if (!STRPREFIX(e, ", ")) {
- VIR_WARN("Expected ', ' parsing pci_add reply '%s'", s);
- return -1;
- }
- s = e + 2;
- }
-
- if (!STRPREFIX(s, "bus ")) {
- VIR_WARN("Expected 'bus ' parsing pci_add reply '%s'", s);
- return -1;
- }
- s += strlen("bus ");
-
- if (virStrToLong_ui(s, &e, 10, &addr->bus) == -1) {
- VIR_WARN("Unable to parse bus number '%s'", s);
- return -1;
- }
-
- if (!STRPREFIX(e, ", ")) {
- VIR_WARN("Expected ', ' parsing pci_add reply '%s'", s);
- return -1;
- }
- s = e + 2;
-
- if (!STRPREFIX(s, "slot ")) {
- VIR_WARN("Expected 'slot ' parsing pci_add reply '%s'", s);
- return -1;
- }
- s += strlen("slot ");
-
- if (virStrToLong_ui(s, &e, 10, &addr->slot) == -1) {
- VIR_WARN("Unable to parse slot number '%s'", s);
- return -1;
- }
-
- return 0;
-}
-
-
-int qemuMonitorTextAddPCIHostDevice(qemuMonitorPtr mon,
- virDevicePCIAddress *hostAddr,
- virDevicePCIAddress *guestAddr)
-{
- char *cmd;
- char *reply = NULL;
- int ret = -1;
-
- memset(guestAddr, 0, sizeof(*guestAddr));
-
- if (hostAddr->domain) {
- /* if domain > 0, the caller has already verified that this qemu
- * supports specifying domain in pci_add command
- */
- if (virAsprintf(&cmd,
- "pci_add pci_addr=auto host host=%.4x:%.2x:%.2x.%.1x",
- hostAddr->domain, hostAddr->bus,
- hostAddr->slot, hostAddr->function) < 0)
- goto cleanup;
- } else {
- if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x",
- hostAddr->bus, hostAddr->slot, hostAddr->function) < 0)
- goto cleanup;
- }
-
- if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
- goto cleanup;
-
- if (strstr(reply, "invalid type: host")) {
- virReportError(VIR_ERR_OPERATION_INVALID, "%s",
- _("PCI device assignment is not supported by this version of qemu"));
- goto cleanup;
- }
-
- if (qemuMonitorTextParsePCIAddReply(mon, reply, guestAddr) < 0) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("parsing pci_add reply failed: %s"), reply);
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- VIR_FREE(cmd);
- VIR_FREE(reply);
- return ret;
-}
-
-
-int qemuMonitorTextAddPCIDisk(qemuMonitorPtr mon,
- const char *path,
- const char *bus,
- virDevicePCIAddress *guestAddr)
-{
- char *cmd = NULL;
- char *reply = NULL;
- char *safe_path = NULL;
- bool tryOldSyntax = false;
- int ret = -1;
-
- safe_path = qemuMonitorEscapeArg(path);
- if (!safe_path)
- return -1;
-
- try_command:
- if (virAsprintf(&cmd, "pci_add %s storage file=%s,if=%s",
- (tryOldSyntax ? "0": "pci_addr=auto"), safe_path, bus) < 0)
- goto cleanup;
-
- if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
- goto cleanup;
-
- if (qemuMonitorTextParsePCIAddReply(mon, reply, guestAddr) < 0) {
- if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
- VIR_FREE(reply);
- VIR_FREE(cmd);
- tryOldSyntax = true;
- goto try_command;
- }
-
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("adding %s disk failed %s: %s"), bus, path, reply);
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- VIR_FREE(safe_path);
- VIR_FREE(cmd);
- VIR_FREE(reply);
- return ret;
-}
-
-
-int qemuMonitorTextAddPCINetwork(qemuMonitorPtr mon,
- const char *nicstr,
- virDevicePCIAddress *guestAddr)
-{
- char *cmd;
- char *reply = NULL;
- int ret = -1;
-
- if (virAsprintf(&cmd, "pci_add pci_addr=auto nic %s", nicstr) < 0)
- return -1;
-
- if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
- goto cleanup;
-
- if (qemuMonitorTextParsePCIAddReply(mon, reply, guestAddr) < 0) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("parsing pci_add reply failed: %s"), reply);
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- VIR_FREE(reply);
- VIR_FREE(cmd);
- return ret;
-}
-
-
-int qemuMonitorTextRemovePCIDevice(qemuMonitorPtr mon,
- virDevicePCIAddress *guestAddr)
-{
- char *cmd = NULL;
- char *reply = NULL;
- bool tryOldSyntax = false;
- int ret = -1;
-
- try_command:
- if (tryOldSyntax) {
- if (virAsprintf(&cmd, "pci_del 0 %.2x", guestAddr->slot) < 0)
- goto cleanup;
- } else {
- /* XXX function ? */
- if (virAsprintf(&cmd, "pci_del pci_addr=%.4x:%.2x:%.2x",
- guestAddr->domain, guestAddr->bus, guestAddr->slot) < 0)
- goto cleanup;
- }
-
- if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
- goto cleanup;
-
- /* Syntax changed when KVM merged PCI hotplug upstream to QEMU,
- * so check for an error message from old KVM indicating the
- * need to try the old syntax */
- if (!tryOldSyntax &&
- strstr(reply, "extraneous characters")) {
- tryOldSyntax = true;
- VIR_FREE(reply);
- VIR_FREE(cmd);
- goto try_command;
- }
- /* If the command fails due to a wrong slot qemu prints: invalid slot,
- * nothing is printed on success */
- if (strstr(reply, "invalid slot") ||
- strstr(reply, "Invalid pci address")) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("failed to detach PCI device, invalid address %.4x:%.2x:%.2x: %s"),
- guestAddr->domain, guestAddr->bus, guestAddr->slot, reply);
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- VIR_FREE(cmd);
- VIR_FREE(reply);
- return ret;
-}
-
-
int qemuMonitorTextSendFileHandle(qemuMonitorPtr mon,
const char *fdname,
int fd)
}
-int qemuMonitorTextAttachPCIDiskController(qemuMonitorPtr mon,
- const char *bus,
- virDevicePCIAddress *guestAddr)
-{
- char *cmd = NULL;
- char *reply = NULL;
- bool tryOldSyntax = false;
- int ret = -1;
-
- try_command:
- if (virAsprintf(&cmd, "pci_add %s storage if=%s",
- (tryOldSyntax ? "0": "pci_addr=auto"), bus) < 0)
- goto cleanup;
-
- if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
- goto cleanup;
-
- if (qemuMonitorTextParsePCIAddReply(mon, reply, guestAddr) < 0) {
- if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
- VIR_FREE(reply);
- VIR_FREE(cmd);
- tryOldSyntax = true;
- goto try_command;
- }
-
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("adding %s disk controller failed: %s"), bus, reply);
- goto cleanup;
- }
-
- ret = 0;
-
- cleanup:
- VIR_FREE(cmd);
- VIR_FREE(reply);
- return ret;
-}
-
-
/*
* The format we're after looks like this
*