render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
9c6c51
From 2e68dbce9f8d49e57a0e16a202483b59e9497054 Mon Sep 17 00:00:00 2001
9c6c51
Message-Id: <2e68dbce9f8d49e57a0e16a202483b59e9497054@dist-git>
9c6c51
From: John Ferlan <jferlan@redhat.com>
9c6c51
Date: Thu, 13 Dec 2018 10:54:33 -0500
9c6c51
Subject: [PATCH] qemu: Add check for whether KVM nesting is enabled
9c6c51
9c6c51
https://bugzilla.redhat.com/show_bug.cgi?id=1645139
9c6c51
9c6c51
Support for nested KVM is handled via a kernel module configuration
9c6c51
parameters values for kvm_intel, kvm_amd, kvm_hv (PPC), or kvm (s390).
9c6c51
While it's possible to fetch the kmod config values via virKModConfig,
9c6c51
unfortunately that is the static value and we need to get the
9c6c51
current/dynamic value from the kernel file system.
9c6c51
9c6c51
So this patch adds a new API virHostKVMSupportsNesting that will
9c6c51
search the 3 kernel modules to get the nesting value and check if
9c6c51
it is 'Y' (or 'y' just in case) to return a true/false whether
9c6c51
the KVM kernel supports nesting.
9c6c51
9c6c51
We need to do this in order to handle cases where adjustments to
9c6c51
the value are made after libvirtd is started to force a refetch of
9c6c51
the latest QEMU capabilities since the correct CPU settings need
9c6c51
to be made for a guest to add the "vmx=on" to/for the guest config.
9c6c51
9c6c51
Signed-off-by: John Ferlan <jferlan@redhat.com>
9c6c51
ACKed-by: Michal Privoznik <mprivozn@redhat.com>
9c6c51
(cherry picked from commit b183a75319b90d0af5512be513743e1eab950612)
9c6c51
9c6c51
NB:
9c6c51
Handled merge/build conflict/issue where VIR_AUTOFREE isn't defined
9c6c51
(or backported to RHEL git).  So rather than relying on the automatic
9c6c51
free of memory, prior to each possible return add a VIR_FREE. It was
9c6c51
that or adjust the logic to set a retval and use goto cleanup type
9c6c51
logic. This way just seemed cleaner.
9c6c51
9c6c51
Signed-off-by: John Ferlan <jferlan@redhat.com>
9c6c51
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
9c6c51
---
9c6c51
 src/qemu/qemu_capabilities.c | 58 ++++++++++++++++++++++++++++++++++++
9c6c51
 1 file changed, 58 insertions(+)
