43fe83
From 9a68121178334ac95dd057c98a3b8922a243fb93 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <9a68121178334ac95dd057c98a3b8922a243fb93.1383922567.git.jdenemar@redhat.com>
43fe83
From: Peter Krempa <pkrempa@redhat.com>
43fe83
Date: Fri, 8 Nov 2013 12:33:35 +0100
43fe83
Subject: [PATCH] qemu: process: Validate specific CPUID flags of a guest
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=1008989
43fe83
43fe83
When starting a VM the qemu process may filter out some requested
43fe83
features of a domain as it's not supported either by the host or by
43fe83
qemu. Libvirt didn't check if this happened which might end up in
43fe83
changing of the guest ABI when migrating.
43fe83
43fe83
The proof of concept implementation adds the check for the recently
43fe83
introduced kvm_pv_unhalt cpuid feature bit. This feature depends on both
43fe83
qemu and host kernel support and thus increase the possibility of guest
43fe83
ABI breakage.
43fe83
43fe83
(cherry picked from commit d94b7817719b064849818b9ba6c37e403b7c003c)
43fe83
43fe83
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
43fe83
---
43fe83
 src/qemu/qemu_process.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
43fe83
 1 file changed, 46 insertions(+)
43fe83
43fe83
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
43fe83
index e0097df..40e3754 100644
43fe83
--- a/src/qemu/qemu_process.c
43fe83
+++ b/src/qemu/qemu_process.c
43fe83
@@ -43,6 +43,7 @@
43fe83
 #include "qemu_bridge_filter.h"
43fe83
 #include "qemu_migration.h"
43fe83
 
43fe83
+#include "cpu/cpu.h"
43fe83
 #include "datatypes.h"
43fe83
 #include "virlog.h"
43fe83
 #include "virerror.h"
43fe83
@@ -3437,6 +3438,47 @@ qemuValidateCpuMax(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
43fe83
     return true;
43fe83
 }
43fe83
 
43fe83
+
43fe83
+static bool
43fe83
+qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, virDomainObjPtr vm)
43fe83
+{
43fe83
+    virDomainDefPtr def = vm->def;
43fe83
+    virArch arch = def->os.arch;
43fe83
+    virCPUDataPtr guestcpu = NULL;
43fe83
+    qemuDomainObjPrivatePtr priv = vm->privateData;
43fe83
+    bool ret = false;
43fe83
+
43fe83
+    switch (arch) {
43fe83
+    case VIR_ARCH_I686:
43fe83
+    case VIR_ARCH_X86_64:
43fe83
+        qemuDomainObjEnterMonitor(driver, vm);
43fe83
+        guestcpu = qemuMonitorGetGuestCPU(priv->mon, arch);
43fe83
+        qemuDomainObjExitMonitor(driver, vm);
43fe83
+
43fe83
+        if (!(guestcpu))
43fe83
+            goto cleanup;
43fe83
+
43fe83
+        if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] == VIR_DOMAIN_FEATURE_STATE_ON) {
43fe83
+            if (!cpuHasFeature(guestcpu, VIR_CPU_x86_KVM_PV_UNHALT)) {
43fe83
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
43fe83
+                               _("host doesn't support paravirtual spinlocks"));
43fe83
+                goto cleanup;
43fe83
+            }
43fe83
+        }
43fe83
+        break;
43fe83
+
43fe83
+    default:
43fe83
+        break;
43fe83
+    }
43fe83
+
43fe83
+    ret = true;
43fe83
+
43fe83
+cleanup:
43fe83
+    cpuDataFree(guestcpu);
43fe83
+    return ret;
43fe83
+}
43fe83
+
43fe83
+
43fe83
 int qemuProcessStart(virConnectPtr conn,
43fe83
                      virQEMUDriverPtr driver,
43fe83
                      virDomainObjPtr vm,
43fe83
@@ -3904,6 +3946,10 @@ int qemuProcessStart(virConnectPtr conn,
43fe83
         priv->agentError = true;
43fe83
     }
43fe83
 
43fe83
+    VIR_DEBUG("Detecting if required emulator features are present");
43fe83
+    if (!qemuProcessVerifyGuestCPU(driver, vm))
43fe83
+        goto cleanup;
43fe83
+
43fe83
     VIR_DEBUG("Detecting VCPU PIDs");
43fe83
     if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
43fe83
         goto cleanup;
43fe83
-- 
43fe83
1.8.4.2
43fe83