[libvirt] [PATCH] Enable support for nested SVM

Jiri Denemark jdenemar at redhat.com
Thu Sep 23 16:05:16 UTC 2010


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

No need to pass arch down here.

> +}
> +
> 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);
> +

The 'arch' argument is not needed here since cpuHasFeature already selected
appropriate implementation according to CPU architecture.

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

No arch argument needed here as well.

> +{
> +    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;
> +        }
> +    }

The two for loops should be replaced by the following single loop (which in
practise will be walked through only once):


    for (i = 0; i < feature->ncpuid; i++) {
        struct cpuX86cpuid *cpuid;

        cpuid = x86DataCpuid(data, feature->cpuid[i].function);
        if (cpuid && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) {
            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,
>  };

The current code would actually work so this is not a show stopper and the
changes could be done as part of a bigger cleanup patch for cpu_x86.c that I
have in my git tree. However I won't send the cleanup patch before I finish
unit tests for all this to check the cleanup doesn't break anything.

The rest looks fine.

Jirka




More information about the libvir-list mailing list