From 037a49dc6613c8785b6925936623200bad812a82 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Wed, 31 Oct 2012 08:31:49 +0100 Subject: [PATCH] Make non-KVM machines work with QMP probing When there is no 'qemu-kvm' binary and the emulator used for a machine is, for example, 'qemu-system-x86_64' that, by default, runs without kvm enabled, libvirt still supplies '-no-kvm' option to this process, even though it does not recognize such option (making the start of a domain fail in that case). This patch fixes building a command-line for QEMU machines without KVM acceleration and is based on following assumptions: - QEMU_CAPS_KVM flag means that QEMU is running KVM accelerated machines by default (without explicitly requesting that using a command-line option). It is the closest to the truth according to the code with the only exception being the comment next to the flag, so it's fixed in this patch as well. - QEMU_CAPS_ENABLE_KVM flag means that QEMU is, by default, running without KVM acceleration and in case we need KVM acceleration it needs to be explicitly instructed to do so. This is partially true for the past (this option essentially means that QEMU recognizes the '-enable-kvm' option, even though it's almost the same). --- src/qemu/qemu_capabilities.c | 30 ++++++++++++++++++++- src/qemu/qemu_capabilities.h | 2 +- src/qemu/qemu_monitor.c | 23 ++++++++++++++++ src/qemu/qemu_monitor.h | 4 +++ src/qemu/qemu_monitor_json.c | 51 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 ++++ 6 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 619431065e..9f151622d6 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2030,6 +2030,33 @@ qemuCapsProbeQMPCPUDefinitions(qemuCapsPtr caps, } +static int +qemuCapsProbeQMPKVMState(qemuCapsPtr caps, + qemuMonitorPtr mon) +{ + bool enabled = false; + bool present = false; + + if (!qemuCapsGet(caps, QEMU_CAPS_KVM)) + return 0; + + if (qemuMonitorGetKVMState(mon, &enabled, &present) < 0) + return -1; + + /* The QEMU_CAPS_KVM flag was initially set according to the QEMU + * reporting the recognition of 'query-kvm' QMP command, but the + * flag means whether the KVM is enabled by default and should be + * disabled in case we want SW emulated machine, so let's fix that + * if it's true. */ + if (!enabled) { + qemuCapsClear(caps, QEMU_CAPS_KVM); + qemuCapsSet(caps, QEMU_CAPS_ENABLE_KVM); + } + + return 0; +} + + int qemuCapsProbeQMP(qemuCapsPtr caps, qemuMonitorPtr mon) { @@ -2160,7 +2187,6 @@ qemuCapsInitQMPBasic(qemuCapsPtr caps) qemuCapsSet(caps, QEMU_CAPS_DRIVE_SERIAL); qemuCapsSet(caps, QEMU_CAPS_MIGRATE_QEMU_UNIX); qemuCapsSet(caps, QEMU_CAPS_CHARDEV); - qemuCapsSet(caps, QEMU_CAPS_ENABLE_KVM); qemuCapsSet(caps, QEMU_CAPS_MONITOR_JSON); qemuCapsSet(caps, QEMU_CAPS_BALLOON); qemuCapsSet(caps, QEMU_CAPS_DEVICE); @@ -2322,6 +2348,8 @@ qemuCapsInitQMP(qemuCapsPtr caps, goto cleanup; if (qemuCapsProbeQMPCPUDefinitions(caps, mon) < 0) goto cleanup; + if (qemuCapsProbeQMPKVMState(caps, mon) < 0) + goto cleanup; ret = 0; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index cce372b3ac..fb88aa1323 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -45,7 +45,7 @@ enum qemuCapsFlags { QEMU_CAPS_MIGRATE_QEMU_TCP = 10, /* have qemu tcp migration */ QEMU_CAPS_MIGRATE_QEMU_EXEC = 11, /* have qemu exec migration */ QEMU_CAPS_DRIVE_CACHE_V2 = 12, /* cache= flag wanting new v2 values */ - QEMU_CAPS_KVM = 13, /* Whether KVM is compiled in */ + QEMU_CAPS_KVM = 13, /* Whether KVM is enabled by default */ QEMU_CAPS_DRIVE_FORMAT = 14, /* Is -drive format= avail */ QEMU_CAPS_VGA = 15, /* Is -vga avail */ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 3126960293..a92f74d63e 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3235,6 +3235,29 @@ int qemuMonitorGetEvents(qemuMonitorPtr mon, } +int qemuMonitorGetKVMState(qemuMonitorPtr mon, + bool *enabled, + bool *present) +{ + VIR_DEBUG("mon=%p enabled=%p present=%p", + mon, enabled, present); + + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (!mon->json) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("JSON monitor is required")); + return -1; + } + + return qemuMonitorJSONGetKVMState(mon, enabled, present); +} + + int qemuMonitorGetObjectTypes(qemuMonitorPtr mon, char ***types) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index f6a4a47a05..dbfab88039 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -620,6 +620,10 @@ int qemuMonitorGetCommands(qemuMonitorPtr mon, int qemuMonitorGetEvents(qemuMonitorPtr mon, char ***events); +int qemuMonitorGetKVMState(qemuMonitorPtr mon, + bool *enabled, + bool *present); + int qemuMonitorGetObjectTypes(qemuMonitorPtr mon, char ***types); int qemuMonitorGetObjectProps(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 9a1f2dc9c2..e4f21667b9 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4293,6 +4293,57 @@ cleanup: } +int qemuMonitorJSONGetKVMState(qemuMonitorPtr mon, + bool *enabled, + bool *present) +{ + int ret; + virJSONValuePtr cmd = NULL; + virJSONValuePtr reply = NULL; + virJSONValuePtr data = NULL; + + /* Safe defaults */ + *enabled = *present = false; + + if (!(cmd = qemuMonitorJSONMakeCommand("query-kvm", NULL))) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) { + if (qemuMonitorJSONHasError(reply, "CommandNotFound")) + 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-kvm reply was missing return data")); + goto cleanup; + } + + if (virJSONValueObjectGetBoolean(data, "enabled", enabled) < 0 || + virJSONValueObjectGetBoolean(data, "present", present) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-kvm replied unexpected data")); + goto cleanup; + } + + ret = 0; + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONGetObjectTypes(qemuMonitorPtr mon, char ***types) { diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 2834fed534..c62ae249e9 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -322,6 +322,11 @@ int qemuMonitorJSONGetEvents(qemuMonitorPtr mon, char ***events) ATTRIBUTE_NONNULL(2); +int qemuMonitorJSONGetKVMState(qemuMonitorPtr mon, + bool *enabled, + bool *present) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + int qemuMonitorJSONGetObjectTypes(qemuMonitorPtr mon, char ***types) ATTRIBUTE_NONNULL(2); -- GitLab