[libvirt] [PATCH v3] qemu: Add check for whether KVM nesting is enabled
John Ferlan
jferlan at redhat.com
Thu Dec 6 12:40:52 UTC 2018
ping?
Thanks -
John
On 11/28/18 8:55 PM, John Ferlan wrote:
> 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) or '1' 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 at redhat.com>
>
> NB to be removed before push - I got data from:
>
> (IBM Z) https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/appe-kvm_on_zsystems
>
> (PPC slide 131) https://events.linuxfoundation.org/wp-content/uploads/2017/12/Taking-it-to-the-Nest-Level-Nested-KVM-on-the-POWER9-Processor-Suraj-Jitindar-Singh-IBM.pdf
>
> Signed-off-by: John Ferlan <jferlan at redhat.com>
> ---
>
> v2: https://www.redhat.com/archives/libvir-list/2018-November/msg00955.html
>
> Changes from code review...
> - Rename variables/API's to KVMSupportsNested
> - Movement of logic to check/set the 'nested' to inside locations that
> ensure KVM was enabled (via capability).
> - Change of logic to not use virKModConfig and instead look at the
> running kernel value for /sys/module/*/parameters/nested where *
> is kvm_intel, kvm_amd, kvm_hv, or kvm
>
> src/qemu/qemu_capabilities.c | 54 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 54 insertions(+)
>
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index 20a1a0c201..bef92a679f 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -558,6 +558,7 @@ struct _virQEMUCaps {
> virObject parent;
>
> bool usedQMP;
> + bool kvmSupportsNesting;
>
> char *binary;
> time_t ctime;
> @@ -1530,6 +1531,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;
> @@ -3589,6 +3591,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);
> @@ -3808,6 +3813,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
> if (qemuCaps->sevCapabilities)
> virQEMUCapsFormatSEVInfo(qemuCaps, &buf);
>
> + if (qemuCaps->kvmSupportsNesting)
> + virBufferAddLit(&buf, "<kvmSupportsNesting/>\n");
> +
> virBufferAdjustIndent(&buf, -2);
> virBufferAddLit(&buf, "</qemuCaps>\n");
>
> @@ -3848,6 +3856,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)
> @@ -3856,6 +3899,7 @@ virQEMUCapsIsValid(void *data,
> virQEMUCapsCachePrivPtr priv = privData;
> bool kvmUsable;
> struct stat sb;
> + bool kvmSupportsNesting;
>
> if (!qemuCaps->binary)
> return true;
> @@ -3933,6 +3977,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;
> @@ -4576,6 +4628,8 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
>
> if (VIR_STRDUP(qemuCaps->kernelVersion, kernelVersion) < 0)
> goto error;
> +
> + qemuCaps->kvmSupportsNesting = virQEMUCapsKVMSupportsNesting();
> }
>
> cleanup:
>
More information about the libvir-list
mailing list