All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eduardo Habkost <ehabkost@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: Liran Alon <liran.alon@oracle.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 2/7] target/i386: introduce generic feature dependency mechanism
Date: Fri, 5 Jul 2019 17:52:28 -0300	[thread overview]
Message-ID: <20190705205228.GF5198@habkost.net> (raw)
In-Reply-To: <1562079681-19204-3-git-send-email-pbonzini@redhat.com>

On Tue, Jul 02, 2019 at 05:01:16PM +0200, Paolo Bonzini wrote:
> Sometimes a CPU feature does not make sense unless another is
> present.  In the case of VMX features, KVM does not even allow
> setting the VMX controls to some invalid combinations.
> 
> Therefore, this patch adds a generic mechanism that looks for bits
> that the user explicitly cleared, and uses them to remove other bits
> from the expanded CPU definition.  If these dependent bits were also
> explicitly *set* by the user, this will be a warning for "-cpu check"
> and an error for "-cpu enforce".  If not, then the dependent bits are
> cleared silently, for convenience.
> 
> With VMX features, this will be used so that for example
> "-cpu host,-rdrand" will also hide support for RDRAND exiting.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  target/i386/cpu.c | 77 +++++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 49 insertions(+), 28 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 9149d0d..412e834 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -799,10 +799,6 @@ typedef struct FeatureWordInfo {
>          /* If type==MSR_FEATURE_WORD */
>          struct {
>              uint32_t index;
> -            struct {   /*CPUID that enumerate this MSR*/
> -                FeatureWord cpuid_class;
> -                uint32_t    cpuid_flag;
> -            } cpuid_dep;
>          } msr;
>      };
>      uint32_t tcg_features; /* Feature flags supported by TCG */
> @@ -1197,10 +1193,6 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>          },
>          .msr = {
>              .index = MSR_IA32_ARCH_CAPABILITIES,
> -            .cpuid_dep = {
> -                FEAT_7_0_EDX,
> -                CPUID_7_0_EDX_ARCH_CAPABILITIES
> -            }
>          },
>      },
>      [FEAT_CORE_CAPABILITY] = {
> @@ -1217,14 +1209,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>          },
>          .msr = {
>              .index = MSR_IA32_CORE_CAPABILITY,
> -            .cpuid_dep = {
> -                FEAT_7_0_EDX,
> -                CPUID_7_0_EDX_CORE_CAPABILITY,
> -            },
>          },
>      },
>  };
>  
> +typedef struct FeatureDep {
> +    uint16_t from, to;

Why uint16_t and not FeatureWord?

> +    uint64_t from_flag, to_flags;

There are other parts of the code that take a
FeatureWord/uint32_t pair (which will become uint64_t).  I'd wrap
this into a typedef.  I also miss documentation on the exact
meaning of those fields.

    typedef struct FeatureMask {
        FeatureWord w;
        uint64_t mask;
    };
    
    
    typedef struct FeatureDependency {
       /*
        * Features in @to may be present only if _all_ features in @from
        * present too.
        */
       FeatureMask from, to;
    };
    
    static FeatureDep feature_dependencies[] = {
        {
            .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES
            .to =   { FEAT_ARCH_CAPABILITIES, ~0ull },
        },
        {
            .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY },
            .to =   { FEAT_CORE_CAPABILITY, ~0ull },
        },
    };


