return 0;
}
+
+int
+qemuDomainUpdateMemoryDeviceInfo(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virHashTablePtr meminfo = NULL;
+ int rc;
+ size_t i;
+
+ if (vm->def->nmems == 0)
+ return 0;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ rc = qemuMonitorGetMemoryDeviceInfo(priv->mon, &meminfo);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ return -1;
+
+ /* if qemu doesn't support the info request, just carry on */
+ if (rc == -2)
+ return 0;
+
+ if (rc < 0)
+ return -1;
+
+ for (i = 0; i < vm->def->nmems; i++) {
+ virDomainMemoryDefPtr mem = vm->def->mems[i];
+ qemuMonitorMemoryDeviceInfoPtr dimm;
+
+ if (!mem->info.alias)
+ continue;
+
+ if (!(dimm = virHashLookup(meminfo, mem->info.alias)))
+ continue;
+
+ mem->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM;
+ mem->info.addr.dimm.slot = dimm->slot;
+ mem->info.addr.dimm.base = dimm->address;
+ }
+
+ virHashFree(meminfo);
+ return 0;
+}
+
+
bool
qemuDomainDefCheckABIStability(virQEMUDriverPtr driver,
virDomainDefPtr src,
VIR_FREE(iothread->name);
VIR_FREE(iothread);
}
+
+
+/**
+ * qemuMonitorGetMemoryDeviceInfo:
+ * @mon: pointer to the monitor
+ * @info: Location to return the hash of qemuMonitorMemoryDeviceInfo
+ *
+ * Retrieve state and addresses of frontend memory devices present in
+ * the guest.
+ *
+ * Returns 0 on success and fills @info with a newly allocated struct; if the
+ * data can't be retrieved due to lack of support in qemu, returns -2. On
+ * other errors returns -1.
+ */
+int
+qemuMonitorGetMemoryDeviceInfo(qemuMonitorPtr mon,
+ virHashTablePtr *info)
+{
+ VIR_DEBUG("mon=%p info=%p", mon, info);
+ int ret;
+
+ *info = NULL;
+
+ if (!mon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return -1;
+ }
+
+ if (!mon->json)
+ return -2;
+
+ if (!(*info = virHashCreate(10, virHashValueFree)))
+ return -1;
+
+ if ((ret = qemuMonitorJSONGetMemoryDeviceInfo(mon, *info)) < 0) {
+ virHashFree(*info);
+ *info = NULL;
+ }
+
+ return ret;
+}
virJSONValueFree(reply);
return ret;
}
+
+
+int
+qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
+ virHashTablePtr info)
+{
+ int ret = -1;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr data = NULL;
+ qemuMonitorMemoryDeviceInfoPtr meminfo = NULL;
+ ssize_t n;
+ size_t i;
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("query-memory-devices", NULL)))
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0) {
+ if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
+ ret = -2;
+ goto cleanup;
+ }
+
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+ }
+
+ if (ret < 0)
+ goto cleanup;
+
+ ret = -1;
+
+ if (!(data = virJSONValueObjectGet(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-memory-devices reply was missing return data"));
+ goto cleanup;
+ }
+
+ if ((n = virJSONValueArraySize(data)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-memory-devices reply data was not an array"));
+ goto cleanup;
+ }
+
+ for (i = 0; i < n; i++) {
+ virJSONValuePtr elem = virJSONValueArrayGet(data, i);
+ const char *type;
+
+ if (!(type = virJSONValueObjectGetString(elem, "type"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-memory-devices reply data doesn't contain "
+ "enum type discriminator"));
+ goto cleanup;
+ }
+
+ /* dimm memory devices */
+ if (STREQ(type, "dimm")) {
+ virJSONValuePtr dimminfo;
+ const char *devalias;
+
+ if (!(dimminfo = virJSONValueObjectGet(elem, "data"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-memory-devices reply data doesn't "
+ "contain enum data"));
+ goto cleanup;
+ }
+
+ if (!(devalias = virJSONValueObjectGetString(dimminfo, "id"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("dimm memory info data is missing 'id'"));
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC(meminfo) < 0)
+ goto cleanup;
+
+ if (virJSONValueObjectGetNumberUlong(dimminfo, "addr",
+ &meminfo->address) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed/missing addr in dimm memory info"));
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetNumberUint(dimminfo, "slot",
+ &meminfo->slot) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed/missing slot in dimm memory info"));
+ goto cleanup;
+ }
+
+ if (virJSONValueObjectGetBoolean(dimminfo, "hotplugged",
+ &meminfo->hotplugged) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed/missing hotplugged in dimm memory info"));
+ goto cleanup;
+
+ }
+
+ if (virJSONValueObjectGetBoolean(dimminfo, "hotpluggable",
+ &meminfo->hotpluggable) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed/missing hotpluggable in dimm memory info"));
+ goto cleanup;
+
+ }
+
+ if (virHashAddEntry(info, devalias, meminfo) < 0)
+ goto cleanup;
+
+ meminfo = NULL;
+ }
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(meminfo);
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}