[libvirt] [PATCH] Enable support for nested SVM

Dave Allan dallan at redhat.com
Wed Sep 22 18:19:06 UTC 2010


On Wed, Sep 22, 2010 at 05:47:42PM +0100, Daniel P. Berrange wrote:
> This enables support for nested SVM using the regular CPU
> model/features block. If the CPU model or features include
> 'svm' or 'vmx', then the '-enable-nesting' flag will be
> added to the QEMU command line. Several of the models
> already include svm support, but QEMU was just masking out
> the svm bit silently. So this will enable SVM on such
> models

I'm very glad to see this patch, as I've wanted to run nested VMs on
my development VM for a while.  Can you give a little more information
on what's required to run a nested VM?

Dave


> * src/qemu/qemu_conf.h: flag for -enable-nesting
> * src/qemu/qemu_conf.c: Use -enable-nesting if VMX or SVM are in
>   the CPUID
> * src/cpu/cpu.h, src/cpu/cpu.c: API to check for a named feature
> * src/cpu/cpu_x86.c: x86 impl of feature check
> * src/libvirt_private.syms: Add cpuHasFeature
> ---
>  src/cpu/cpu.c            |   24 ++++++++++++++++++++++
>  src/cpu/cpu.h            |   12 +++++++++++
>  src/cpu/cpu_x86.c        |   50 ++++++++++++++++++++++++++++++++++++++++++++++
>  src/libvirt_private.syms |    1 +
>  src/qemu/qemu_conf.c     |   19 +++++++++++++++-
>  src/qemu/qemu_conf.h     |    1 +
>  6 files changed, 105 insertions(+), 2 deletions(-)
> 
> diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
> index def6974..c7a282e 100644
> --- a/src/cpu/cpu.c
> +++ b/src/cpu/cpu.c
> @@ -424,3 +424,27 @@ cpuUpdate(virCPUDefPtr guest,
>  
>      return driver->update(guest, host);
>  }
> +
> +bool
> +cpuHasFeature(const char *arch,
> +              const union cpuData *data,
> +              const char *feature)
> +{
> +    struct cpuArchDriver *driver;
> +
> +    VIR_DEBUG("arch=%s, data=%p, feature=%s",
> +              arch, data, feature);
> +
> +    if ((driver = cpuGetSubDriver(arch)) == NULL)
> +        return -1;
> +
> +    if (driver->hasFeature == NULL) {
> +        virCPUReportError(VIR_ERR_NO_SUPPORT,
> +                _("cannot check guest CPU data for %s architecture"),
> +                          arch);
> +        return -1;
> +    }
> +
> +    return driver->hasFeature(arch, data, feature);
> +}
> +
> diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
> index a745917..405af48 100644
> --- a/src/cpu/cpu.h
> +++ b/src/cpu/cpu.h
> @@ -82,6 +82,11 @@ typedef int
>  (*cpuArchUpdate)    (virCPUDefPtr guest,
>                       const virCPUDefPtr host);
>  
> +typedef bool
> +(*cpuArchHasFeature) (const char *arch,
> +                      const union cpuData *data,
> +                      const char *feature);
> +
>  
>  struct cpuArchDriver {
>      const char *name;
> @@ -95,6 +100,7 @@ struct cpuArchDriver {
>      cpuArchGuestData    guestData;
>      cpuArchBaseline     baseline;
>      cpuArchUpdate       update;
> +    cpuArchHasFeature    hasFeature;
>  };
>  
>  
> @@ -151,4 +157,10 @@ extern int
>  cpuUpdate   (virCPUDefPtr guest,
>               const virCPUDefPtr host);
>  
> +extern bool
> +cpuHasFeature(const char *arch,
> +              const union cpuData *data,
> +              const char *feature);
> +
> +
>  #endif /* __VIR_CPU_H__ */
> diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
> index 1937901..cc82d58 100644
> --- a/src/cpu/cpu_x86.c
> +++ b/src/cpu/cpu_x86.c
> @@ -1754,6 +1754,55 @@ cleanup:
>      return ret;
>  }
>  
> +static bool x86HasFeature(const char *arch ATTRIBUTE_UNUSED,
> +                          const union cpuData *data,
> +                          const char *name)
> +{
> +    struct x86_map *map;
> +    struct x86_feature *feature;
> +    bool ret = false;
> +    int i;
> +
> +    if (!(map = x86LoadMap()))
> +        return false;
> +
> +    if (!(feature = x86FeatureFind(map, name)))
> +        goto cleanup;
> +
> +    for (i = 0 ; i < data->x86.basic_len ; i++) {
> +        if (data->x86.basic[i].function == feature->cpuid->function &&
> +            ((data->x86.basic[i].eax & feature->cpuid->eax)
> +             == feature->cpuid->eax) &&
> +            ((data->x86.basic[i].ebx & feature->cpuid->ebx)
> +             == feature->cpuid->ebx) &&
> +            ((data->x86.basic[i].ecx & feature->cpuid->ecx)
> +             == feature->cpuid->ecx) &&
> +            ((data->x86.basic[i].edx & feature->cpuid->edx)
> +             == feature->cpuid->edx)) {
> +            ret = true;
> +            goto cleanup;
> +        }
> +    }
> +
> +    for (i = 0 ; i < data->x86.extended_len ; i++) {
> +        if (data->x86.extended[i].function == feature->cpuid->function &&
> +            ((data->x86.extended[i].eax & feature->cpuid->eax)
> +             == feature->cpuid->eax) &&
> +            ((data->x86.extended[i].ebx & feature->cpuid->ebx)
> +             == feature->cpuid->ebx) &&
> +            ((data->x86.extended[i].ecx & feature->cpuid->ecx)
> +             == feature->cpuid->ecx) &&
> +            ((data->x86.extended[i].edx & feature->cpuid->edx)
> +             == feature->cpuid->edx)) {
> +            ret = true;
> +            goto cleanup;
> +        }
> +    }
> +
> +cleanup:
> +    x86MapFree(map);
> +    return ret;
> +}
>  
>  struct cpuArchDriver cpuDriverX86 = {
>      .name = "x86",
> @@ -1771,4 +1820,5 @@ struct cpuArchDriver cpuDriverX86 = {
>      .guestData  = x86GuestData,
>      .baseline   = x86Baseline,
>      .update     = x86Update,
> +    .hasFeature = x86HasFeature,
>  };
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index c2905ba..428b887 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -90,6 +90,7 @@ cpuEncode;
>  cpuGuestData;
>  cpuNodeData;
>  cpuUpdate;
> +cpuHasFeature;
>  
>  
>  # cpu_conf.h
> diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
> index 7a37c70..88dbf9b 100644
> --- a/src/qemu/qemu_conf.c
> +++ b/src/qemu/qemu_conf.c
> @@ -1210,6 +1210,8 @@ static unsigned long long qemudComputeCmdFlags(const char *help,
>          flags |= QEMUD_CMD_FLAG_NO_KVM_PIT;
>      if (strstr(help, "-tdf"))
>          flags |= QEMUD_CMD_FLAG_TDF;
> +    if (strstr(help, "-enable-nesting"))
> +        flags |= QEMUD_CMD_FLAG_NESTING;
>      if (strstr(help, ",menu=on"))
>          flags |= QEMUD_CMD_FLAG_BOOT_MENU;
>  
> @@ -3500,7 +3502,8 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
>                     const char *emulator,
>                     unsigned long long qemuCmdFlags,
>                     const struct utsname *ut,
> -                   char **opt)
> +                   char **opt,
> +                   bool *hasHwVirt)
>  {
>      const virCPUDefPtr host = driver->caps->host.cpu;
>      virCPUDefPtr guest = NULL;
> @@ -3511,6 +3514,8 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
>      virBuffer buf = VIR_BUFFER_INITIALIZER;
>      int i;
>  
> +    *hasHwVirt = false;
> +
>      if (def->cpu && def->cpu->model) {
>          if (qemudProbeCPUModels(emulator, qemuCmdFlags, ut->machine,
>                                  &ncpus, &cpus) < 0)
> @@ -3552,6 +3557,10 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
>          if (cpuDecode(guest, data, cpus, ncpus, preferred) < 0)
>              goto cleanup;
>  
> +        *hasHwVirt =
> +            cpuHasFeature(guest->arch, data, "svm") ||
> +            cpuHasFeature(guest->arch, data, "vmx");
> +
>          virBufferVSprintf(&buf, "%s", guest->model);
>          for (i = 0; i < guest->nfeatures; i++) {
>              char sign;
> @@ -3678,6 +3687,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
>      char *cpu;
>      char *smp;
>      int last_good_net = -1;
> +    bool hasHwVirt = false;
>  
>      uname_normalize(&ut);
>  
> @@ -3871,13 +3881,18 @@ int qemudBuildCommandLine(virConnectPtr conn,
>          ADD_ARG_LIT(def->os.machine);
>      }
>  
> -    if (qemuBuildCpuArgStr(driver, def, emulator, qemuCmdFlags, &ut, &cpu) < 0)
> +    if (qemuBuildCpuArgStr(driver, def, emulator, qemuCmdFlags,
> +                           &ut, &cpu, &hasHwVirt) < 0)
>          goto error;
>  
>      if (cpu) {
>          ADD_ARG_LIT("-cpu");
>          ADD_ARG_LIT(cpu);
>          VIR_FREE(cpu);
> +
> +        if ((qemuCmdFlags & QEMUD_CMD_FLAG_NESTING) &&
> +            hasHwVirt)
> +            ADD_ARG_LIT("-enable-nesting");
>      }
>  
>      if (disableKQEMU)
> diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
> index 2c9e608..16f72f5 100644
> --- a/src/qemu/qemu_conf.h
> +++ b/src/qemu/qemu_conf.h
> @@ -93,6 +93,7 @@ enum qemud_cmd_flags {
>      QEMUD_CMD_FLAG_NODEFCONFIG   = (1LL << 37), /* -nodefconfig */
>      QEMUD_CMD_FLAG_BOOT_MENU     = (1LL << 38), /* -boot menu=on support */
>      QEMUD_CMD_FLAG_ENABLE_KQEMU  = (1LL << 39), /* -enable-kqemu flag */
> +    QEMUD_CMD_FLAG_NESTING       = (1LL << 40), /* -enable-nesting (SVM/VMX) */
>  };
>  
>  /* Main driver state */
> -- 
> 1.7.2.3
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list




More information about the libvir-list mailing list