]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
More flexible setup of QEMU capabilities/emulators
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 20 Mar 2009 11:20:26 +0000 (11:20 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 20 Mar 2009 11:20:26 +0000 (11:20 +0000)
ChangeLog
src/qemu_conf.c
src/qemu_conf.h

index 8b94f0e96e56ea38bb3cf0efcdaf16db95eb8efa..b5a05fe8832706f6edc2d8bf759fbc19cf69613f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * docs/schemas/domain.rng: extend definition for security attributes
index 9371b02ca9144575e05941763b7f3b020df27713..9727a1501930430cec82462841a347578f6ebd8e 100644 (file)
@@ -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 const arch_info_x86_64_flags [] = {
 /* 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 *qemu,
 
     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 conn,
     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 conn,
     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 conn,
         }
     }
 
+    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 conn,
         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 conn,
     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 conn,
         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 d676a80dd78d05824cf63a0d6eae9f98fb62f412..70fe9c89c6aa2405b9e34c7341d6e9e9a24088fc 100644 (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_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 */