More flexible setup of QEMU capabilities/emulators

This commit is contained in:
Daniel P. Berrange 2009-03-20 11:20:26 +00:00
parent 0ad4ece725
commit b75a469852
3 changed files with 113 additions and 46 deletions

View File

@ -1,3 +1,12 @@
Fri Mar 20 11:21:40 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
Make use of emulator binaries more flexible
* src/qemu_conf.h: Add flag for -no-kvm option
* src/qemu_conf.c: Allow i686 on x86_64 for KVM guests using
-cpu flag. Allow qemu-system-x86_64 to be used for 32-bit
guests. Allow KVM binary to be used for non-KVM guests using
-no-kvm flag
Thu Mar 19 15:25:40 CET 2009 Daniel Veillard <veillard@redhat.com> Thu Mar 19 15:25:40 CET 2009 Daniel Veillard <veillard@redhat.com>
* docs/schemas/domain.rng: extend definition for security attributes * docs/schemas/domain.rng: extend definition for security attributes

View File

@ -211,6 +211,7 @@ struct qemu_arch_info {
const char *const *machines; const char *const *machines;
int nmachines; int nmachines;
const char *binary; const char *binary;
const char *altbinary;
const struct qemu_feature_flags *flags; const struct qemu_feature_flags *flags;
int nflags; int nflags;
}; };
@ -231,24 +232,24 @@ static const struct qemu_feature_flags const arch_info_x86_64_flags [] = {
/* The archicture tables for supported QEMU archs */ /* The archicture tables for supported QEMU archs */
static const struct qemu_arch_info const arch_info_hvm[] = { static const struct qemu_arch_info const arch_info_hvm[] = {
{ "i686", 32, arch_info_hvm_x86_machines, 2, { "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, { "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, { "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, { "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, { "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, { "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[] = { static const struct qemu_arch_info const arch_info_xen[] = {
{ "i686", 32, arch_info_xen_x86_machines, 1, { "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, { "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 static int
@ -257,43 +258,62 @@ qemudCapsInitGuest(virCapsPtr caps,
const struct qemu_arch_info *info, const struct qemu_arch_info *info,
int hvm) { int hvm) {
virCapsGuestPtr guest; 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; 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); hasbase = (access(info->binary, X_OK) == 0);
hasaltbase = (access(info->altbinary, X_OK) == 0);
samearch = STREQ(info->arch, hostmachine); /* Can use acceleration for KVM/KQEMU if
if (samearch) { * - 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 */ const char *const kvmbins[] = { "/usr/bin/qemu-kvm", /* Fedora */
"/usr/bin/kvm" }; /* Upstream .spec */ "/usr/bin/kvm" }; /* Upstream .spec */
for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) { 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]; kvmbin = kvmbins[i];
break; break;
} }
} }
} else {
haskvm = 0; if (access("/dev/kqemu", F_OK) == 0)
haskqemu = 1;
} }
if (!hasbase && !haskvm)
if (!hasbase && !hasaltbase && !haskvm)
return 0; 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, if ((guest = virCapabilitiesAddGuest(caps,
hvm ? "hvm" : "xen", hvm ? "hvm" : "xen",
info->arch, info->arch,
info->wordsize, info->wordsize,
info->binary, (hasbase ? info->binary :
(hasaltbase ? info->altbinary : kvmbin)),
NULL, NULL,
info->nmachines, info->nmachines,
info->machines)) == NULL) info->machines)) == NULL)
return -1; return -1;
if (hvm) { if (hvm) {
if (hasbase && if (virCapabilitiesAddGuestDomain(guest,
virCapabilitiesAddGuestDomain(guest,
"qemu", "qemu",
NULL, NULL,
NULL, NULL,
@ -301,27 +321,23 @@ qemudCapsInitGuest(virCapsPtr caps,
NULL) == NULL) NULL) == NULL)
return -1; return -1;
/* If guest & host match, then we can accelerate */ if (haskqemu &&
if (samearch) { virCapabilitiesAddGuestDomain(guest,
if (access("/dev/kqemu", F_OK) == 0 && "kqemu",
virCapabilitiesAddGuestDomain(guest, NULL,
"kqemu", NULL,
NULL, 0,
NULL, NULL) == NULL)
0, return -1;
NULL) == NULL)
return -1;
if (access("/dev/kvm", F_OK) == 0 && if (haskvm &&
haskvm && virCapabilitiesAddGuestDomain(guest,
virCapabilitiesAddGuestDomain(guest, "kvm",
"kvm", kvmbin,
kvmbin, NULL,
NULL, 0,
0, NULL) == NULL)
NULL) == NULL) return -1;
return -1;
}
} else { } else {
if (virCapabilitiesAddGuestDomain(guest, if (virCapabilitiesAddGuestDomain(guest,
"kvm", "kvm",
@ -363,12 +379,14 @@ virCapsPtr qemudCapsInit(void) {
if (virCapsInitNUMA(caps) < 0) if (virCapsInitNUMA(caps) < 0)
goto no_memory; goto no_memory;
/* First the pure HVM guests */
for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++) for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++)
if (qemudCapsInitGuest(caps, if (qemudCapsInitGuest(caps,
utsname.machine, utsname.machine,
&arch_info_hvm[i], 1) < 0) &arch_info_hvm[i], 1) < 0)
goto no_memory; goto no_memory;
/* Then possibly the Xen paravirt guests (ie Xenner */
if (access("/usr/bin/xenner", X_OK) == 0 && if (access("/usr/bin/xenner", X_OK) == 0 &&
access("/dev/kvm", F_OK) == 0) { access("/dev/kvm", F_OK) == 0) {
for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_xen) ; i++) for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_xen) ; i++)
@ -430,6 +448,8 @@ int qemudExtractVersionInfo(const char *qemu,
if (strstr(help, "-no-kqemu")) if (strstr(help, "-no-kqemu"))
flags |= QEMUD_CMD_FLAG_KQEMU; flags |= QEMUD_CMD_FLAG_KQEMU;
if (strstr(help, "-no-kvm"))
flags |= QEMUD_CMD_FLAG_KVM;
if (strstr(help, "-no-reboot")) if (strstr(help, "-no-reboot"))
flags |= QEMUD_CMD_FLAG_NO_REBOOT; flags |= QEMUD_CMD_FLAG_NO_REBOOT;
if (strstr(help, "-name")) if (strstr(help, "-name"))
@ -749,6 +769,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
char boot[VIR_DOMAIN_BOOT_LAST]; char boot[VIR_DOMAIN_BOOT_LAST];
struct utsname ut; struct utsname ut;
int disableKQEMU = 0; int disableKQEMU = 0;
int disableKVM = 0;
int qargc = 0, qarga = 0; int qargc = 0, qarga = 0;
const char **qargv = NULL; const char **qargv = NULL;
int qenvc = 0, qenva = 0; int qenvc = 0, qenva = 0;
@ -757,6 +778,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
char uuid[VIR_UUID_STRING_BUFLEN]; char uuid[VIR_UUID_STRING_BUFLEN];
char domid[50]; char domid[50];
char *pidfile; char *pidfile;
const char *cpu = NULL;
uname_normalize(&ut); uname_normalize(&ut);
@ -789,9 +811,16 @@ int qemudBuildCommandLine(virConnectPtr conn,
} }
} }
emulator = vm->def->emulator;
if (!emulator)
emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
if (!emulator)
return -1;
/* Need to explicitly disable KQEMU if /* Need to explicitly disable KQEMU if
* 1. Arch matches host arch * 1. Arch matches host arch
* 2. Guest is 'qemu' * 2. Guest domain is 'qemu'
* 3. The qemu binary has the -no-kqemu flag * 3. The qemu binary has the -no-kqemu flag
*/ */
if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) && if ((qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
@ -799,6 +828,34 @@ int qemudBuildCommandLine(virConnectPtr conn,
vm->def->virtType == VIR_DOMAIN_VIRT_QEMU) vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
disableKQEMU = 1; 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 \ #define ADD_ARG_SPACE \
do { \ do { \
if (qargc == qarga) { \ if (qargc == qarga) { \
@ -887,12 +944,6 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ENV_COPY("LOGNAME"); ADD_ENV_COPY("LOGNAME");
ADD_ENV_COPY("TMPDIR"); 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(emulator);
ADD_ARG_LIT("-S"); ADD_ARG_LIT("-S");
@ -904,9 +955,15 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT("-M"); ADD_ARG_LIT("-M");
ADD_ARG_LIT(vm->def->os.machine); ADD_ARG_LIT(vm->def->os.machine);
} }
if (cpu) {
ADD_ARG_LIT("-cpu");
ADD_ARG_LIT(cpu);
}
if (disableKQEMU) if (disableKQEMU)
ADD_ARG_LIT("-no-kqemu"); ADD_ARG_LIT("-no-kqemu");
if (disableKVM)
ADD_ARG_LIT("-no-kvm");
ADD_ARG_LIT("-m"); ADD_ARG_LIT("-m");
ADD_ARG_LIT(memory); ADD_ARG_LIT(memory);
ADD_ARG_LIT("-smp"); ADD_ARG_LIT("-smp");

View File

@ -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_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_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_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 */ /* Main driver state */