This enables support for nested SVM using the regular CPU
model/features block. If the CPU model or features include
'svm' or 'vmx', then the '-enable-nesting' flag will be
added to the QEMU command line. Several of the models
already include svm support, but QEMU was just masking out
the svm bit silently. So this will enable SVM on such
models
* src/qemu/qemu_conf.h: flag for -enable-nesting
* src/qemu/qemu_conf.c: Use -enable-nesting if VMX or SVM are in
the CPUID
---
src/qemu/qemu_conf.c | 39 +++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_conf.h | 1 +
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 7a37c70..a2aab95 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1210,6 +1210,8 @@ static unsigned long long qemudComputeCmdFlags(const char *help,
flags |= QEMUD_CMD_FLAG_NO_KVM_PIT;
if (strstr(help, "-tdf"))
flags |= QEMUD_CMD_FLAG_TDF;
+ if (strstr(help, "-enable-nesting"))
+ flags |= QEMUD_CMD_FLAG_NESTING;
if (strstr(help, ",menu=on"))
flags |= QEMUD_CMD_FLAG_BOOT_MENU;
@@ -3494,13 +3496,36 @@ error:
}
+#define CPUID_FUNCTION_SVM 0x80000001
+#define CPUID_ECX_SVM 0x00000004
+
+#define CPUID_FUNCTION_VMX 0x00000001
+#define CPUID_ECX_VMX 0x00000020
+
+static bool qemuCpuHasHwVirt(union cpuData *data)
+{
+ int i;
+ for (i = 0 ; i < data->x86.basic_len ; i++) {
+ if (data->x86.basic[i].function == CPUID_FUNCTION_VMX &&
+ (data->x86.basic[i].ecx & CPUID_ECX_VMX))
+ return true;
+ }
+ for (i = 0 ; i < data->x86.extended_len ; i++) {
+ if (data->x86.extended[i].function == CPUID_FUNCTION_SVM &&
+ (data->x86.extended[i].ecx & CPUID_ECX_SVM))
+ return true;
+ }
+ return false;
+}
+
static int
qemuBuildCpuArgStr(const struct qemud_driver *driver,
const virDomainDefPtr def,
const char *emulator,
unsigned long long qemuCmdFlags,
const struct utsname *ut,
- char **opt)
+ char **opt,
+ bool *hasHwVirt)
{
const virCPUDefPtr host = driver->caps->host.cpu;
virCPUDefPtr guest = NULL;
@@ -3511,6 +3536,8 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
virBuffer buf = VIR_BUFFER_INITIALIZER;
int i;
+ *hasHwVirt = false;
+
if (def->cpu && def->cpu->model) {
if (qemudProbeCPUModels(emulator, qemuCmdFlags, ut->machine,
&ncpus, &cpus) < 0)
@@ -3552,6 +3579,8 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
if (cpuDecode(guest, data, cpus, ncpus, preferred) < 0)
goto cleanup;
+ *hasHwVirt = qemuCpuHasHwVirt(data);
+
virBufferVSprintf(&buf, "%s", guest->model);
for (i = 0; i < guest->nfeatures; i++) {
char sign;
@@ -3678,6 +3707,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
char *cpu;
char *smp;
int last_good_net = -1;
+ bool hasHwVirt = false;
uname_normalize(&ut);
@@ -3871,13 +3901,18 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT(def->os.machine);
}
- if (qemuBuildCpuArgStr(driver, def, emulator, qemuCmdFlags, &ut, &cpu) <
0)
+ if (qemuBuildCpuArgStr(driver, def, emulator, qemuCmdFlags,
+ &ut, &cpu, &hasHwVirt) < 0)
goto error;
if (cpu) {
ADD_ARG_LIT("-cpu");
ADD_ARG_LIT(cpu);
VIR_FREE(cpu);
+
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NESTING) &&
+ hasHwVirt)
+ ADD_ARG_LIT("-enable-nesting");
}
if (disableKQEMU)
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 2c9e608..16f72f5 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -93,6 +93,7 @@ enum qemud_cmd_flags {
QEMUD_CMD_FLAG_NODEFCONFIG = (1LL << 37), /* -nodefconfig */
QEMUD_CMD_FLAG_BOOT_MENU = (1LL << 38), /* -boot menu=on support */
QEMUD_CMD_FLAG_ENABLE_KQEMU = (1LL << 39), /* -enable-kqemu flag */
+ QEMUD_CMD_FLAG_NESTING = (1LL << 40), /* -enable-nesting (SVM/VMX) */
};
/* Main driver state */
--
1.7.2.3