[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