diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 3be2220a..d0ea77a8 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_aarch64 #define par_write par_write_aarch64 #define parse_array parse_array_aarch64 +#define parse_cpu_model parse_cpu_model_aarch64 #define parse_error parse_error_aarch64 #define parse_escape parse_escape_aarch64 #define parse_keyword parse_keyword_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index ddfc84a5..d6a79ac7 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_aarch64eb #define par_write par_write_aarch64eb #define parse_array parse_array_aarch64eb +#define parse_cpu_model parse_cpu_model_aarch64eb #define parse_error parse_error_aarch64eb #define parse_escape parse_escape_aarch64eb #define parse_keyword parse_keyword_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index da113846..bd0a792c 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_arm #define par_write par_write_arm #define parse_array parse_array_arm +#define parse_cpu_model parse_cpu_model_arm #define parse_error parse_error_arm #define parse_escape parse_escape_arm #define parse_keyword parse_keyword_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index d44cf486..2dcb704b 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_armeb #define par_write par_write_armeb #define parse_array parse_array_armeb +#define parse_cpu_model parse_cpu_model_armeb #define parse_error parse_error_armeb #define parse_escape parse_escape_armeb #define parse_keyword parse_keyword_armeb diff --git a/qemu/exec.c b/qemu/exec.c index 6565e0d1..6c6613ac 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -620,6 +620,29 @@ void cpu_exec_init(CPUState *cpu, void *opaque) #endif } +const char *parse_cpu_model(struct uc_struct *uc, const char *cpu_model) +{ + ObjectClass *oc; + CPUClass *cc; + gchar **model_pieces; + const char *cpu_type; + + model_pieces = g_strsplit(cpu_model, ",", 2); + + oc = cpu_class_by_name(uc, CPU_RESOLVING_TYPE, model_pieces[0]); + if (oc == NULL) { + fprintf(stderr, "unable to find CPU model '%s'", model_pieces[0]); + g_strfreev(model_pieces); + return NULL; + } + + cpu_type = object_class_get_name(oc); + cc = CPU_CLASS(uc, oc); + cc->parse_features(uc, cpu_type, model_pieces[1], &error_fatal); + g_strfreev(model_pieces); + return cpu_type; +} + #if defined(CONFIG_USER_ONLY) static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) { diff --git a/qemu/glib_compat.c b/qemu/glib_compat.c index 1c3a4039..d2f536ad 100644 --- a/qemu/glib_compat.c +++ b/qemu/glib_compat.c @@ -224,6 +224,106 @@ void g_list_free(GList *list) } } +/** + * g_list_free_full: + * @list: a pointer to a #GList + * @free_func: the function to be called to free each element's data + * + * Convenience method, which frees all the memory used by a #GList, and + * calls the specified destroy function on every element's data. + * + * Since: 2.28 + */ +void +g_list_free_full (GList *list, + GDestroyNotify free_func) +{ + g_list_foreach (list, (GFunc) free_func, NULL); + g_list_free (list); +} + +/** + * g_list_last: + * @list: a #GList + * + * Gets the last element in a #GList. + * + * Returns: the last element in the #GList, + * or %NULL if the #GList has no elements + */ +GList* +g_list_last (GList *list) +{ + if (list) + { + while (list->next) + list = list->next; + } + + return list; +} + +/** + * g_list_append: + * @list: a pointer to a #GList + * @data: the data for the new element + * + * Adds a new element on to the end of the list. + * + * + * The return value is the new start of the list, which + * may have changed, so make sure you store the new value. + * + * + * + * Note that g_list_append() has to traverse the entire list + * to find the end, which is inefficient when adding multiple + * elements. A common idiom to avoid the inefficiency is to prepend + * the elements and reverse the list when all elements have been added. + * + * + * |[ + * /* Notice that these are initialized to the empty list. */ + * GList *list = NULL, *number_list = NULL; + * + * /* This is a list of strings. */ + * list = g_list_append (list, "first"); + * list = g_list_append (list, "second"); + * + * /* This is a list of integers. */ + * number_list = g_list_append (number_list, GINT_TO_POINTER (27)); + * number_list = g_list_append (number_list, GINT_TO_POINTER (14)); + * ]| + * + * Returns: the new start of the #GList + */ +GList* +g_list_append (GList *list, + gpointer data) +{ + GList *new_list; + GList *last; + + new_list = g_new0(GList, 1); + new_list->data = data; + new_list->next = NULL; + + if (list) + { + last = g_list_last (list); + /* g_assert (last != NULL); */ + last->next = new_list; + new_list->prev = last; + + return list; + } + else + { + new_list->prev = NULL; + return new_list; + } +} + GList *g_list_insert_sorted(GList *list, gpointer data, GCompareFunc compare) { GList *i; diff --git a/qemu/header_gen.py b/qemu/header_gen.py index e8b82956..8b8cbe89 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -1953,6 +1953,7 @@ symbols = ( 'page_size_init', 'par_write', 'parse_array', + 'parse_cpu_model', 'parse_error', 'parse_escape', 'parse_keyword', diff --git a/qemu/hw/arm/tosa.c b/qemu/hw/arm/tosa.c index 56fd871a..3aa40192 100644 --- a/qemu/hw/arm/tosa.c +++ b/qemu/hw/arm/tosa.c @@ -22,9 +22,9 @@ static int tosa_init(struct uc_struct *uc, MachineState *machine) { if (uc->mode & UC_MODE_MCLASS) { - uc->cpu = cpu_init(uc, "cortex-m3"); + uc->cpu = cpu_create(uc, "cortex-m3"); } else { - uc->cpu = cpu_init(uc, "cortex-a15"); + uc->cpu = cpu_create(uc, "cortex-a15"); } return 0; diff --git a/qemu/hw/m68k/dummy_m68k.c b/qemu/hw/m68k/dummy_m68k.c index 0423bafd..3acc3d3c 100644 --- a/qemu/hw/m68k/dummy_m68k.c +++ b/qemu/hw/m68k/dummy_m68k.c @@ -19,14 +19,10 @@ /* Board init. */ static int dummy_m68k_init(struct uc_struct *uc, MachineState *machine) { - const char *cpu_model = machine->cpu_model; CPUM68KState *env; + const char *cpu_type = parse_cpu_model(uc, "cf4ve"); - if (!cpu_model) { - cpu_model = "cfv4e"; - } - - uc->cpu = cpu_init(uc, cpu_model); + uc->cpu = cpu_create(uc, cpu_type); if (!uc->cpu) { fprintf(stderr, "Unable to find m68k CPU definition\n"); return -1; @@ -45,6 +41,7 @@ static void dummy_m68k_machine_init(struct uc_struct *uc, MachineClass *mc) mc->init = dummy_m68k_init; mc->is_default = 1; mc->arch = UC_ARCH_M68K; + mc->default_cpu_type = M68K_CPU_TYPE_NAME("cfv4e"); } DEFINE_MACHINE("dummy", dummy_m68k_machine_init) diff --git a/qemu/hw/mips/mips_r4k.c b/qemu/hw/mips/mips_r4k.c index 48fd0df6..267f0e81 100644 --- a/qemu/hw/mips/mips_r4k.c +++ b/qemu/hw/mips/mips_r4k.c @@ -25,18 +25,14 @@ static int mips_r4k_init(struct uc_struct *uc, MachineState *machine) { - const char *cpu_model = machine->cpu_model; - - /* init CPUs */ - if (cpu_model == NULL) { #ifdef TARGET_MIPS64 - cpu_model = "R4000"; + const char *cpu_model = MIPS_CPU_TYPE_NAME("R4000"); #else - cpu_model = "24Kf"; + const char *cpu_model = MIPS_CPU_TYPE_NAME("24Kf"); #endif - } + const char *cpu_type = parse_cpu_model(uc, cpu_model); - uc->cpu = cpu_generic_init(uc, TYPE_MIPS_CPU, cpu_model); + uc->cpu = cpu_create(uc, cpu_type); if (uc->cpu == NULL) { fprintf(stderr, "Unable to find CPU definition\n"); return -1; @@ -50,6 +46,11 @@ static void mips_machine_init(struct uc_struct *uc, MachineClass *mc) mc->init = mips_r4k_init; mc->is_default = 1; mc->arch = UC_ARCH_MIPS; +#ifdef TARGET_MIPS64 + mc->default_cpu_type = MIPS_CPU_TYPE_NAME("R4000"); +#else + mc->default_cpu_type = MIPS_CPU_TYPE_NAME("24Kf"); +#endif } DEFINE_MACHINE("mips", mips_machine_init) diff --git a/qemu/hw/sparc/leon3.c b/qemu/hw/sparc/leon3.c index 68083974..64ff7d6c 100644 --- a/qemu/hw/sparc/leon3.c +++ b/qemu/hw/sparc/leon3.c @@ -38,15 +38,10 @@ static int leon3_generic_hw_init(struct uc_struct *uc, MachineState *machine) { - const char *cpu_model = machine->cpu_model; + const char *cpu_type = parse_cpu_model(uc, "LEON3"); SPARCCPU *cpu; - /* Init CPU */ - if (!cpu_model) { - cpu_model = "LEON3"; - } - - uc->cpu = cpu_init(uc, cpu_model); + uc->cpu = cpu_create(uc, cpu_type); cpu = SPARC_CPU(uc, uc->cpu); if (cpu == NULL) { fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); @@ -63,6 +58,7 @@ static void leon3_generic_machine_init(struct uc_struct *uc, MachineClass *mc) mc->init = leon3_generic_hw_init; mc->is_default = 1; mc->arch = UC_ARCH_SPARC; + mc->default_cpu_type = SPARC_CPU_TYPE_NAME("LEON3"); } DEFINE_MACHINE("leon3_generic", leon3_generic_machine_init) diff --git a/qemu/hw/sparc64/sun4u.c b/qemu/hw/sparc64/sun4u.c index 7b0246a9..e2e68810 100644 --- a/qemu/hw/sparc64/sun4u.c +++ b/qemu/hw/sparc64/sun4u.c @@ -36,14 +36,10 @@ /* Sun4u hardware initialisation */ static int sun4u_init(struct uc_struct *uc, MachineState *machine) { - const char *cpu_model = machine->cpu_model; + const char *cpu_type = parse_cpu_model(uc, "Sun UltraSparc IV"); SPARCCPU *cpu; - if (cpu_model == NULL) { - cpu_model = "Sun UltraSparc IV"; - } - - uc->cpu = cpu_init(uc, cpu_model); + uc->cpu = cpu_create(uc, cpu_type); cpu = SPARC_CPU(uc, uc->cpu); if (cpu == NULL) { fprintf(stderr, "Unable to find Sparc CPU definition\n"); @@ -61,6 +57,7 @@ static void sun4u_class_init(struct uc_struct *uc, ObjectClass *oc, void *data) mc->max_cpus = 1; /* XXX for now */ mc->is_default = 1; mc->arch = UC_ARCH_SPARC; + mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Sun UltraSparc IV"); } static const TypeInfo sun4u_type = { diff --git a/qemu/include/glib_compat.h b/qemu/include/glib_compat.h index 5f3f8af7..b4599055 100644 --- a/qemu/include/glib_compat.h +++ b/qemu/include/glib_compat.h @@ -74,9 +74,12 @@ typedef struct _GList { struct _GList *prev; } GList; +GList* g_list_append(GList *list, gpointer data); GList *g_list_first(GList *list); +GList* g_list_last(GList *list); void g_list_foreach(GList *list, GFunc func, gpointer user_data); void g_list_free(GList *list); +void g_list_free_full(GList *list, GDestroyNotify free_func); GList* g_list_insert_before(GList *list, GList *sibling, gpointer data); GList *g_list_insert_sorted(GList *list, gpointer data, GCompareFunc compare); #define g_list_next(list) (list->next) diff --git a/qemu/include/hw/boards.h b/qemu/include/hw/boards.h index cf76a842..27efd7db 100644 --- a/qemu/include/hw/boards.h +++ b/qemu/include/hw/boards.h @@ -112,7 +112,6 @@ struct MachineState { /*< public >*/ ram_addr_t ram_size; ram_addr_t maxram_size; - const char *cpu_model; const char *cpu_type; struct uc_struct *uc; AccelState *accelerator; diff --git a/qemu/include/qom/cpu.h b/qemu/include/qom/cpu.h index 339ffb40..0345167c 100644 --- a/qemu/include/qom/cpu.h +++ b/qemu/include/qom/cpu.h @@ -538,26 +538,14 @@ ObjectClass *cpu_class_by_name(struct uc_struct *uc, const char *typename, const CPUState *cpu_create(struct uc_struct *uc, const char *typename); /** - * cpu_parse_cpu_model: - * @typename: The CPU base type or CPU type. + * parse_cpu_model: * @cpu_model: The model string including optional parameters. * * processes optional parameters and registers them as global properties * * Returns: type of CPU to create or %NULL if an error occurred. */ -const char *cpu_parse_cpu_model(struct uc_struct *uc, const char *typename, const char *cpu_model); - -/** - * cpu_generic_init: - * @typename: The CPU base type. - * @cpu_model: The model string including optional parameters. - * - * Instantiates a CPU, processes optional parameters and realizes the CPU. - * - * Returns: A #CPUState or %NULL if an error occurred. - */ -CPUState *cpu_generic_init(struct uc_struct *uc, const char *typename, const char *cpu_model); +const char *parse_cpu_model(struct uc_struct *uc, const char *cpu_model); /** * cpu_has_work: diff --git a/qemu/m68k.h b/qemu/m68k.h index 926f1bb3..ecd7499b 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_m68k #define par_write par_write_m68k #define parse_array parse_array_m68k +#define parse_cpu_model parse_cpu_model_m68k #define parse_error parse_error_m68k #define parse_escape parse_escape_m68k #define parse_keyword parse_keyword_m68k diff --git a/qemu/mips.h b/qemu/mips.h index f35826b9..d66d73a6 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_mips #define par_write par_write_mips #define parse_array parse_array_mips +#define parse_cpu_model parse_cpu_model_mips #define parse_error parse_error_mips #define parse_escape parse_escape_mips #define parse_keyword parse_keyword_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index e10cb052..42e318b3 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_mips64 #define par_write par_write_mips64 #define parse_array parse_array_mips64 +#define parse_cpu_model parse_cpu_model_mips64 #define parse_error parse_error_mips64 #define parse_escape parse_escape_mips64 #define parse_keyword parse_keyword_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index c3fd3f7a..b281b9aa 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_mips64el #define par_write par_write_mips64el #define parse_array parse_array_mips64el +#define parse_cpu_model parse_cpu_model_mips64el #define parse_error parse_error_mips64el #define parse_escape parse_escape_mips64el #define parse_keyword parse_keyword_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 8e67aa8d..81df74e8 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_mipsel #define par_write par_write_mipsel #define parse_array parse_array_mipsel +#define parse_cpu_model parse_cpu_model_mipsel #define parse_error parse_error_mipsel #define parse_escape parse_escape_mipsel #define parse_keyword parse_keyword_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index f527cdca..4a0946bf 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_powerpc #define par_write par_write_powerpc #define parse_array parse_array_powerpc +#define parse_cpu_model parse_cpu_model_powerpc #define parse_error parse_error_powerpc #define parse_escape parse_escape_powerpc #define parse_keyword parse_keyword_powerpc diff --git a/qemu/qom/cpu.c b/qemu/qom/cpu.c index 0946f5ce..fcb0e5f8 100644 --- a/qemu/qom/cpu.c +++ b/qemu/qom/cpu.c @@ -53,46 +53,6 @@ CPUState *cpu_create(struct uc_struct *uc, const char *typename) return cpu; } -const char *cpu_parse_cpu_model(struct uc_struct *uc, const char *typename, const char *cpu_model) -{ - ObjectClass *oc; - CPUClass *cc; - Error *err = NULL; - gchar **model_pieces; - const char *cpu_type; - - model_pieces = g_strsplit(cpu_model, ",", 2); - - oc = cpu_class_by_name(uc, typename, model_pieces[0]); - if (oc == NULL) { - g_strfreev(model_pieces); - return NULL; - } - - cpu_type = object_class_get_name(oc); - cc = CPU_CLASS(uc, oc); - cc->parse_features(uc, cpu_type, model_pieces[1], &err); - g_strfreev(model_pieces); - if (err != NULL) { - error_free(err); - return NULL; - } - return cpu_type; -} - -CPUState *cpu_generic_init(struct uc_struct *uc, const char *typename, const char *cpu_model) -{ - /* TODO: all callers of cpu_generic_init() need to be converted to - * call cpu_parse_features() only once, before calling cpu_generic_init(). - */ - const char *cpu_type = cpu_parse_cpu_model(uc, typename, cpu_model); - - if (cpu_type) { - return cpu_create(uc, cpu_type); - } - return NULL; -} - bool cpu_paging_enabled(const CPUState *cpu) { CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu); @@ -234,22 +194,17 @@ static ObjectClass *cpu_common_class_by_name(struct uc_struct *uc, const char *c static void cpu_common_parse_features(struct uc_struct *uc, const char *typename, char *features, Error **errp) { - char *featurestr; /* Single "key=value" string being parsed */ char *val; + /* Single "key=value" string being parsed */ + char *featurestr = features ? strtok(features, ",") : NULL; - /* TODO: all callers of ->parse_features() need to be changed to - * call it only once, so we can remove this check (or change it - * to assert(!cpu_globals_initialized). - * Current callers of ->parse_features() are: - * - cpu_generic_init() - */ + /* should be called only once, catch invalid users */ + assert(!uc->cpu_globals_initialized); if (uc->cpu_globals_initialized) { return; } uc->cpu_globals_initialized = true; - featurestr = features ? strtok(features, ",") : NULL; - while (featurestr) { val = strchr(featurestr, '='); if (val) { diff --git a/qemu/sparc.h b/qemu/sparc.h index 7f3d0ca4..f705f196 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_sparc #define par_write par_write_sparc #define parse_array parse_array_sparc +#define parse_cpu_model parse_cpu_model_sparc #define parse_error parse_error_sparc #define parse_escape parse_escape_sparc #define parse_keyword parse_keyword_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 8667a157..bca41e2c 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_sparc64 #define par_write par_write_sparc64 #define parse_array parse_array_sparc64 +#define parse_cpu_model parse_cpu_model_sparc64 #define parse_error parse_error_sparc64 #define parse_escape parse_escape_sparc64 #define parse_keyword parse_keyword_sparc64 diff --git a/qemu/target/sparc/cpu.c b/qemu/target/sparc/cpu.c index 831e7a6b..3b055a9f 100644 --- a/qemu/target/sparc/cpu.c +++ b/qemu/target/sparc/cpu.c @@ -514,105 +514,97 @@ static void print_features(FILE *f, fprintf_function cpu_fprintf, } #endif -static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features) +static void +cpu_add_feat_as_prop(const char *typename, const char *name, const char *val) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(feature_name); i++) { - if (feature_name[i] && !strcmp(flagname, feature_name[i])) { - *features |= 1 << i; - return; - } - } - //error_report("CPU feature %s not found", flagname); + // Unicorn: if'd out +#if 0 + GlobalProperty *prop = g_new0(typeof(*prop), 1); + prop->driver = typename; + prop->property = g_strdup(name); + prop->value = g_strdup(val); + prop->errp = &error_fatal; + qdev_prop_register_global(prop); +#endif } -static void sparc_cpu_parse_features(CPUState *cs, char *features, +/* Parse "+feature,-feature,feature=foo" CPU feature string */ +static void sparc_cpu_parse_features(struct uc_struct *uc, const char *typename, char *features, Error **errp) { - SPARCCPU *cpu = SPARC_CPU(cs->uc, cs); - sparc_def_t *cpu_def = &cpu->env.def; - char *featurestr; - uint32_t plus_features = 0; - uint32_t minus_features = 0; - uint64_t iu_version; - uint32_t fpu_version, mmu_version, nwindows; + GList *l, *plus_features = NULL, *minus_features = NULL; + char *featurestr; /* Single 'key=value" string being parsed */ + static bool cpu_globals_initialized; - featurestr = features ? strtok(features, ",") : NULL; - while (featurestr) { - char *val; + if (cpu_globals_initialized) { + return; + } + cpu_globals_initialized = true; + if (!features) { + return; + } + + for (featurestr = strtok(features, ","); + featurestr; + featurestr = strtok(NULL, ",")) { + const char *name; + const char *val = NULL; + char *eq = NULL; + + /* Compatibility syntax: */ if (featurestr[0] == '+') { - add_flagname_to_bitmaps(featurestr + 1, &plus_features); + plus_features = g_list_append(plus_features, + g_strdup(featurestr + 1)); + continue; } else if (featurestr[0] == '-') { - add_flagname_to_bitmaps(featurestr + 1, &minus_features); - } else if ((val = strchr(featurestr, '='))) { - *val = 0; val++; - if (!strcmp(featurestr, "iu_version")) { - char *err; + minus_features = g_list_append(minus_features, + g_strdup(featurestr + 1)); + continue; + } - iu_version = strtoll(val, &err, 0); - if (!*val || *err) { - error_setg(errp, "bad numerical value %s", val); - return; - } - cpu_def->iu_version = iu_version; -#ifdef DEBUG_FEATURES - fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version); -#endif - } else if (!strcmp(featurestr, "fpu_version")) { - char *err; + eq = strchr(featurestr, '='); + name = featurestr; + if (eq) { + *eq++ = 0; + val = eq; - fpu_version = strtol(val, &err, 0); - if (!*val || *err) { - error_setg(errp, "bad numerical value %s", val); - return; - } - cpu_def->fpu_version = fpu_version; -#ifdef DEBUG_FEATURES - fprintf(stderr, "fpu_version %x\n", fpu_version); -#endif - } else if (!strcmp(featurestr, "mmu_version")) { - char *err; - - mmu_version = strtol(val, &err, 0); - if (!*val || *err) { - error_setg(errp, "bad numerical value %s", val); - return; - } - cpu_def->mmu_version = mmu_version; -#ifdef DEBUG_FEATURES - fprintf(stderr, "mmu_version %x\n", mmu_version); -#endif - } else if (!strcmp(featurestr, "nwindows")) { - char *err; - - nwindows = strtol(val, &err, 0); - if (!*val || *err || nwindows > MAX_NWINDOWS || - nwindows < MIN_NWINDOWS) { - error_setg(errp, "bad numerical value %s", val); - return; - } - cpu_def->nwindows = nwindows; -#ifdef DEBUG_FEATURES - fprintf(stderr, "nwindows %d\n", nwindows); -#endif - } else { - error_setg(errp, "unrecognized feature %s", featurestr); + /* + * Temporarily, only +feat/-feat will be supported + * for boolean properties until we remove the + * minus-overrides-plus semantics and just follow + * the order options appear on the command-line. + * + * TODO: warn if user is relying on minus-override-plus semantics + * TODO: remove minus-override-plus semantics after + * warning for a few releases + */ + if (!strcasecmp(val, "on") || + !strcasecmp(val, "off") || + !strcasecmp(val, "true") || + !strcasecmp(val, "false")) { + error_setg(errp, "Boolean properties in format %s=%s" + " are not supported", name, val); return; } } else { - error_setg(errp, "feature string `%s' not in format " - "(+feature|-feature|feature=xyz)", featurestr); + error_setg(errp, "Unsupported property format: %s", name); return; } - featurestr = strtok(NULL, ","); + cpu_add_feat_as_prop(typename, name, val); } - cpu_def->features |= plus_features; - cpu_def->features &= ~minus_features; -#ifdef DEBUG_FEATURES - print_features(stderr, fprintf, cpu_def->features, NULL); -#endif + + for (l = plus_features; l; l = l->next) { + const char *name = l->data; + cpu_add_feat_as_prop(typename, name, "on"); + } + g_list_free_full(plus_features, g_free); + + for (l = minus_features; l; l = l->next) { + const char *name = l->data; + cpu_add_feat_as_prop(typename, name, "off"); + } + g_list_free_full(minus_features, g_free); } #if 0 diff --git a/qemu/vl.c b/qemu/vl.c index b2b8d42f..4a0ef6e6 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -162,12 +162,8 @@ int machine_initialize(struct uc_struct *uc) machine_class->max_cpus = 1; configure_accelerator(current_machine); - current_machine->cpu_model = NULL; - /* parse features once if machine provides default cpu_type */ - if (machine_class->default_cpu_type) { - current_machine->cpu_type = machine_class->default_cpu_type; - } + current_machine->cpu_type = machine_class->default_cpu_type; return machine_class->init(uc, current_machine); } diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 8802fe8b..26eb361e 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1947,6 +1947,7 @@ #define page_size_init page_size_init_x86_64 #define par_write par_write_x86_64 #define parse_array parse_array_x86_64 +#define parse_cpu_model parse_cpu_model_x86_64 #define parse_error parse_error_x86_64 #define parse_escape parse_escape_x86_64 #define parse_keyword parse_keyword_x86_64