[libvirt] PATCH: Be more flexible in emulator choice on x86 archs

Currently we are pretty strict about what emulator binary we allow for QEMU guests on x86 arches. In particular, for arch+domain type combos: - i686+qemu must use 'qemu' binary - x86_64+qemu must use 'qemu-system-x86_64' binary - kvm must use 'qemu-kvm' or 'kvm' binaries - i686+kvm on x86_64 host is not allowed These restrictions are overkill because - i686+qemu could use 'qemu-system-x86_64' if '-cpu qemu32' is added - i686+qemu could use 'qemu-kvm' if '-cpu qemu32 -no-kvm' is added - x86_64+qemu could use 'qemu-kvm' if '-no-kvm' is added - i686+kvm on x86_64 host can be used if '-cpu qemu32' is added This patch makes QEMU driver more flexible in this way when setting up its capabilities information. It also makes it aware of the -no-kvm and -cpu flag, using them where required by the os type + arch + emulator combinations specified in the guest XML. This should finally remove the confusion where a user in virt-manager selectrs 'i686' and then wonders why we've disallowed choice of 'kvm'. It also fixes 'virsh version' when only qemu-kvm is installed. The matrix should now work thus: 1. qemu, qemu-system-x86_64, qemu-kvm all available qemu+i686 => qemu qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm 2. qemu, qemu-kvm available qemu+i686 => qemu qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm 3. qemu-system-x86_64, qemu-kvm available qemu+i686 => qemu-system-x86_64 -cpu qemu32 qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm 4. qemu-kvm available qemu+i686 => qemu-kvm -no-kvm -cpu qemu32 qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm The only real remaining problem is that we don't cope with scenario where the KVM enabled binary is called 'qemu-system-x64_64' instead of 'qemu-kvm' or 'kvm'. Regards, Daniel Index: src/qemu_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_conf.c,v retrieving revision 1.138 diff -u -p -r1.138 qemu_conf.c --- src/qemu_conf.c 16 Mar 2009 13:54:26 -0000 1.138 +++ src/qemu_conf.c 16 Mar 2009 17:53:20 -0000 @@ -211,6 +211,7 @@ struct qemu_arch_info { const char *const *machines; int nmachines; const char *binary; + const char *altbinary; const struct qemu_feature_flags *flags; int nflags; }; @@ -231,24 +232,24 @@ static const struct qemu_feature_flags c /* The archicture tables for supported QEMU archs */ static const struct qemu_arch_info const arch_info_hvm[] = { { "i686", 32, arch_info_hvm_x86_machines, 2, - "/usr/bin/qemu", arch_info_i686_flags, 4 }, + "/usr/bin/qemu", "/usr/bin/qemu-system-x86_64", arch_info_i686_flags, 4 }, { "x86_64", 64, arch_info_hvm_x86_machines, 2, - "/usr/bin/qemu-system-x86_64", arch_info_x86_64_flags, 2 }, + "/usr/bin/qemu-system-x86_64", NULL, arch_info_x86_64_flags, 2 }, { "mips", 32, arch_info_hvm_mips_machines, 1, - "/usr/bin/qemu-system-mips", NULL, 0 }, + "/usr/bin/qemu-system-mips", NULL, NULL, 0 }, { "mipsel", 32, arch_info_hvm_mips_machines, 1, - "/usr/bin/qemu-system-mipsel", NULL, 0 }, + "/usr/bin/qemu-system-mipsel", NULL, NULL, 0 }, { "sparc", 32, arch_info_hvm_sparc_machines, 1, - "/usr/bin/qemu-system-sparc", NULL, 0 }, + "/usr/bin/qemu-system-sparc", NULL, NULL, 0 }, { "ppc", 32, arch_info_hvm_ppc_machines, 3, - "/usr/bin/qemu-system-ppc", NULL, 0 }, + "/usr/bin/qemu-system-ppc", NULL, NULL, 0 }, }; static const struct qemu_arch_info const arch_info_xen[] = { { "i686", 32, arch_info_xen_x86_machines, 1, - "/usr/bin/xenner", arch_info_i686_flags, 4 }, + "/usr/bin/xenner", NULL, arch_info_i686_flags, 4 }, { "x86_64", 64, arch_info_xen_x86_machines, 1, - "/usr/bin/xenner", arch_info_x86_64_flags, 2 }, + "/usr/bin/xenner", NULL, arch_info_x86_64_flags, 2 }, }; static int @@ -257,43 +258,62 @@ qemudCapsInitGuest(virCapsPtr caps, const struct qemu_arch_info *info, int hvm) { virCapsGuestPtr guest; - int i, haskvm, hasbase, samearch; + int i; + int hasbase = 0; + int hasaltbase = 0; + int haskvm = 0; + int haskqemu = 0; const char *kvmbin = NULL; - /* Check for existance of base emulator */ + /* Check for existance of base emulator, or alternate base + * which can be used with magic cpu choice + */ hasbase = (access(info->binary, X_OK) == 0); + hasaltbase = (access(info->altbinary, X_OK) == 0); - samearch = STREQ(info->arch, hostmachine); - if (samearch) { + /* Can use acceleration for KVM/KQEMU if + * - host & guest arches match + * Or + * - hostarch is x86_64 and guest arch is i686 + * The latter simply needs "-cpu qemu32" + */ + if (STREQ(info->arch, hostmachine) || + (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) { const char *const kvmbins[] = { "/usr/bin/qemu-kvm", /* Fedora */ "/usr/bin/kvm" }; /* Upstream .spec */ for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) { - if ((haskvm = (access(kvmbins[i], X_OK) == 0))) { + if (access(kvmbins[i], X_OK) == 0 && + access("/dev/kvm", F_OK) == 0) { + haskvm = 1; kvmbin = kvmbins[i]; break; } } - } else { - haskvm = 0; + + if (access("/dev/kqemu", F_OK) == 0) + haskqemu = 1; } - if (!hasbase && !haskvm) + + if (!hasbase && !hasaltbase && !haskvm) return 0; + /* We register kvm as the base emulator too, since we can + * just give -no-kvm to disable acceleration if required */ if ((guest = virCapabilitiesAddGuest(caps, hvm ? "hvm" : "xen", info->arch, info->wordsize, - info->binary, + (hasbase ? info->binary : + (hasaltbase ? info->altbinary : kvmbin)), NULL, info->nmachines, info->machines)) == NULL) return -1; if (hvm) { - if (hasbase && - virCapabilitiesAddGuestDomain(guest, + if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, @@ -301,27 +321,23 @@ qemudCapsInitGuest(virCapsPtr caps, NULL) == NULL) return -1; - /* If guest & host match, then we can accelerate */ - if (samearch) { - if (access("/dev/kqemu", F_OK) == 0 && - virCapabilitiesAddGuestDomain(guest, - "kqemu", - NULL, - NULL, - 0, - NULL) == NULL) - return -1; + if (haskqemu && + virCapabilitiesAddGuestDomain(guest, + "kqemu", + NULL, + NULL, + 0, + NULL) == NULL) + return -1; - if (access("/dev/kvm", F_OK) == 0 && - haskvm && - virCapabilitiesAddGuestDomain(guest, - "kvm", - kvmbin, - NULL, - 0, - NULL) == NULL) - return -1; - } + if (haskvm && + virCapabilitiesAddGuestDomain(guest, + "kvm", + kvmbin, + NULL, + 0, + NULL) == NULL) + return -1; } else { if (virCapabilitiesAddGuestDomain(guest, "kvm", @@ -363,12 +379,14 @@ virCapsPtr qemudCapsInit(void) { if (virCapsInitNUMA(caps) < 0) goto no_memory; + /* First the pure HVM guests */ for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++) if (qemudCapsInitGuest(caps, utsname.machine, &arch_info_hvm[i], 1) < 0) goto no_memory; + /* Then possibly the Xen paravirt guests (ie Xenner */ if (access("/usr/bin/xenner", X_OK) == 0 && access("/dev/kvm", F_OK) == 0) { for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_xen) ; i++) @@ -430,6 +448,8 @@ int qemudExtractVersionInfo(const char * if (strstr(help, "-no-kqemu")) flags |= QEMUD_CMD_FLAG_KQEMU; + if (strstr(help, "-no-kvm")) + flags |= QEMUD_CMD_FLAG_KVM; if (strstr(help, "-no-reboot")) flags |= QEMUD_CMD_FLAG_NO_REBOOT; if (strstr(help, "-name")) @@ -749,6 +769,7 @@ int qemudBuildCommandLine(virConnectPtr char boot[VIR_DOMAIN_BOOT_LAST]; struct utsname ut; int disableKQEMU = 0; + int disableKVM = 0; int qargc = 0, qarga = 0; const char **qargv = NULL; int qenvc = 0, qenva = 0; @@ -757,6 +778,7 @@ int qemudBuildCommandLine(virConnectPtr char uuid[VIR_UUID_STRING_BUFLEN]; char domid[50]; char *pidfile; + const char *cpu = NULL; uname_normalize(&ut); @@ -789,9 +811,16 @@ int qemudBuildCommandLine(virConnectPtr } } + emulator = vm->def->emulator; + if (!emulator) + emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps); + if (!emulator) + return -1; + + /* Need to explicitly disable KQEMU if * 1. Arch matches host arch - * 2. Guest is 'qemu' + * 2. Guest domain is 'qemu' * 3. The qemu binary has the -no-kqemu flag */ if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) && @@ -799,6 +828,34 @@ int qemudBuildCommandLine(virConnectPtr vm->def->virtType == VIR_DOMAIN_VIRT_QEMU) disableKQEMU = 1; + /* Need to explicitly disable KVM if + * 1. Arch matches host arch + * 2. Guest domain is 'qemu' + * 3. The qemu binary has the -no-kvm flag + */ + if ((qemuCmdFlags & QEMUD_CMD_FLAG_KVM) && + STREQ(ut.machine, vm->def->os.arch) && + vm->def->virtType == VIR_DOMAIN_VIRT_QEMU) + disableKVM = 1; + + /* + * Need to force a 32-bit guest CPU type if + * + * 1. guest OS is i686 + * 2. host OS is x86_64 + * 3. emulator is qemu-kvm or kvm + * + * Or + * + * 1. guest OS is i686 + * 2. emulator is qemu-system-x86_64 + */ + if (STREQ(vm->def->os.arch, "i686") && + ((STREQ(ut.machine, "x86_64") && + strstr(emulator, "kvm")) || + strstr(emulator, "x86_64"))) + cpu = "qemu32"; + #define ADD_ARG_SPACE \ do { \ if (qargc == qarga) { \ @@ -887,12 +944,6 @@ int qemudBuildCommandLine(virConnectPtr ADD_ENV_COPY("LOGNAME"); ADD_ENV_COPY("TMPDIR"); - emulator = vm->def->emulator; - if (!emulator) - emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps); - if (!emulator) - return -1; - ADD_ARG_LIT(emulator); ADD_ARG_LIT("-S"); @@ -904,9 +955,15 @@ int qemudBuildCommandLine(virConnectPtr ADD_ARG_LIT("-M"); ADD_ARG_LIT(vm->def->os.machine); } + if (cpu) { + ADD_ARG_LIT("-cpu"); + ADD_ARG_LIT(cpu); + } if (disableKQEMU) ADD_ARG_LIT("-no-kqemu"); + if (disableKVM) + ADD_ARG_LIT("-no-kvm"); ADD_ARG_LIT("-m"); ADD_ARG_LIT(memory); ADD_ARG_LIT("-smp"); Index: src/qemu_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/qemu_conf.h,v retrieving revision 1.58 diff -u -p -r1.58 qemu_conf.h --- src/qemu_conf.h 16 Mar 2009 13:54:26 -0000 1.58 +++ src/qemu_conf.h 16 Mar 2009 17:53:20 -0000 @@ -55,6 +55,7 @@ enum qemud_cmd_flags { QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP = (1 << 10), /* New migration syntax after merge to QEMU with TCP transport */ QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC = (1 << 11), /* New migration syntax after merge to QEMU with EXEC transport */ QEMUD_CMD_FLAG_DRIVE_CACHE_V2 = (1 << 12), /* Is the cache= flag wanting new v2 values */ + QEMUD_CMD_FLAG_KVM = (1 << 13), /* Whether KVM is compiled in */ }; /* Main driver state */ Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_driver.c,v retrieving revision 1.218 diff -u -p -r1.218 qemu_driver.c --- src/qemu_driver.c 16 Mar 2009 17:16:04 -0000 1.218 +++ src/qemu_driver.c 16 Mar 2009 17:53:20 -0000 @@ -1733,6 +1733,7 @@ qemudMonitorCommand(const virDomainObjPt static int qemudProbe(void) { if ((virFileExists("/usr/bin/qemu")) || + (virFileExists("/usr/bin/qemu-system-x86_64")) || (virFileExists("/usr/bin/qemu-kvm")) || (virFileExists("/usr/bin/kvm")) || (virFileExists("/usr/bin/xenner"))) @@ -1749,10 +1750,10 @@ static virDrvOpenStatus qemudOpen(virCon if (qemu_driver == NULL) goto decline; - if (!qemudProbe()) - goto decline; - if (conn->uri == NULL) { + if (!qemudProbe()) + goto decline; + conn->uri = xmlParseURI(uid ? "qemu:///session" : "qemu:///system"); if (!conn->uri) { virReportOOMError(conn); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Hi Dan, I'd like to ask about qemu-0.10.0: it already contains KVM support, BUT in contrary to std kvm userspace package, KVM support needs to be enabled by switch (while in kvm shipped userspace it's enabled by default and can by disabled by switch). How can I enable it when I want to use new qemu + with KVM enabled from libvirt? thanks a lot in advance... BR nik On Mon, Mar 16, 2009 at 06:03:59PM +0000, Daniel P. Berrange wrote:
Currently we are pretty strict about what emulator binary we allow for QEMU guests on x86 arches. In particular, for arch+domain type combos:
- i686+qemu must use 'qemu' binary - x86_64+qemu must use 'qemu-system-x86_64' binary - kvm must use 'qemu-kvm' or 'kvm' binaries - i686+kvm on x86_64 host is not allowed
These restrictions are overkill because
- i686+qemu could use 'qemu-system-x86_64' if '-cpu qemu32' is added - i686+qemu could use 'qemu-kvm' if '-cpu qemu32 -no-kvm' is added - x86_64+qemu could use 'qemu-kvm' if '-no-kvm' is added - i686+kvm on x86_64 host can be used if '-cpu qemu32' is added
This patch makes QEMU driver more flexible in this way when setting up its capabilities information. It also makes it aware of the -no-kvm and -cpu flag, using them where required by the os type + arch + emulator combinations specified in the guest XML.
This should finally remove the confusion where a user in virt-manager selectrs 'i686' and then wonders why we've disallowed choice of 'kvm'. It also fixes 'virsh version' when only qemu-kvm is installed.
The matrix should now work thus:
1. qemu, qemu-system-x86_64, qemu-kvm all available
qemu+i686 => qemu qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
2. qemu, qemu-kvm available
qemu+i686 => qemu qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
3. qemu-system-x86_64, qemu-kvm available
qemu+i686 => qemu-system-x86_64 -cpu qemu32 qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
4. qemu-kvm available
qemu+i686 => qemu-kvm -no-kvm -cpu qemu32 qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
The only real remaining problem is that we don't cope with scenario where the KVM enabled binary is called 'qemu-system-x64_64' instead of 'qemu-kvm' or 'kvm'.
Regards, Daniel
Index: src/qemu_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_conf.c,v retrieving revision 1.138 diff -u -p -r1.138 qemu_conf.c --- src/qemu_conf.c 16 Mar 2009 13:54:26 -0000 1.138 +++ src/qemu_conf.c 16 Mar 2009 17:53:20 -0000 @@ -211,6 +211,7 @@ struct qemu_arch_info { const char *const *machines; int nmachines; const char *binary; + const char *altbinary; const struct qemu_feature_flags *flags; int nflags; }; @@ -231,24 +232,24 @@ static const struct qemu_feature_flags c /* The archicture tables for supported QEMU archs */ static const struct qemu_arch_info const arch_info_hvm[] = { { "i686", 32, arch_info_hvm_x86_machines, 2, - "/usr/bin/qemu", arch_info_i686_flags, 4 }, + "/usr/bin/qemu", "/usr/bin/qemu-system-x86_64", arch_info_i686_flags, 4 }, { "x86_64", 64, arch_info_hvm_x86_machines, 2, - "/usr/bin/qemu-system-x86_64", arch_info_x86_64_flags, 2 }, + "/usr/bin/qemu-system-x86_64", NULL, arch_info_x86_64_flags, 2 }, { "mips", 32, arch_info_hvm_mips_machines, 1, - "/usr/bin/qemu-system-mips", NULL, 0 }, + "/usr/bin/qemu-system-mips", NULL, NULL, 0 }, { "mipsel", 32, arch_info_hvm_mips_machines, 1, - "/usr/bin/qemu-system-mipsel", NULL, 0 }, + "/usr/bin/qemu-system-mipsel", NULL, NULL, 0 }, { "sparc", 32, arch_info_hvm_sparc_machines, 1, - "/usr/bin/qemu-system-sparc", NULL, 0 }, + "/usr/bin/qemu-system-sparc", NULL, NULL, 0 }, { "ppc", 32, arch_info_hvm_ppc_machines, 3, - "/usr/bin/qemu-system-ppc", NULL, 0 }, + "/usr/bin/qemu-system-ppc", NULL, NULL, 0 }, };
static const struct qemu_arch_info const arch_info_xen[] = { { "i686", 32, arch_info_xen_x86_machines, 1, - "/usr/bin/xenner", arch_info_i686_flags, 4 }, + "/usr/bin/xenner", NULL, arch_info_i686_flags, 4 }, { "x86_64", 64, arch_info_xen_x86_machines, 1, - "/usr/bin/xenner", arch_info_x86_64_flags, 2 }, + "/usr/bin/xenner", NULL, arch_info_x86_64_flags, 2 }, };
static int @@ -257,43 +258,62 @@ qemudCapsInitGuest(virCapsPtr caps, const struct qemu_arch_info *info, int hvm) { virCapsGuestPtr guest; - int i, haskvm, hasbase, samearch; + int i; + int hasbase = 0; + int hasaltbase = 0; + int haskvm = 0; + int haskqemu = 0; const char *kvmbin = NULL;
- /* Check for existance of base emulator */ + /* Check for existance of base emulator, or alternate base + * which can be used with magic cpu choice + */ hasbase = (access(info->binary, X_OK) == 0); + hasaltbase = (access(info->altbinary, X_OK) == 0);
- samearch = STREQ(info->arch, hostmachine); - if (samearch) { + /* Can use acceleration for KVM/KQEMU if + * - host & guest arches match + * Or + * - hostarch is x86_64 and guest arch is i686 + * The latter simply needs "-cpu qemu32" + */ + if (STREQ(info->arch, hostmachine) || + (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) { const char *const kvmbins[] = { "/usr/bin/qemu-kvm", /* Fedora */ "/usr/bin/kvm" }; /* Upstream .spec */
for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) { - if ((haskvm = (access(kvmbins[i], X_OK) == 0))) { + if (access(kvmbins[i], X_OK) == 0 && + access("/dev/kvm", F_OK) == 0) { + haskvm = 1; kvmbin = kvmbins[i]; break; } } - } else { - haskvm = 0; + + if (access("/dev/kqemu", F_OK) == 0) + haskqemu = 1; }
- if (!hasbase && !haskvm) + + if (!hasbase && !hasaltbase && !haskvm) return 0;
+ /* We register kvm as the base emulator too, since we can + * just give -no-kvm to disable acceleration if required */ if ((guest = virCapabilitiesAddGuest(caps, hvm ? "hvm" : "xen", info->arch, info->wordsize, - info->binary, + (hasbase ? info->binary : + (hasaltbase ? info->altbinary : kvmbin)), NULL, info->nmachines, info->machines)) == NULL) return -1;
if (hvm) { - if (hasbase && - virCapabilitiesAddGuestDomain(guest, + if (virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, @@ -301,27 +321,23 @@ qemudCapsInitGuest(virCapsPtr caps, NULL) == NULL) return -1;
- /* If guest & host match, then we can accelerate */ - if (samearch) { - if (access("/dev/kqemu", F_OK) == 0 && - virCapabilitiesAddGuestDomain(guest, - "kqemu", - NULL, - NULL, - 0, - NULL) == NULL) - return -1; + if (haskqemu && + virCapabilitiesAddGuestDomain(guest, + "kqemu", + NULL, + NULL, + 0, + NULL) == NULL) + return -1;
- if (access("/dev/kvm", F_OK) == 0 && - haskvm && - virCapabilitiesAddGuestDomain(guest, - "kvm", - kvmbin, - NULL, - 0, - NULL) == NULL) - return -1; - } + if (haskvm && + virCapabilitiesAddGuestDomain(guest, + "kvm", + kvmbin, + NULL, + 0, + NULL) == NULL) + return -1; } else { if (virCapabilitiesAddGuestDomain(guest, "kvm", @@ -363,12 +379,14 @@ virCapsPtr qemudCapsInit(void) { if (virCapsInitNUMA(caps) < 0) goto no_memory;
+ /* First the pure HVM guests */ for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++) if (qemudCapsInitGuest(caps, utsname.machine, &arch_info_hvm[i], 1) < 0) goto no_memory;
+ /* Then possibly the Xen paravirt guests (ie Xenner */ if (access("/usr/bin/xenner", X_OK) == 0 && access("/dev/kvm", F_OK) == 0) { for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_xen) ; i++) @@ -430,6 +448,8 @@ int qemudExtractVersionInfo(const char *
if (strstr(help, "-no-kqemu")) flags |= QEMUD_CMD_FLAG_KQEMU; + if (strstr(help, "-no-kvm")) + flags |= QEMUD_CMD_FLAG_KVM; if (strstr(help, "-no-reboot")) flags |= QEMUD_CMD_FLAG_NO_REBOOT; if (strstr(help, "-name")) @@ -749,6 +769,7 @@ int qemudBuildCommandLine(virConnectPtr char boot[VIR_DOMAIN_BOOT_LAST]; struct utsname ut; int disableKQEMU = 0; + int disableKVM = 0; int qargc = 0, qarga = 0; const char **qargv = NULL; int qenvc = 0, qenva = 0; @@ -757,6 +778,7 @@ int qemudBuildCommandLine(virConnectPtr char uuid[VIR_UUID_STRING_BUFLEN]; char domid[50]; char *pidfile; + const char *cpu = NULL;
uname_normalize(&ut);
@@ -789,9 +811,16 @@ int qemudBuildCommandLine(virConnectPtr } }
+ emulator = vm->def->emulator; + if (!emulator) + emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps); + if (!emulator) + return -1; + + /* Need to explicitly disable KQEMU if * 1. Arch matches host arch - * 2. Guest is 'qemu' + * 2. Guest domain is 'qemu' * 3. The qemu binary has the -no-kqemu flag */ if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) && @@ -799,6 +828,34 @@ int qemudBuildCommandLine(virConnectPtr vm->def->virtType == VIR_DOMAIN_VIRT_QEMU) disableKQEMU = 1;
+ /* Need to explicitly disable KVM if + * 1. Arch matches host arch + * 2. Guest domain is 'qemu' + * 3. The qemu binary has the -no-kvm flag + */ + if ((qemuCmdFlags & QEMUD_CMD_FLAG_KVM) && + STREQ(ut.machine, vm->def->os.arch) && + vm->def->virtType == VIR_DOMAIN_VIRT_QEMU) + disableKVM = 1; + + /* + * Need to force a 32-bit guest CPU type if + * + * 1. guest OS is i686 + * 2. host OS is x86_64 + * 3. emulator is qemu-kvm or kvm + * + * Or + * + * 1. guest OS is i686 + * 2. emulator is qemu-system-x86_64 + */ + if (STREQ(vm->def->os.arch, "i686") && + ((STREQ(ut.machine, "x86_64") && + strstr(emulator, "kvm")) || + strstr(emulator, "x86_64"))) + cpu = "qemu32"; + #define ADD_ARG_SPACE \ do { \ if (qargc == qarga) { \ @@ -887,12 +944,6 @@ int qemudBuildCommandLine(virConnectPtr ADD_ENV_COPY("LOGNAME"); ADD_ENV_COPY("TMPDIR");
- emulator = vm->def->emulator; - if (!emulator) - emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps); - if (!emulator) - return -1; - ADD_ARG_LIT(emulator); ADD_ARG_LIT("-S");
@@ -904,9 +955,15 @@ int qemudBuildCommandLine(virConnectPtr ADD_ARG_LIT("-M"); ADD_ARG_LIT(vm->def->os.machine); } + if (cpu) { + ADD_ARG_LIT("-cpu"); + ADD_ARG_LIT(cpu); + }
if (disableKQEMU) ADD_ARG_LIT("-no-kqemu"); + if (disableKVM) + ADD_ARG_LIT("-no-kvm"); ADD_ARG_LIT("-m"); ADD_ARG_LIT(memory); ADD_ARG_LIT("-smp"); Index: src/qemu_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/qemu_conf.h,v retrieving revision 1.58 diff -u -p -r1.58 qemu_conf.h --- src/qemu_conf.h 16 Mar 2009 13:54:26 -0000 1.58 +++ src/qemu_conf.h 16 Mar 2009 17:53:20 -0000 @@ -55,6 +55,7 @@ enum qemud_cmd_flags { QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP = (1 << 10), /* New migration syntax after merge to QEMU with TCP transport */ QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC = (1 << 11), /* New migration syntax after merge to QEMU with EXEC transport */ QEMUD_CMD_FLAG_DRIVE_CACHE_V2 = (1 << 12), /* Is the cache= flag wanting new v2 values */ + QEMUD_CMD_FLAG_KVM = (1 << 13), /* Whether KVM is compiled in */ };
/* Main driver state */ Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_driver.c,v retrieving revision 1.218 diff -u -p -r1.218 qemu_driver.c --- src/qemu_driver.c 16 Mar 2009 17:16:04 -0000 1.218 +++ src/qemu_driver.c 16 Mar 2009 17:53:20 -0000 @@ -1733,6 +1733,7 @@ qemudMonitorCommand(const virDomainObjPt static int qemudProbe(void) { if ((virFileExists("/usr/bin/qemu")) || + (virFileExists("/usr/bin/qemu-system-x86_64")) || (virFileExists("/usr/bin/qemu-kvm")) || (virFileExists("/usr/bin/kvm")) || (virFileExists("/usr/bin/xenner"))) @@ -1749,10 +1750,10 @@ static virDrvOpenStatus qemudOpen(virCon if (qemu_driver == NULL) goto decline;
- if (!qemudProbe()) - goto decline; - if (conn->uri == NULL) { + if (!qemudProbe()) + goto decline; + conn->uri = xmlParseURI(uid ? "qemu:///session" : "qemu:///system"); if (!conn->uri) { virReportOOMError(conn);
-- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
-- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- ------------------------------------- Nikola CIPRICH LinuxBox.cz, s.r.o. 28. rijna 168, 709 01 Ostrava tel.: +420 596 603 142 fax: +420 596 621 273 mobil: +420 777 093 799 www.linuxbox.cz mobil servis: +420 737 238 656 email servis: servis@linuxbox.cz -------------------------------------

On Fri, Mar 20, 2009 at 08:23:46AM +0100, Nikola Ciprich wrote:
Hi Dan, I'd like to ask about qemu-0.10.0: it already contains KVM support, BUT in contrary to std kvm userspace package, KVM support needs to be enabled by switch (while in kvm shipped userspace it's enabled by default and can by disabled by switch). How can I enable it when I want to use new qemu + with KVM enabled from libvirt? thanks a lot in advance...
We don't have support for that yet - its one of the next things we need to sort out. To be honest you are still far better off using the separate KVM releases because they have better performance and functionality. The built-in KVM support in QEMU is still very much work in progress. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Mar 16, 2009 at 06:03:59PM +0000, Daniel P. Berrange wrote:
Currently we are pretty strict about what emulator binary we allow for QEMU guests on x86 arches. In particular, for arch+domain type combos:
- i686+qemu must use 'qemu' binary - x86_64+qemu must use 'qemu-system-x86_64' binary - kvm must use 'qemu-kvm' or 'kvm' binaries - i686+kvm on x86_64 host is not allowed
These restrictions are overkill because
- i686+qemu could use 'qemu-system-x86_64' if '-cpu qemu32' is added - i686+qemu could use 'qemu-kvm' if '-cpu qemu32 -no-kvm' is added - x86_64+qemu could use 'qemu-kvm' if '-no-kvm' is added - i686+kvm on x86_64 host can be used if '-cpu qemu32' is added
This patch makes QEMU driver more flexible in this way when setting up its capabilities information. It also makes it aware of the -no-kvm and -cpu flag, using them where required by the os type + arch + emulator combinations specified in the guest XML.
This should finally remove the confusion where a user in virt-manager selectrs 'i686' and then wonders why we've disallowed choice of 'kvm'. It also fixes 'virsh version' when only qemu-kvm is installed.
The matrix should now work thus:
1. qemu, qemu-system-x86_64, qemu-kvm all available
qemu+i686 => qemu qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
2. qemu, qemu-kvm available
qemu+i686 => qemu qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
3. qemu-system-x86_64, qemu-kvm available
qemu+i686 => qemu-system-x86_64 -cpu qemu32 qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
4. qemu-kvm available
qemu+i686 => qemu-kvm -no-kvm -cpu qemu32 qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
The only real remaining problem is that we don't cope with scenario where the KVM enabled binary is called 'qemu-system-x64_64' instead of 'qemu-kvm' or 'kvm'.
The confusion around this deserve a patch, and that sounds one way to get this solved ... but I find the approach "here is a hard coded path", then "oh we finally need to add a second hardcoded path" a bit worrying. This also doesn't cope with the occasional troubles where people have a binary outside of /usr/bin. Maybe some of this logic could be reduced and relying on configuration data would allow a fully flexible system (where the user can bite himself too, but heh), by suggesting architecture emulation binary names (with the above as the default) and a separate path list to lookup those binaries. Or we could just allow symlinks to be set in /usr/local/bin pointing to whatever the binaries names may be on that system or something approaching. But ACK, as is this solves the problem, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Fri, Mar 20, 2009 at 11:57:24AM +0100, Daniel Veillard wrote:
On Mon, Mar 16, 2009 at 06:03:59PM +0000, Daniel P. Berrange wrote:
Currently we are pretty strict about what emulator binary we allow for QEMU guests on x86 arches. In particular, for arch+domain type combos:
- i686+qemu must use 'qemu' binary - x86_64+qemu must use 'qemu-system-x86_64' binary - kvm must use 'qemu-kvm' or 'kvm' binaries - i686+kvm on x86_64 host is not allowed
These restrictions are overkill because
- i686+qemu could use 'qemu-system-x86_64' if '-cpu qemu32' is added - i686+qemu could use 'qemu-kvm' if '-cpu qemu32 -no-kvm' is added - x86_64+qemu could use 'qemu-kvm' if '-no-kvm' is added - i686+kvm on x86_64 host can be used if '-cpu qemu32' is added
This patch makes QEMU driver more flexible in this way when setting up its capabilities information. It also makes it aware of the -no-kvm and -cpu flag, using them where required by the os type + arch + emulator combinations specified in the guest XML.
This should finally remove the confusion where a user in virt-manager selectrs 'i686' and then wonders why we've disallowed choice of 'kvm'. It also fixes 'virsh version' when only qemu-kvm is installed.
The matrix should now work thus:
1. qemu, qemu-system-x86_64, qemu-kvm all available
qemu+i686 => qemu qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
2. qemu, qemu-kvm available
qemu+i686 => qemu qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
3. qemu-system-x86_64, qemu-kvm available
qemu+i686 => qemu-system-x86_64 -cpu qemu32 qemu+x86_64 => qemu-system-x86_64 kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
4. qemu-kvm available
qemu+i686 => qemu-kvm -no-kvm -cpu qemu32 qemu+x86_64 => qemu-kvm -no-kvm kvm+i686 => qemu-kvm -cpu qemu32 kvm+x86_64 => qemu-kvm
The only real remaining problem is that we don't cope with scenario where the KVM enabled binary is called 'qemu-system-x64_64' instead of 'qemu-kvm' or 'kvm'.
The confusion around this deserve a patch, and that sounds one way to get this solved ... but I find the approach "here is a hard coded path", then "oh we finally need to add a second hardcoded path" a bit worrying. This also doesn't cope with the occasional troubles where people have a binary outside of /usr/bin. Maybe some of this logic could be reduced and relying on configuration data would allow a fully flexible system (where the user can bite himself too, but heh), by suggesting architecture emulation binary names (with the above as the default) and a separate path list to lookup those binaries. Or we could just allow symlinks to be set in /usr/local/bin pointing to whatever the binaries names may be on that system or something approaching.
I agree, this approach we're currently using has pretty much reached the end of its practicality. In particular it is impossible to solve the problem of figuring out whether a plain 'qemu' binary supports kvm natively. To adress that, we'd actually need to run the binary and probe its output. This would require pretty much re-writing this entire capabilities setup logic from scratch. Similarly coping with varying path locations is another problem we can't easily solve with this current code. To address this I think we'd need to completely change the logic to do something like - For each directory in $PATH For each emulator name in (qemu, qemu-system-x864, etc) If emulator exists run $emulator -help So this lets us build up a list of all available emulators and their capabilities (eg, whether each supports qemu, kqemu, kvm).
From that list, we can then populate the list of supported combinations of guest, arch, domain type.
If we honour $PATH, then it probably wouldn't be neccessary to add config params for it.
But ACK, as is this solves the problem,
Ok, will commit it shortly. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Fri, Mar 20, 2009 at 11:18:57AM +0000, Daniel P. Berrange wrote:
To address this I think we'd need to completely change the logic to do something like
- For each directory in $PATH For each emulator name in (qemu, qemu-system-x864, etc) If emulator exists run $emulator -help
So this lets us build up a list of all available emulators and their capabilities (eg, whether each supports qemu, kqemu, kvm).
yes far more flexible, and introspection is the right way to assess capabilities. Agreed this sounds the way to go.
From that list, we can then populate the list of supported combinations of guest, arch, domain type.
If we honour $PATH, then it probably wouldn't be neccessary to add config params for it.
yes that would probably be sufficient, unless the admin did something really weird like using /usr/lib/libexec or something ... Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/
participants (3)
-
Daniel P. Berrange
-
Daniel Veillard
-
Nikola Ciprich