qemu: Add check for whether KVM nesting is enabled

Support for nested KVM is handled via a kernel module configuration
parameters values for kvm_intel, kvm_amd, kvm_hv (PPC), or kvm (s390).
While it's possible to fetch the kmod config values via virKModConfig,
unfortunately that is the static value and we need to get the
current/dynamic value from the kernel file system.

So this patch adds a new API virHostKVMSupportsNesting that will
search the 3 kernel modules to get the nesting value and check if
it is 'Y' (or 'y' just in case) to return a true/false whether
the KVM kernel supports nesting.

We need to do this in order to handle cases where adjustments to
the value are made after libvirtd is started to force a refetch of
the latest QEMU capabilities since the correct CPU settings need
to be made for a guest to add the "vmx=on" to/for the guest config.

Signed-off-by: John Ferlan <jferlan@redhat.com>
ACKed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
John Ferlan 2018-11-12 14:58:09 -05:00
parent e0eb8a8a69
commit b183a75319

View File

@ -559,6 +559,7 @@ struct _virQEMUCaps {
virObject parent;
bool usedQMP;
bool kvmSupportsNesting;
char *binary;
time_t ctime;
@ -1532,6 +1533,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
return NULL;
ret->usedQMP = qemuCaps->usedQMP;
ret->kvmSupportsNesting = qemuCaps->kvmSupportsNesting;
if (VIR_STRDUP(ret->binary, qemuCaps->binary) < 0)
goto error;
@ -3591,6 +3593,9 @@ virQEMUCapsLoadCache(virArch hostArch,
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
if (virXPathBoolean("boolean(./kvmSupportsNesting)", ctxt) > 0)
qemuCaps->kvmSupportsNesting = true;
ret = 0;
cleanup:
VIR_FREE(str);
@ -3810,6 +3815,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
if (qemuCaps->sevCapabilities)
virQEMUCapsFormatSEVInfo(qemuCaps, &buf);
if (qemuCaps->kvmSupportsNesting)
virBufferAddLit(&buf, "<kvmSupportsNesting/>\n");
virBufferAdjustIndent(&buf, -2);
virBufferAddLit(&buf, "</qemuCaps>\n");
@ -3850,6 +3858,41 @@ virQEMUCapsSaveFile(void *data,
}
/* Check the kernel module parameters 'nested' file to determine if enabled
*
* Intel: 'kvm_intel' uses 'Y'
* AMD: 'kvm_amd' uses '1'
* PPC64: 'kvm_hv' uses 'Y'
* S390: 'kvm' uses '1'
*/
static bool
virQEMUCapsKVMSupportsNesting(void)
{
static char const * const kmod[] = {"kvm_intel", "kvm_amd",
"kvm_hv", "kvm"};
VIR_AUTOFREE(char *) value = NULL;
int rc;
size_t i;
for (i = 0; i < ARRAY_CARDINALITY(kmod); i++) {
VIR_FREE(value);
rc = virFileReadValueString(&value, "/sys/module/%s/parameters/nested",
kmod[i]);
if (rc == -2)
continue;
if (rc < 0) {
virResetLastError();
return false;
}
if (value[0] == 'Y' || value[0] == 'y' || value[0] == '1')
return true;
}
return false;
}
static bool
virQEMUCapsIsValid(void *data,
void *privData)
@ -3858,6 +3901,7 @@ virQEMUCapsIsValid(void *data,
virQEMUCapsCachePrivPtr priv = privData;
bool kvmUsable;
struct stat sb;
bool kvmSupportsNesting;
if (!qemuCaps->binary)
return true;
@ -3935,6 +3979,14 @@ virQEMUCapsIsValid(void *data,
qemuCaps->kernelVersion);
return false;
}
kvmSupportsNesting = virQEMUCapsKVMSupportsNesting();
if (kvmSupportsNesting != qemuCaps->kvmSupportsNesting) {
VIR_DEBUG("Outdated capabilities for '%s': kvm kernel nested "
"value changed from %d",
qemuCaps->binary, qemuCaps->kvmSupportsNesting);
return false;
}
}
return true;
@ -4579,6 +4631,8 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
if (VIR_STRDUP(qemuCaps->kernelVersion, kernelVersion) < 0)
goto error;
qemuCaps->kvmSupportsNesting = virQEMUCapsKVMSupportsNesting();
}
cleanup: