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(a)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
mobil servis: +420 737 238 656
email servis: servis(a)linuxbox.cz
-------------------------------------