return driver->update(guest, host);
}
+
+int
+cpuHasFeature(const char *arch,
+ const union cpuData *data,
+ const char *feature)
+{
+ struct cpuArchDriver *driver;
+
+ VIR_DEBUG("arch=%s, data=%p, feature=%s",
+ arch, data, feature);
+
+ if ((driver = cpuGetSubDriver(arch)) == NULL)
+ return -1;
+
+ if (driver->hasFeature == NULL) {
+ virCPUReportError(VIR_ERR_NO_SUPPORT,
+ _("cannot check guest CPU data for %s architecture"),
+ arch);
+ return -1;
+ }
+
+ return driver->hasFeature(data, feature);
+}
(*cpuArchUpdate) (virCPUDefPtr guest,
const virCPUDefPtr host);
+typedef int
+(*cpuArchHasFeature) (const union cpuData *data,
+ const char *feature);
+
struct cpuArchDriver {
const char *name;
cpuArchGuestData guestData;
cpuArchBaseline baseline;
cpuArchUpdate update;
+ cpuArchHasFeature hasFeature;
};
cpuUpdate (virCPUDefPtr guest,
const virCPUDefPtr host);
+extern int
+cpuHasFeature(const char *arch,
+ const union cpuData *data,
+ const char *feature);
+
+
#endif /* __VIR_CPU_H__ */
return ret;
}
+static int x86HasFeature(const union cpuData *data,
+ const char *name)
+{
+ struct x86_map *map;
+ struct x86_feature *feature;
+ int ret = -1;
+ int i;
+
+ if (!(map = x86LoadMap()))
+ return -1;
+
+ if (!(feature = x86FeatureFind(map, name)))
+ goto cleanup;
+
+ for (i = 0 ; i < feature->ncpuid ; i++) {
+ struct cpuX86cpuid *cpuid;
+
+ cpuid = x86DataCpuid(data, feature->cpuid[i].function);
+ if (cpuid && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) {
+ ret = 1;
+ goto cleanup;
+ }
+ }
+ ret = 0;
+
+cleanup:
+ x86MapFree(map);
+ return ret;
+}
struct cpuArchDriver cpuDriverX86 = {
.name = "x86",
.guestData = x86GuestData,
.baseline = x86Baseline,
.update = x86Update,
+ .hasFeature = x86HasFeature,
};
cpuGuestData;
cpuNodeData;
cpuUpdate;
+cpuHasFeature;
# cpu_conf.h
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;
if (strstr(help, "-fsdev"))
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;
virBuffer buf = VIR_BUFFER_INITIALIZER;
int i;
+ *hasHwVirt = false;
+
if (def->cpu && def->cpu->model) {
if (qemudProbeCPUModels(emulator, qemuCmdFlags, ut->machine,
&ncpus, &cpus) < 0)
if (ncpus > 0 && host) {
virCPUCompareResult cmp;
const char *preferred;
+ int hasSVM;
cmp = cpuGuestData(host, def->cpu, &data);
switch (cmp) {
if (cpuDecode(guest, data, cpus, ncpus, preferred) < 0)
goto cleanup;
+ /* Only 'svm' requires --enable-nesting. The nested
+ * 'vmx' patches now simply hook off the CPU features
+ */
+ hasSVM = cpuHasFeature(guest->arch, data, "svm");
+ if (hasSVM < 0)
+ goto cleanup;
+ *hasHwVirt = hasSVM > 0 ? true : false;
+
virBufferVSprintf(&buf, "%s", guest->model);
for (i = 0; i < guest->nfeatures; i++) {
char sign;
char *cpu;
char *smp;
int last_good_net = -1;
+ bool hasHwVirt = false;
uname_normalize(&ut);
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)
QEMUD_CMD_FLAG_BOOT_MENU = (1LL << 38), /* -boot menu=on support */
QEMUD_CMD_FLAG_ENABLE_KQEMU = (1LL << 39), /* -enable-kqemu flag */
QEMUD_CMD_FLAG_FSDEV = (1LL << 40), /* -fstype filesystem passthrough */
+ QEMUD_CMD_FLAG_NESTING = (1LL << 41), /* -enable-nesting (SVM/VMX) */
};
/* Main driver state */
QEMUD_CMD_FLAG_RTC_TD_HACK |
QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_NO_KVM_PIT |
- QEMUD_CMD_FLAG_TDF,
+ QEMUD_CMD_FLAG_TDF |
+ QEMUD_CMD_FLAG_NESTING,
10005, 1, 0);
DO_TEST("kvm-86",
QEMUD_CMD_FLAG_VNC_COLON |
QEMUD_CMD_FLAG_RTC_TD_HACK |
QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_NO_KVM_PIT |
- QEMUD_CMD_FLAG_TDF,
+ QEMUD_CMD_FLAG_TDF |
+ QEMUD_CMD_FLAG_NESTING,
10050, 1, 0);
DO_TEST("qemu-kvm-0.11.0-rc2",
QEMUD_CMD_FLAG_VNC_COLON |
QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_NO_KVM_PIT |
QEMUD_CMD_FLAG_TDF |
- QEMUD_CMD_FLAG_BOOT_MENU,
+ QEMUD_CMD_FLAG_BOOT_MENU |
+ QEMUD_CMD_FLAG_NESTING,
10092, 1, 0);
DO_TEST("qemu-0.12.1",
QEMUD_CMD_FLAG_VNC_COLON |
QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_NO_KVM_PIT |
QEMUD_CMD_FLAG_TDF |
- QEMUD_CMD_FLAG_BOOT_MENU,
+ QEMUD_CMD_FLAG_BOOT_MENU |
+ QEMUD_CMD_FLAG_NESTING,
12003, 1, 0);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;