|
|
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 |
|