9c6c51
9c6c51
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
9c6c51
index 57b1b99076..ba8c717e22 100644
9c6c51
--- a/src/qemu/qemu_capabilities.c
9c6c51
+++ b/src/qemu/qemu_capabilities.c
9c6c51
@@ -550,6 +550,7 @@ struct _virQEMUCaps {
9c6c51
     virObject parent;
9c6c51
 
9c6c51
     bool usedQMP;
9c6c51
+    bool kvmSupportsNesting;
9c6c51
 
9c6c51
     char *binary;
9c6c51
     time_t ctime;
9c6c51
@@ -1606,6 +1607,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
9c6c51
         return NULL;
9c6c51
 
9c6c51
     ret->usedQMP = qemuCaps->usedQMP;
9c6c51
+    ret->kvmSupportsNesting = qemuCaps->kvmSupportsNesting;
9c6c51
 
9c6c51
     if (VIR_STRDUP(ret->binary, qemuCaps->binary) < 0)
9c6c51
         goto error;
9c6c51
@@ -3597,6 +3599,9 @@ virQEMUCapsLoadCache(virArch hostArch,
9c6c51
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
9c6c51
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
9c6c51
 
9c6c51
+    if (virXPathBoolean("boolean(./kvmSupportsNesting)", ctxt) > 0)
9c6c51
+        qemuCaps->kvmSupportsNesting = true;
9c6c51
+
9c6c51
     ret = 0;
9c6c51
  cleanup:
9c6c51
     VIR_FREE(str);
9c6c51
@@ -3813,6 +3818,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
9c6c51
     if (qemuCaps->sevCapabilities)
9c6c51
         virQEMUCapsFormatSEVInfo(qemuCaps, &buf;;
9c6c51
 
9c6c51
+    if (qemuCaps->kvmSupportsNesting)
9c6c51
+        virBufferAddLit(&buf, "<kvmSupportsNesting/>\n");
9c6c51
+
9c6c51
     virBufferAdjustIndent(&buf, -2);
9c6c51
     virBufferAddLit(&buf, "</qemuCaps>\n");
9c6c51
 
9c6c51
@@ -3853,6 +3861,45 @@ virQEMUCapsSaveFile(void *data,
9c6c51
 }
9c6c51
 
9c6c51
 
9c6c51
+/* Check the kernel module parameters 'nested' file to determine if enabled
9c6c51
+ *
9c6c51
+ *   Intel: 'kvm_intel' uses 'Y'
9c6c51
+ *   AMD:   'kvm_amd' uses '1'
9c6c51
+ *   PPC64: 'kvm_hv' uses 'Y'
9c6c51
+ *   S390:  'kvm' uses '1'
9c6c51
+ */
9c6c51
+static bool
9c6c51
+virQEMUCapsKVMSupportsNesting(void)
9c6c51
+{
9c6c51
+    static char const * const kmod[] = {"kvm_intel", "kvm_amd",
9c6c51
+                                        "kvm_hv", "kvm"};
9c6c51
+    char * value = NULL;
9c6c51
+    int rc;
9c6c51
+    size_t i;
9c6c51
+
9c6c51
+    for (i = 0; i < ARRAY_CARDINALITY(kmod); i++) {
9c6c51
+        VIR_FREE(value);
9c6c51
+        rc = virFileReadValueString(&value, "/sys/module/%s/parameters/nested",
9c6c51
+                                    kmod[i]);
9c6c51
+        if (rc == -2)
9c6c51
+            continue;
9c6c51
+        if (rc < 0) {
9c6c51
+            virResetLastError();
9c6c51
+            VIR_FREE(value);
9c6c51
+            return false;
9c6c51
+        }
9c6c51
+
9c6c51
+        if (value[0] == 'Y' || value[0] == 'y' || value[0] == '1') {
9c6c51
+            VIR_FREE(value);
9c6c51
+            return true;
9c6c51
+        }
9c6c51
+    }
9c6c51
+
9c6c51
+    VIR_FREE(value);
9c6c51
+    return false;
9c6c51
+}
9c6c51
+
9c6c51
+
9c6c51
 static bool
9c6c51
 virQEMUCapsIsValid(void *data,
9c6c51
                    void *privData)
9c6c51
@@ -3861,6 +3908,7 @@ virQEMUCapsIsValid(void *data,
9c6c51
     virQEMUCapsCachePrivPtr priv = privData;
9c6c51
     bool kvmUsable;
9c6c51
     struct stat sb;
9c6c51
+    bool kvmSupportsNesting;
9c6c51
 
9c6c51
     if (!qemuCaps->binary)
9c6c51
         return true;
9c6c51
@@ -3938,6 +3986,14 @@ virQEMUCapsIsValid(void *data,
9c6c51
                       qemuCaps->kernelVersion);
9c6c51
             return false;
9c6c51
         }
9c6c51
+
9c6c51
+        kvmSupportsNesting = virQEMUCapsKVMSupportsNesting();
9c6c51
+        if (kvmSupportsNesting != qemuCaps->kvmSupportsNesting) {
9c6c51
+            VIR_DEBUG("Outdated capabilities for '%s': kvm kernel nested "
9c6c51
+                      "value changed from %d",
9c6c51
+                     qemuCaps->binary, qemuCaps->kvmSupportsNesting);
9c6c51
+            return false;
9c6c51
+        }
9c6c51
     }
9c6c51
 
9c6c51
     return true;
9c6c51
@@ -4591,6 +4647,8 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
9c6c51
 
9c6c51
         if (VIR_STRDUP(qemuCaps->kernelVersion, kernelVersion) < 0)
9c6c51
             goto error;
9c6c51
+
9c6c51
+        qemuCaps->kvmSupportsNesting = virQEMUCapsKVMSupportsNesting();
9c6c51
     }
9c6c51
 
9c6c51
  cleanup:
9c6c51
-- 
9c6c51
2.20.1
9c6c51