File qemu-caps.patch of Package libvirt

commit b75a469852ee791fb2e7a831c4f86957ad44f419
Author: Daniel P. Berrange <berrange@redhat.com>
Date:   Fri Mar 20 11:20:26 2009 +0000

    More flexible setup of QEMU capabilities/emulators

Index: libvirt-0.4.6/src/qemu_conf.c
===================================================================
--- libvirt-0.4.6.orig/src/qemu_conf.c
+++ libvirt-0.4.6/src/qemu_conf.c
@@ -180,6 +180,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;
 };
@@ -200,24 +201,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
@@ -226,43 +227,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,
@@ -270,27 +290,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",
@@ -388,12 +404,14 @@ virCapsPtr qemudCapsInit(void) {
     if (qemudCapsInitNUMA(caps) < 0)
         goto no_memory;
 
+    /* First the pure HVM guests */
     for (i = 0 ; i < (sizeof(arch_info_hvm)/sizeof(arch_info_hvm[0])) ; 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 < (sizeof(arch_info_xen)/sizeof(arch_info_xen[0])) ; i++)
@@ -452,6 +470,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"))
@@ -726,9 +746,11 @@ int qemudBuildCommandLine(virConnectPtr
     virDomainChrDefPtr parallel = vm->def->parallels;
     struct utsname ut;
     int disableKQEMU = 0;
+    int disableKVM = 0;
     int qargc = 0, qarga = 0;
     const char **qargv = NULL;
     const char *emulator;
+    const char *cpu = NULL;
 
     uname(&ut);
 
@@ -739,9 +761,16 @@ int qemudBuildCommandLine(virConnectPtr
         !ut.machine[4])
         ut.machine[1] = '6';
 
+    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) &&
@@ -749,6 +778,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) {                                           \
@@ -784,18 +841,20 @@ int qemudBuildCommandLine(virConnectPtr
     snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024);
     snprintf(vcpus, sizeof(vcpus), "%lu", vm->def->vcpus);
 
-    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");
-    ADD_ARG_LIT("-M");
-    ADD_ARG_LIT(vm->def->os.machine);
+    if (vm->def->os.machine) {
+        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: libvirt-0.4.6/src/qemu_conf.h
===================================================================
--- libvirt-0.4.6.orig/src/qemu_conf.h
+++ libvirt-0.4.6/src/qemu_conf.h
@@ -45,6 +45,7 @@ enum qemud_cmd_flags {
     QEMUD_CMD_FLAG_DRIVE          = (1 << 3),
     QEMUD_CMD_FLAG_DRIVE_BOOT     = (1 << 4),
     QEMUD_CMD_FLAG_NAME           = (1 << 5),
+    QEMUD_CMD_FLAG_KVM            = (1 << 13), /* Whether KVM is compiled in */
 };
 
 /* Main driver state */
openSUSE Build Service is sponsored by