return ret;
}
+
+/**
+ * To update video memory size in status XML we need to load correct values from
+ * QEMU. This is supported only with JSON monitor.
+ *
+ * Returns 0 on success, -1 on failure and sets proper error message.
+ */
+int
+qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon,
+ virDomainVideoDefPtr video,
+ const char *videoName)
+{
+ int ret = -1;
+ char *path = NULL;
+
+ if (mon->json) {
+ ret = qemuMonitorFindObjectPath(mon, "/", videoName, &path);
+ if (ret < 0) {
+ if (ret == -2)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to find QOM Object path for "
+ "device '%s'"), videoName);
+ return -1;
+ }
+
+ ret = qemuMonitorJSONUpdateVideoMemorySize(mon, video, path);
+ VIR_FREE(path);
+ return ret;
+ }
+
+ return 0;
+}
+
+
int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
const char *cmd,
int scm_fd,
ATTRIBUTE_NONNULL(1);
void qemuMonitorSetOptions(qemuMonitorPtr mon, virJSONValuePtr options)
ATTRIBUTE_NONNULL(1);
+int qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon,
+ virDomainVideoDefPtr video,
+ const char *videName)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
const char *cmd,
int scm_fd,
}
+/**
+ * Loads correct video memory size values from QEMU and update the video
+ * definition.
+ *
+ * Return 0 on success, -1 on failure and set proper error message.
+ */
+int
+qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
+ virDomainVideoDefPtr video,
+ char *path)
+{
+ qemuMonitorJSONObjectProperty prop = {
+ QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
+ {0}
+ };
+
+ switch (video->type) {
+ case VIR_DOMAIN_VIDEO_TYPE_VGA:
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("QOM Objext '%s' has no property 'vgamem_mb'"),
+ path);
+ return -1;
+ }
+ video->vram = prop.val.ul * 1024;
+ break;
+ case VIR_DOMAIN_VIDEO_TYPE_QXL:
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vram_size", &prop) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("QOM Objext '%s' has no property 'vram_size'"),
+ path);
+ return -1;
+ }
+ video->vram = prop.val.ul / 1024;
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "ram_size", &prop) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("QOM Objext '%s' has no property 'ram_size'"),
+ path);
+ return -1;
+ }
+ video->ram = prop.val.ul / 1024;
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("QOM Objext '%s' has no property 'vgamem_mb'"),
+ path);
+ return -1;
+ }
+ video->vgamem = prop.val.ul * 1024;
+ break;
+ case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("QOM Objext '%s' has no property 'vgamem_mb'"),
+ path);
+ return -1;
+ }
+ video->vram = prop.val.ul * 1024;
+ break;
+ case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
+ case VIR_DOMAIN_VIDEO_TYPE_XEN:
+ case VIR_DOMAIN_VIDEO_TYPE_VBOX:
+ case VIR_DOMAIN_VIDEO_TYPE_LAST:
+ break;
+ }
+
+ return 0;
+}
+
+
/*
* Returns: 0 if balloon not supported, +1 if balloon query worked
* or -1 on failure
int **pids);
int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
int *virtType);
+int qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
+ virDomainVideoDefPtr video,
+ char *path);
int qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
unsigned long long *currmem);
int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
}
+/**
+ * Loads and update video memory size for video devices according to QEMU
+ * process as the QEMU will silently update the values that we pass to QEMU
+ * through command line. We need to load these updated values and store them
+ * into the status XML.
+ *
+ * We will fail if for some reason the values cannot be loaded from QEMU because
+ * its mandatory to get the correct video memory size to status XML to not break
+ * migration.
+ */
+static int
+qemuProcessUpdateVideoRamSize(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ int asyncJob)
+{
+ int ret = -1;
+ ssize_t i;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainVideoDefPtr video = NULL;
+ virQEMUDriverConfigPtr cfg = NULL;
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ for (i = 0; i < vm->def->nvideos; i++) {
+ video = vm->def->videos[i];
+
+ switch (video->type) {
+ case VIR_DOMAIN_VIDEO_TYPE_VGA:
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VGA_VGAMEM)) {
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video, "VGA") < 0)
+ goto error;
+ }
+ break;
+ case VIR_DOMAIN_VIDEO_TYPE_QXL:
+ if (i == 0) {
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGA_VGAMEM)) {
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
+ "qxl-vga") < 0)
+ goto error;
+ }
+ } else {
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGAMEM)) {
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
+ "qxl") < 0)
+ goto error;
+ }
+ }
+ break;
+ case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM)) {
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
+ "vmware-svga") < 0)
+ goto error;
+ }
+ break;
+ case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
+ case VIR_DOMAIN_VIDEO_TYPE_XEN:
+ case VIR_DOMAIN_VIDEO_TYPE_VBOX:
+ case VIR_DOMAIN_VIDEO_TYPE_LAST:
+ break;
+ }
+
+ }
+
+ qemuDomainObjExitMonitor(driver, vm);
+
+ cfg = virQEMUDriverGetConfig(driver);
+ ret = virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm);
+ virObjectUnref(cfg);
+
+ return ret;
+
+ error:
+ qemuDomainObjExitMonitor(driver, vm);
+ return -1;
+}
+
+
struct qemuProcessHookData {
virConnectPtr conn;
virDomainObjPtr vm;
}
qemuDomainObjExitMonitor(driver, vm);
+ VIR_DEBUG("Detecting actual memory size for video device");
+ if (qemuProcessUpdateVideoRamSize(driver, vm, asyncJob) < 0)
+ goto cleanup;
+
if (!(flags & VIR_QEMU_PROCESS_START_PAUSED)) {
VIR_DEBUG("Starting domain CPUs");
/* Allow the CPUS to start executing */