Commit 245edd0c authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

target/i386: handle filtered_features in a new function mark_unavailable_features



The next patch will add a different reason for filtering features, unrelated
to host feature support.  Extract a new function that takes care of disabling
the features and optionally reporting them.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 9e5ef164
Loading
Loading
Loading
Loading
+48 −39
Original line number Diff line number Diff line
@@ -3096,17 +3096,41 @@ static char *feature_word_description(FeatureWordInfo *f, uint32_t bit)
    return NULL;
}

static void report_unavailable_features(FeatureWord w, uint32_t mask)
static bool x86_cpu_have_filtered_features(X86CPU *cpu)
{
    FeatureWord w;

    for (w = 0; w < FEATURE_WORDS; w++) {
        if (cpu->filtered_features[w]) {
            return true;
        }
    }

    return false;
}

static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask,
                                      const char *verbose_prefix)
{
    CPUX86State *env = &cpu->env;
    FeatureWordInfo *f = &feature_word_info[w];
    int i;
    char *feat_word_str;

    if (!cpu->force_features) {
        env->features[w] &= ~mask;
    }
    cpu->filtered_features[w] |= mask;

    if (!verbose_prefix) {
        return;
    }

    for (i = 0; i < 32; ++i) {
        if ((1UL << i) & mask) {
            feat_word_str = feature_word_description(f, i);
            warn_report("%s doesn't support requested feature: %s%s%s [bit %d]",
                        accel_uses_host_cpuid() ? "host" : "TCG",
            warn_report("%s: %s%s%s [bit %d]",
                        verbose_prefix,
                        feat_word_str,
                        f->feat_names[i] ? "." : "",
                        f->feat_names[i] ? f->feat_names[i] : "", i);
@@ -3511,7 +3535,7 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features,
}

static void x86_cpu_expand_features(X86CPU *cpu, Error **errp);
static int x86_cpu_filter_features(X86CPU *cpu);
static void x86_cpu_filter_features(X86CPU *cpu, bool verbose);

/* Build a list with the name of all features on a feature word array */
static void x86_cpu_list_feature_names(FeatureWordArray features,
@@ -3576,7 +3600,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc,
        next = &new->next;
    }

    x86_cpu_filter_features(xc);
    x86_cpu_filter_features(xc, false);

    x86_cpu_list_feature_names(xc->filtered_features, next);

@@ -3784,15 +3808,6 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
    return r;
}

static void x86_cpu_report_filtered_features(X86CPU *cpu)
{
    FeatureWord w;

    for (w = 0; w < FEATURE_WORDS; w++) {
        report_unavailable_features(w, cpu->filtered_features[w]);
    }
}

static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
{
    PropValue *pv;
@@ -5154,24 +5169,24 @@ out:
 *
 * Returns: 0 if all flags are supported by the host, non-zero otherwise.
 */
static int x86_cpu_filter_features(X86CPU *cpu)
static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
{
    CPUX86State *env = &cpu->env;
    FeatureWord w;
    int rv = 0;
    const char *prefix = NULL;

    if (verbose) {
        prefix = accel_uses_host_cpuid()
                 ? "host doesn't support requested feature"
                 : "TCG doesn't support requested feature";
    }

    for (w = 0; w < FEATURE_WORDS; w++) {
        uint32_t host_feat =
            x86_cpu_get_supported_feature_word(w, false);
        uint32_t requested_features = env->features[w];
        uint32_t available_features = requested_features & host_feat;
        if (!cpu->force_features) {
            env->features[w] = available_features;
        }
        cpu->filtered_features[w] = requested_features & ~available_features;
        if (cpu->filtered_features[w]) {
            rv = 1;
        }
        uint32_t unavailable_features = requested_features & ~host_feat;
        mark_unavailable_features(cpu, w, unavailable_features, prefix);
    }

    if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) &&
@@ -5197,13 +5212,9 @@ static int x86_cpu_filter_features(X86CPU *cpu)
             * host can't emulate the capabilities we report on
             * cpu_x86_cpuid(), intel-pt can't be enabled on the current host.
             */
            env->features[FEAT_7_0_EBX] &= ~CPUID_7_0_EBX_INTEL_PT;
            cpu->filtered_features[FEAT_7_0_EBX] |= CPUID_7_0_EBX_INTEL_PT;
            rv = 1;
            mark_unavailable_features(cpu, FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT, prefix);
        }
    }

    return rv;
}

static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
@@ -5244,17 +5255,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
        goto out;
    }

    if (x86_cpu_filter_features(cpu) &&
        (cpu->check_cpuid || cpu->enforce_cpuid)) {
        x86_cpu_report_filtered_features(cpu);
        if (cpu->enforce_cpuid) {
    x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid);

    if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) {
        error_setg(&local_err,
                   accel_uses_host_cpuid() ?
                       "Host doesn't support requested features" :
                       "TCG doesn't support requested features");
        goto out;
    }
    }

    /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
     * CPUID[1].EDX.