static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)

{

    unsigned int i;

    x86_def_t *def;



    char *s = g_strdup(cpu_model);

    char *featurestr, *name = strtok(s, ",");

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

        if (!strcmp(name, def->name))

            break;

    if (kvm_enabled() && strcmp(name, "host") == 0) {

        cpu_x86_fill_host(x86_cpu_def);

    } else if (!def) {

        goto error;

    } else {

        memcpy(x86_cpu_def, def, sizeof(*def));

    }



    plus_kvm_features = ~0; /* not supported bits will be filtered out later */



    add_flagname_to_bitmaps("hypervisor", &plus_features,

        &plus_ext_features, &plus_ext2_features, &plus_ext3_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,

                            &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,

                            &minus_svm_features);

        } else if ((val = strchr(featurestr, '='))) {

            *val = 0; val++;

            if (!strcmp(featurestr, "family")) {

                char *err;

                numvalue = strtoul(val, &err, 0);

                if (!*val || *err) {

                    fprintf(stderr, "bad numerical value %s\n", val);

                    goto error;

                }

                x86_cpu_def->family = numvalue;

            } else if (!strcmp(featurestr, "model")) {

                char *err;

                numvalue = strtoul(val, &err, 0);

                if (!*val || *err || numvalue > 0xff) {

                    fprintf(stderr, "bad numerical value %s\n", val);

                    goto error;

                }

                x86_cpu_def->model = numvalue;

            } else if (!strcmp(featurestr, "stepping")) {

                char *err;

                numvalue = strtoul(val, &err, 0);

                if (!*val || *err || numvalue > 0xf) {

                    fprintf(stderr, "bad numerical value %s\n", val);

                    goto error;

                }

                x86_cpu_def->stepping = numvalue ;

            } else if (!strcmp(featurestr, "level")) {

                char *err;

                numvalue = strtoul(val, &err, 0);

                if (!*val || *err) {

                    fprintf(stderr, "bad numerical value %s\n", val);

                    goto error;

                }

                x86_cpu_def->level = numvalue;

            } else if (!strcmp(featurestr, "xlevel")) {

                char *err;

                numvalue = strtoul(val, &err, 0);

                if (!*val || *err) {

                    fprintf(stderr, "bad numerical value %s\n", val);

                    goto error;

                }

                if (numvalue < 0x80000000) {

                    numvalue += 0x80000000;

                }

                x86_cpu_def->xlevel = numvalue;

            } else if (!strcmp(featurestr, "vendor")) {

                if (strlen(val) != 12) {

                    fprintf(stderr, "vendor string must be 12 chars long\n");

                    goto error;

                }

                x86_cpu_def->vendor1 = 0;

                x86_cpu_def->vendor2 = 0;

                x86_cpu_def->vendor3 = 0;

                for(i = 0; i < 4; i++) {

                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);

                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);

                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);

                }

                x86_cpu_def->vendor_override = 1;

            } else if (!strcmp(featurestr, "model_id")) {

                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),

                        val);

            } else if (!strcmp(featurestr, "tsc_freq")) {

                int64_t tsc_freq;

                char *err;



                tsc_freq = strtosz_suffix_unit(val, &err,

                                               STRTOSZ_DEFSUFFIX_B, 1000);

                if (!*val || *err) {

                    fprintf(stderr, "bad numerical value %s\n", val);

                    goto error;

                }

                x86_cpu_def->tsc_khz = tsc_freq / 1000;

            } else {

                fprintf(stderr, "unrecognized feature %s\n", featurestr);

                goto error;

            }

        } else if (!strcmp(featurestr, "check")) {

            check_cpuid = 1;

        } else if (!strcmp(featurestr, "enforce")) {

            check_cpuid = enforce_cpuid = 1;

        } else {

            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);

            goto error;

        }

        featurestr = strtok(NULL, ",");

    }

    x86_cpu_def->features |= plus_features;

    x86_cpu_def->ext_features |= plus_ext_features;

    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;

    }

    g_free(s);

    return 0;



error:

    g_free(s);

    return -1;

}
