提交 037a49dc 编写于 作者: M Martin Kletzander

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).
上级 adaa7ab6
......@@ -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;
......
......@@ -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 */
......
......@@ -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)
{
......
......@@ -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,
......
......@@ -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)
{
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册