> +} FeatureDep;
> +
> +static FeatureDep feature_dependencies[] = {
> +    {
> +        .from = FEAT_7_0_EDX,            .from_flag = CPUID_7_0_EDX_ARCH_CAPABILITIES,
> +        .to = FEAT_ARCH_CAPABILITIES,    .to_flags = ~0ull,
> +    },
> +    {
> +        .from = FEAT_7_0_EDX,            .from_flag = CPUID_7_0_EDX_CORE_CAPABILITY,
> +        .to = FEAT_CORE_CAPABILITY,      .to_flags = ~0ull,
> +    },
> +};
> +
>  typedef struct X86RegisterInfo32 {
>      /* Name of register */
>      const char *name;
> @@ -5086,9 +5090,42 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
>  {
>      CPUX86State *env = &cpu->env;
>      FeatureWord w;
> +    int i;
>      GList *l;
>      Error *local_err = NULL;
>  
> +    for (l = plus_features; l; l = l->next) {
> +        const char *prop = l->data;
> +        object_property_set_bool(OBJECT(cpu), true, prop, &local_err);
> +        if (local_err) {
> +            goto out;
> +        }
> +    }
> +
> +    for (l = minus_features; l; l = l->next) {
> +        const char *prop = l->data;
> +        object_property_set_bool(OBJECT(cpu), false, prop, &local_err);
> +        if (local_err) {
> +            goto out;
> +        }
> +    }

Maybe getting rid of plus_features/minus_features (as described
in the TODO comment below) will make things simpler.

> +
> +    for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) {
> +        FeatureDep *d = &feature_dependencies[i];
> +        if ((env->user_features[d->from] & d->from_flag) &&
> +            !(env->features[d->from] & d->from_flag)) {

Why does it matter if the feature was cleared explicitly by the
user?

> +            uint64_t unavailable_features = env->features[d->to] & d->to_flags;
> +
> +            /* Not an error unless the dependent feature was added explicitly.  */
> +            mark_unavailable_features(cpu, d->to, unavailable_features & env->user_features[d->to],
> +                                      "This feature depends on other features that were not requested");
> +
> +            /* Prevent adding the feature in the loop below.  */
> +            env->user_features[d->to] |= d->to_flags;
> +            env->features[d->to] &= ~d->to_flags;
> +        }
> +    }

Maybe move this entire block inside x86_cpu_filter_features()?

> +
>      /*TODO: Now cpu->max_features doesn't overwrite features
>       * set using QOM properties, and we can convert
>       * plus_features & minus_features to global properties
> @@ -5106,22 +5143,6 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
>          }
>      }
>  
> -    for (l = plus_features; l; l = l->next) {
> -        const char *prop = l->data;
> -        object_property_set_bool(OBJECT(cpu), true, prop, &local_err);
> -        if (local_err) {
> -            goto out;
> -        }
> -    }
> -
> -    for (l = minus_features; l; l = l->next) {
> -        const char *prop = l->data;
> -        object_property_set_bool(OBJECT(cpu), false, prop, &local_err);
> -        if (local_err) {
> -            goto out;
> -        }
> -    }
> -
>      if (!kvm_enabled() || !cpu->expose_kvm) {
>          env->features[FEAT_KVM] = 0;
>      }
> -- 
> 1.8.3.1
> 
> 
> 

-- 
Eduardo


  reply	other threads:[~2019-07-05 20:54 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-02 15:01 [Qemu-devel] [RFC PATCH 0/7] target/i386: support VMX features in "-cpu" Paolo Bonzini
2019-07-02 15:01 ` [Qemu-devel] [PATCH 1/7] target/i386: handle filtered_features in a new function mark_unavailable_features Paolo Bonzini
2019-07-05 20:37   ` Eduardo Habkost
2019-07-05 21:32     ` Paolo Bonzini
2019-07-05 21:44       ` Eduardo Habkost
2019-07-05 22:07         ` Paolo Bonzini
2019-07-05 22:16           ` Eduardo Habkost
2019-07-02 15:01 ` [Qemu-devel] [PATCH 2/7] target/i386: introduce generic feature dependency mechanism Paolo Bonzini
2019-07-05 20:52   ` Eduardo Habkost [this message]
2019-07-05 21:12     ` Paolo Bonzini
2019-07-05 21:41       ` Eduardo Habkost
2019-07-05 22:07         ` Paolo Bonzini
2019-07-08 21:45           ` Eduardo Habkost
2019-07-02 15:01 ` [Qemu-devel] [PATCH 3/7] target/i386: expand feature words to 64 bits Paolo Bonzini
2019-07-02 15:01 ` [Qemu-devel] [PATCH 4/7] target/i386: add VMX definitions Paolo Bonzini
2019-07-02 15:01 ` [Qemu-devel] [PATCH 5/7] vmxcap: correct the name of the variables Paolo Bonzini
2019-07-02 15:01 ` [Qemu-devel] [PATCH 6/7] target/i386: add VMX features Paolo Bonzini
2019-07-05 21:22   ` Eduardo Habkost
2019-07-05 22:12     ` Paolo Bonzini
2019-07-05 22:33       ` Eduardo Habkost
2019-07-05 22:42         ` Paolo Bonzini
2019-07-05 22:48           ` Eduardo Habkost
2019-07-02 15:01 ` [Qemu-devel] [PATCH 7/7] target/i386: work around KVM_GET_MSRS bug for secondary execution controls Paolo Bonzini
2019-07-02 20:46 ` [Qemu-devel] [RFC PATCH 0/7] target/i386: support VMX features in "-cpu" no-reply
2019-07-02 21:13 ` no-reply
2019-07-02 21:38   ` [Qemu-devel] No symbols in LeakSanitizer output (was Re: [RFC PATCH 0/7] target/i386: support VMX features in "-cpu") Eduardo Habkost
2019-07-02 23:05     ` Peter Maydell
2019-07-05 10:19     ` Paolo Bonzini
  -- strict thread matches above, loose matches on Subject: below --
2019-09-17 10:34 [Qemu-devel] [PATCH v2 0/7] target/i386: support VMX features in "-cpu" Paolo Bonzini
2019-09-17 10:34 ` [Qemu-devel] [PATCH 2/7] target/i386: introduce generic feature dependency mechanism Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190705205228.GF5198@habkost.net \
    --to=ehabkost@redhat.com \
    --cc=liran.alon@oracle.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.