Re: [Qemu-devel] [PATCH 2/2] qemu-kvm: Add svm cpuid features

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10.09.2010, at 17:38, Joerg Roedel wrote:

> This patch adds the svm cpuid feature flags to the qemu
> intialization path.
> 
> Signed-off-by: Joerg Roedel <joerg.roedel@xxxxxxx>
> ---
> target-i386/cpu.h   |   12 +++++++
> target-i386/cpuid.c |   80 ++++++++++++++++++++++++++++++++++++++++-----------
> target-i386/kvm.c   |    3 ++
> 3 files changed, 78 insertions(+), 17 deletions(-)
> 
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 1144d4e..77eeab1 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -405,6 +405,17 @@
> #define CPUID_EXT3_IBS     (1 << 10)
> #define CPUID_EXT3_SKINIT  (1 << 12)
> 
> +#define CPUID_SVM_NPT          (1 << 0)
> +#define CPUID_SVM_LBRV         (1 << 1)
> +#define CPUID_SVM_SVMLOCK      (1 << 2)
> +#define CPUID_SVM_NRIPSAVE     (1 << 3)
> +#define CPUID_SVM_TSCSCALE     (1 << 4)
> +#define CPUID_SVM_VMCBCLEAN    (1 << 5)
> +#define CPUID_SVM_FLUSHASID    (1 << 6)
> +#define CPUID_SVM_DECODEASSIST (1 << 7)
> +#define CPUID_SVM_PAUSEFILTER  (1 << 10)
> +#define CPUID_SVM_PFTHRESHOLD  (1 << 12)
> +
> #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
> #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */
> #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */
> @@ -702,6 +713,7 @@ typedef struct CPUX86State {
>     uint8_t has_error_code;
>     uint32_t sipi_vector;
>     uint32_t cpuid_kvm_features;
> +    uint32_t cpuid_svm_features;
> 
>     /* in order to simplify APIC support, we leave this pointer to the
>        user */
> diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
> index 3fcf78f..ea1ac73 100644
> --- a/target-i386/cpuid.c
> +++ b/target-i386/cpuid.c
> @@ -79,6 +79,17 @@ static const char *kvm_feature_name[] = {
>     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> };
> 
> +static const char *svm_feature_name[] = {
> +    "npt", "lbrv", "svm_lock", "nrip_save",
> +    "tsc_scale", "vmcb_clean",  "flushbyasid", "decodeassists",
> +    NULL, NULL, "pause_filter", NULL,
> +    "pfthreshold", NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +    NULL, NULL, NULL, NULL,
> +};
> +
> /* collects per-function cpuid data
>  */
> typedef struct model_features_t {
> @@ -192,13 +203,15 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
>                                     uint32_t *ext_features,
>                                     uint32_t *ext2_features,
>                                     uint32_t *ext3_features,
> -                                    uint32_t *kvm_features)
> +                                    uint32_t *kvm_features,
> +                                    uint32_t *svm_features)
> {
>     if (!lookup_feature(features, flagname, NULL, feature_name) &&
>         !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
>         !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
>         !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
> -        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name))
> +        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) &&
> +        !lookup_feature(svm_features, flagname, NULL, svm_feature_name))
>             fprintf(stderr, "CPU feature %s not found\n", flagname);
> }
> 
> @@ -210,7 +223,8 @@ typedef struct x86_def_t {
>     int family;
>     int model;
>     int stepping;
> -    uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
> +    uint32_t features, ext_features, ext2_features, ext3_features;
> +    uint32_t kvm_features, svm_features;
>     uint32_t xlevel;
>     char model_id[48];
>     int vendor_override;
> @@ -253,6 +267,7 @@ typedef struct x86_def_t {
>           CPUID_EXT2_PDPE1GB */
> #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
>           CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
> +#define TCG_SVM_FEATURES 0
> 
> /* maintains list of cpu model definitions
>  */
> @@ -278,6 +293,8 @@ static x86_def_t builtin_x86_defs[] = {
>             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
>         .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
>             CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
> +        .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV | CPUID_SVM_NRIPSAVE |
> +            CPUID_SVM_VMCBCLEAN,
>         .xlevel = 0x8000000A,
>         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
>     },
> @@ -305,6 +322,8 @@ static x86_def_t builtin_x86_defs[] = {
>                     CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
>         .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
>             CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
> +        .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV | CPUID_SVM_NRIPSAVE |
> +            CPUID_SVM_VMCBCLEAN,

Does that phenom already do all those? It does NPT, but I'm not sure about NRIPSAVE for example.

>         .xlevel = 0x8000001A,
>         .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
>     },
> @@ -505,6 +524,15 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
>     cpu_x86_fill_model_id(x86_cpu_def->model_id);
>     x86_cpu_def->vendor_override = 0;
> 
> +
> +    /*
> +     * Every SVM feature requires emulation support in KVM - so we can't just
> +     * read the host features here. KVM might even support SVM features not
> +     * available on the host hardware
> +     */
> +    x86_cpu_def->svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV |
> +                                CPUID_SVM_NRIPSAVE | CPUID_SVM_VMCBCLEAN;

Hrm. Wouldn't it make more sense to declare this to -1? This will still go through the kernel space matcher which tells us which features are available anyways, right?


> +
>     return 0;
> }
> 
> @@ -560,8 +588,14 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
> 
>     char *s = strdup(cpu_model);
>     char *featurestr, *name = strtok(s, ",");
> -    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
> -    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0, minus_kvm_features = 0;
> +    /* Features to be added*/
> +    uint32_t plus_features = 0, plus_ext_features = 0;
> +    uint32_t plus_ext2_features = 0, plus_ext3_features = 0;
> +    uint32_t plus_kvm_features = 0, plus_svm_features = 0;
> +    /* Features to be removed */
> +    uint32_t minus_features = 0, minus_ext_features = 0;
> +    uint32_t minus_ext2_features = 0, minus_ext3_features = 0;
> +    uint32_t minus_kvm_features = 0, minus_svm_features = 0;
>     uint32_t numvalue;
> 
>     for (def = x86_defs; def; def = def->next)
> @@ -579,16 +613,22 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
> 
>     add_flagname_to_bitmaps("hypervisor", &plus_features,
>         &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
> -        &plus_kvm_features);
> +        &plus_kvm_features, &plus_svm_features);
> 
>     featurestr = strtok(NULL, ",");
> 
>     while (featurestr) {
>         char *val;
>         if (featurestr[0] == '+') {
> -            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features);
> +            add_flagname_to_bitmaps(featurestr + 1, &plus_features,
> +                            &plus_ext_features, &plus_ext2_features,
> +                            &plus_ext3_features, &plus_kvm_features,
> +                            &plus_svm_features);
>         } else if (featurestr[0] == '-') {
> -            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features);
> +            add_flagname_to_bitmaps(featurestr + 1, &minus_features,
> +                            &minus_ext_features, &minus_ext2_features,
> +                            &minus_ext3_features, &minus_kvm_features,
> +                            &minus_svm_features);
>         } else if ((val = strchr(featurestr, '='))) {
>             *val = 0; val++;
>             if (!strcmp(featurestr, "family")) {
> @@ -670,11 +710,13 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
>     x86_cpu_def->ext2_features |= plus_ext2_features;
>     x86_cpu_def->ext3_features |= plus_ext3_features;
>     x86_cpu_def->kvm_features |= plus_kvm_features;
> +    x86_cpu_def->svm_features |= plus_svm_features;
>     x86_cpu_def->features &= ~minus_features;
>     x86_cpu_def->ext_features &= ~minus_ext_features;
>     x86_cpu_def->ext2_features &= ~minus_ext2_features;
>     x86_cpu_def->ext3_features &= ~minus_ext3_features;
>     x86_cpu_def->kvm_features &= ~minus_kvm_features;
> +    x86_cpu_def->svm_features &= ~minus_svm_features;
>     if (check_cpuid) {
>         if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
>             goto error;
> @@ -816,6 +858,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
>     env->cpuid_ext3_features = def->ext3_features;
>     env->cpuid_xlevel = def->xlevel;
>     env->cpuid_kvm_features = def->kvm_features;
> +    env->cpuid_svm_features = def->svm_features;
>     if (!kvm_enabled()) {
>         env->cpuid_features &= TCG_FEATURES;
>         env->cpuid_ext_features &= TCG_EXT_FEATURES;
> @@ -825,6 +868,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
> #endif
>             );
>         env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
> +        env->cpuid_svm_features &= TCG_SVM_FEATURES;
>     }
>     {
>         const char *model_id = def->model_id;
> @@ -1135,11 +1179,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>                 *ecx |= 1 << 1;    /* CmpLegacy bit */
>             }
>         }
> -
> -        if (kvm_enabled()) {
> -            /* Nested SVM not yet supported in upstream QEMU */
> -            *ecx &= ~CPUID_EXT3_SVM;
> -        }

Have you made sure that the default cpu type doesn't enable the SVM bit? I couldn't find any trace of an override to "kvm64" as default type when KVM is used.

The rest looks good :). Thanks a lot for this patch set!


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux