Use cpu_create(type) instead of cpu_init(cpu_model)

With all targets defining CPU_RESOLVING_TYPE, refactor
cpu_parse_cpu_model(type, cpu_model) to parse_cpu_model(cpu_model)
so that callers won't have to know internal resolving cpu
type. Place it in exec.c so it could be called from both
target independed vl.c and *-user/main.c.

That allows us to stop abusing cpu type from
MachineClass::default_cpu_type
as resolver class in vl.c which were confusing part of
cpu_parse_cpu_model().

Also with new parse_cpu_model(), the last users of cpu_init()
in null-machine.c and bsd/linux-user targets could be switched
to cpu_create() API and cpu_init() API will be removed by
follow up patch.

With no longer users left remove MachineState::cpu_model field,
new code should use MachineState::cpu_type instead and
leave cpu_model parsing to generic code in vl.c.

Backports commit 2278b93941d42c30e2950d4b8dff4943d064e7de from qemu
This commit is contained in:
Igor Mammedov 2018-03-20 13:47:38 -04:00 committed by Lioncash
parent 7fe1504224
commit f8eeacb280
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
27 changed files with 241 additions and 180 deletions

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_aarch64 #define page_size_init page_size_init_aarch64
#define par_write par_write_aarch64 #define par_write par_write_aarch64
#define parse_array parse_array_aarch64 #define parse_array parse_array_aarch64
#define parse_cpu_model parse_cpu_model_aarch64
#define parse_error parse_error_aarch64 #define parse_error parse_error_aarch64
#define parse_escape parse_escape_aarch64 #define parse_escape parse_escape_aarch64
#define parse_keyword parse_keyword_aarch64 #define parse_keyword parse_keyword_aarch64

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_aarch64eb #define page_size_init page_size_init_aarch64eb
#define par_write par_write_aarch64eb #define par_write par_write_aarch64eb
#define parse_array parse_array_aarch64eb #define parse_array parse_array_aarch64eb
#define parse_cpu_model parse_cpu_model_aarch64eb
#define parse_error parse_error_aarch64eb #define parse_error parse_error_aarch64eb
#define parse_escape parse_escape_aarch64eb #define parse_escape parse_escape_aarch64eb
#define parse_keyword parse_keyword_aarch64eb #define parse_keyword parse_keyword_aarch64eb

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_arm #define page_size_init page_size_init_arm
#define par_write par_write_arm #define par_write par_write_arm
#define parse_array parse_array_arm #define parse_array parse_array_arm
#define parse_cpu_model parse_cpu_model_arm
#define parse_error parse_error_arm #define parse_error parse_error_arm
#define parse_escape parse_escape_arm #define parse_escape parse_escape_arm
#define parse_keyword parse_keyword_arm #define parse_keyword parse_keyword_arm

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_armeb #define page_size_init page_size_init_armeb
#define par_write par_write_armeb #define par_write par_write_armeb
#define parse_array parse_array_armeb #define parse_array parse_array_armeb
#define parse_cpu_model parse_cpu_model_armeb
#define parse_error parse_error_armeb #define parse_error parse_error_armeb
#define parse_escape parse_escape_armeb #define parse_escape parse_escape_armeb
#define parse_keyword parse_keyword_armeb #define parse_keyword parse_keyword_armeb

View file

@ -620,6 +620,29 @@ void cpu_exec_init(CPUState *cpu, void *opaque)
#endif #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) #if defined(CONFIG_USER_ONLY)
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
{ {

View file

@ -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.
*
* <note><para>
* The return value is the new start of the list, which
* may have changed, so make sure you store the new value.
* </para></note>
*
* <note><para>
* 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.
* </para></note>
*
* |[
* /&ast; Notice that these are initialized to the empty list. &ast;/
* GList *list = NULL, *number_list = NULL;
*
* /&ast; This is a list of strings. &ast;/
* list = g_list_append (list, "first");
* list = g_list_append (list, "second");
*
* /&ast; This is a list of integers. &ast;/
* 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 *g_list_insert_sorted(GList *list, gpointer data, GCompareFunc compare)
{ {
GList *i; GList *i;

View file

@ -1953,6 +1953,7 @@ symbols = (
'page_size_init', 'page_size_init',
'par_write', 'par_write',
'parse_array', 'parse_array',
'parse_cpu_model',
'parse_error', 'parse_error',
'parse_escape', 'parse_escape',
'parse_keyword', 'parse_keyword',

View file

@ -22,9 +22,9 @@
static int tosa_init(struct uc_struct *uc, MachineState *machine) static int tosa_init(struct uc_struct *uc, MachineState *machine)
{ {
if (uc->mode & UC_MODE_MCLASS) { if (uc->mode & UC_MODE_MCLASS) {
uc->cpu = cpu_init(uc, "cortex-m3"); uc->cpu = cpu_create(uc, "cortex-m3");
} else { } else {
uc->cpu = cpu_init(uc, "cortex-a15"); uc->cpu = cpu_create(uc, "cortex-a15");
} }
return 0; return 0;

View file

@ -19,14 +19,10 @@
/* Board init. */ /* Board init. */
static int dummy_m68k_init(struct uc_struct *uc, MachineState *machine) static int dummy_m68k_init(struct uc_struct *uc, MachineState *machine)
{ {
const char *cpu_model = machine->cpu_model;
CPUM68KState *env; CPUM68KState *env;
const char *cpu_type = parse_cpu_model(uc, "cf4ve");
if (!cpu_model) { uc->cpu = cpu_create(uc, cpu_type);
cpu_model = "cfv4e";
}
uc->cpu = cpu_init(uc, cpu_model);
if (!uc->cpu) { if (!uc->cpu) {
fprintf(stderr, "Unable to find m68k CPU definition\n"); fprintf(stderr, "Unable to find m68k CPU definition\n");
return -1; return -1;
@ -45,6 +41,7 @@ static void dummy_m68k_machine_init(struct uc_struct *uc, MachineClass *mc)
mc->init = dummy_m68k_init; mc->init = dummy_m68k_init;
mc->is_default = 1; mc->is_default = 1;
mc->arch = UC_ARCH_M68K; mc->arch = UC_ARCH_M68K;
mc->default_cpu_type = M68K_CPU_TYPE_NAME("cfv4e");
} }
DEFINE_MACHINE("dummy", dummy_m68k_machine_init) DEFINE_MACHINE("dummy", dummy_m68k_machine_init)

View file

@ -25,18 +25,14 @@
static int mips_r4k_init(struct uc_struct *uc, MachineState *machine) 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 #ifdef TARGET_MIPS64
cpu_model = "R4000"; const char *cpu_model = MIPS_CPU_TYPE_NAME("R4000");
#else #else
cpu_model = "24Kf"; const char *cpu_model = MIPS_CPU_TYPE_NAME("24Kf");
#endif #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) { if (uc->cpu == NULL) {
fprintf(stderr, "Unable to find CPU definition\n"); fprintf(stderr, "Unable to find CPU definition\n");
return -1; return -1;
@ -50,6 +46,11 @@ static void mips_machine_init(struct uc_struct *uc, MachineClass *mc)
mc->init = mips_r4k_init; mc->init = mips_r4k_init;
mc->is_default = 1; mc->is_default = 1;
mc->arch = UC_ARCH_MIPS; 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) DEFINE_MACHINE("mips", mips_machine_init)

View file

@ -38,15 +38,10 @@
static int leon3_generic_hw_init(struct uc_struct *uc, MachineState *machine) 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; SPARCCPU *cpu;
/* Init CPU */ uc->cpu = cpu_create(uc, cpu_type);
if (!cpu_model) {
cpu_model = "LEON3";
}
uc->cpu = cpu_init(uc, cpu_model);
cpu = SPARC_CPU(uc, uc->cpu); cpu = SPARC_CPU(uc, uc->cpu);
if (cpu == NULL) { if (cpu == NULL) {
fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); 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->init = leon3_generic_hw_init;
mc->is_default = 1; mc->is_default = 1;
mc->arch = UC_ARCH_SPARC; mc->arch = UC_ARCH_SPARC;
mc->default_cpu_type = SPARC_CPU_TYPE_NAME("LEON3");
} }
DEFINE_MACHINE("leon3_generic", leon3_generic_machine_init) DEFINE_MACHINE("leon3_generic", leon3_generic_machine_init)

View file

@ -36,14 +36,10 @@
/* Sun4u hardware initialisation */ /* Sun4u hardware initialisation */
static int sun4u_init(struct uc_struct *uc, MachineState *machine) 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; SPARCCPU *cpu;
if (cpu_model == NULL) { uc->cpu = cpu_create(uc, cpu_type);
cpu_model = "Sun UltraSparc IV";
}
uc->cpu = cpu_init(uc, cpu_model);
cpu = SPARC_CPU(uc, uc->cpu); cpu = SPARC_CPU(uc, uc->cpu);
if (cpu == NULL) { if (cpu == NULL) {
fprintf(stderr, "Unable to find Sparc CPU definition\n"); 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->max_cpus = 1; /* XXX for now */
mc->is_default = 1; mc->is_default = 1;
mc->arch = UC_ARCH_SPARC; mc->arch = UC_ARCH_SPARC;
mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Sun UltraSparc IV");
} }
static const TypeInfo sun4u_type = { static const TypeInfo sun4u_type = {

View file

@ -74,9 +74,12 @@ typedef struct _GList {
struct _GList *prev; struct _GList *prev;
} GList; } GList;
GList* g_list_append(GList *list, gpointer data);
GList *g_list_first(GList *list); 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_foreach(GList *list, GFunc func, gpointer user_data);
void g_list_free(GList *list); 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_before(GList *list, GList *sibling, gpointer data);
GList *g_list_insert_sorted(GList *list, gpointer data, GCompareFunc compare); GList *g_list_insert_sorted(GList *list, gpointer data, GCompareFunc compare);
#define g_list_next(list) (list->next) #define g_list_next(list) (list->next)

View file

@ -112,7 +112,6 @@ struct MachineState {
/*< public >*/ /*< public >*/
ram_addr_t ram_size; ram_addr_t ram_size;
ram_addr_t maxram_size; ram_addr_t maxram_size;
const char *cpu_model;
const char *cpu_type; const char *cpu_type;
struct uc_struct *uc; struct uc_struct *uc;
AccelState *accelerator; AccelState *accelerator;

View file

@ -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); CPUState *cpu_create(struct uc_struct *uc, const char *typename);
/** /**
* cpu_parse_cpu_model: * parse_cpu_model:
* @typename: The CPU base type or CPU type.
* @cpu_model: The model string including optional parameters. * @cpu_model: The model string including optional parameters.
* *
* processes optional parameters and registers them as global properties * processes optional parameters and registers them as global properties
* *
* Returns: type of CPU to create or %NULL if an error occurred. * 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); const char *parse_cpu_model(struct uc_struct *uc, 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);
/** /**
* cpu_has_work: * cpu_has_work:

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_m68k #define page_size_init page_size_init_m68k
#define par_write par_write_m68k #define par_write par_write_m68k
#define parse_array parse_array_m68k #define parse_array parse_array_m68k
#define parse_cpu_model parse_cpu_model_m68k
#define parse_error parse_error_m68k #define parse_error parse_error_m68k
#define parse_escape parse_escape_m68k #define parse_escape parse_escape_m68k
#define parse_keyword parse_keyword_m68k #define parse_keyword parse_keyword_m68k

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_mips #define page_size_init page_size_init_mips
#define par_write par_write_mips #define par_write par_write_mips
#define parse_array parse_array_mips #define parse_array parse_array_mips
#define parse_cpu_model parse_cpu_model_mips
#define parse_error parse_error_mips #define parse_error parse_error_mips
#define parse_escape parse_escape_mips #define parse_escape parse_escape_mips
#define parse_keyword parse_keyword_mips #define parse_keyword parse_keyword_mips

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_mips64 #define page_size_init page_size_init_mips64
#define par_write par_write_mips64 #define par_write par_write_mips64
#define parse_array parse_array_mips64 #define parse_array parse_array_mips64
#define parse_cpu_model parse_cpu_model_mips64
#define parse_error parse_error_mips64 #define parse_error parse_error_mips64
#define parse_escape parse_escape_mips64 #define parse_escape parse_escape_mips64
#define parse_keyword parse_keyword_mips64 #define parse_keyword parse_keyword_mips64

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_mips64el #define page_size_init page_size_init_mips64el
#define par_write par_write_mips64el #define par_write par_write_mips64el
#define parse_array parse_array_mips64el #define parse_array parse_array_mips64el
#define parse_cpu_model parse_cpu_model_mips64el
#define parse_error parse_error_mips64el #define parse_error parse_error_mips64el
#define parse_escape parse_escape_mips64el #define parse_escape parse_escape_mips64el
#define parse_keyword parse_keyword_mips64el #define parse_keyword parse_keyword_mips64el

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_mipsel #define page_size_init page_size_init_mipsel
#define par_write par_write_mipsel #define par_write par_write_mipsel
#define parse_array parse_array_mipsel #define parse_array parse_array_mipsel
#define parse_cpu_model parse_cpu_model_mipsel
#define parse_error parse_error_mipsel #define parse_error parse_error_mipsel
#define parse_escape parse_escape_mipsel #define parse_escape parse_escape_mipsel
#define parse_keyword parse_keyword_mipsel #define parse_keyword parse_keyword_mipsel

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_powerpc #define page_size_init page_size_init_powerpc
#define par_write par_write_powerpc #define par_write par_write_powerpc
#define parse_array parse_array_powerpc #define parse_array parse_array_powerpc
#define parse_cpu_model parse_cpu_model_powerpc
#define parse_error parse_error_powerpc #define parse_error parse_error_powerpc
#define parse_escape parse_escape_powerpc #define parse_escape parse_escape_powerpc
#define parse_keyword parse_keyword_powerpc #define parse_keyword parse_keyword_powerpc

View file

@ -53,46 +53,6 @@ CPUState *cpu_create(struct uc_struct *uc, const char *typename)
return cpu; 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) bool cpu_paging_enabled(const CPUState *cpu)
{ {
CPUClass *cc = CPU_GET_CLASS(cpu->uc, 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, static void cpu_common_parse_features(struct uc_struct *uc, const char *typename, char *features,
Error **errp) Error **errp)
{ {
char *featurestr; /* Single "key=value" string being parsed */
char *val; 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 /* should be called only once, catch invalid users */
* call it only once, so we can remove this check (or change it assert(!uc->cpu_globals_initialized);
* to assert(!cpu_globals_initialized).
* Current callers of ->parse_features() are:
* - cpu_generic_init()
*/
if (uc->cpu_globals_initialized) { if (uc->cpu_globals_initialized) {
return; return;
} }
uc->cpu_globals_initialized = true; uc->cpu_globals_initialized = true;
featurestr = features ? strtok(features, ",") : NULL;
while (featurestr) { while (featurestr) {
val = strchr(featurestr, '='); val = strchr(featurestr, '=');
if (val) { if (val) {

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_sparc #define page_size_init page_size_init_sparc
#define par_write par_write_sparc #define par_write par_write_sparc
#define parse_array parse_array_sparc #define parse_array parse_array_sparc
#define parse_cpu_model parse_cpu_model_sparc
#define parse_error parse_error_sparc #define parse_error parse_error_sparc
#define parse_escape parse_escape_sparc #define parse_escape parse_escape_sparc
#define parse_keyword parse_keyword_sparc #define parse_keyword parse_keyword_sparc

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_sparc64 #define page_size_init page_size_init_sparc64
#define par_write par_write_sparc64 #define par_write par_write_sparc64
#define parse_array parse_array_sparc64 #define parse_array parse_array_sparc64
#define parse_cpu_model parse_cpu_model_sparc64
#define parse_error parse_error_sparc64 #define parse_error parse_error_sparc64
#define parse_escape parse_escape_sparc64 #define parse_escape parse_escape_sparc64
#define parse_keyword parse_keyword_sparc64 #define parse_keyword parse_keyword_sparc64

View file

@ -514,105 +514,97 @@ static void print_features(FILE *f, fprintf_function cpu_fprintf,
} }
#endif #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; // Unicorn: if'd out
#if 0
for (i = 0; i < ARRAY_SIZE(feature_name); i++) { GlobalProperty *prop = g_new0(typeof(*prop), 1);
if (feature_name[i] && !strcmp(flagname, feature_name[i])) { prop->driver = typename;
*features |= 1 << i; prop->property = g_strdup(name);
return; prop->value = g_strdup(val);
} prop->errp = &error_fatal;
} qdev_prop_register_global(prop);
//error_report("CPU feature %s not found", flagname); #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) Error **errp)
{ {
SPARCCPU *cpu = SPARC_CPU(cs->uc, cs); GList *l, *plus_features = NULL, *minus_features = NULL;
sparc_def_t *cpu_def = &cpu->env.def; char *featurestr; /* Single 'key=value" string being parsed */
char *featurestr; static bool cpu_globals_initialized;
uint32_t plus_features = 0;
uint32_t minus_features = 0;
uint64_t iu_version;
uint32_t fpu_version, mmu_version, nwindows;
featurestr = features ? strtok(features, ",") : NULL; if (cpu_globals_initialized) {
while (featurestr) { return;
char *val; }
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] == '+') { 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] == '-') { } else if (featurestr[0] == '-') {
add_flagname_to_bitmaps(featurestr + 1, &minus_features); minus_features = g_list_append(minus_features,
} else if ((val = strchr(featurestr, '='))) { g_strdup(featurestr + 1));
*val = 0; val++; continue;
if (!strcmp(featurestr, "iu_version")) { }
char *err;
iu_version = strtoll(val, &err, 0); eq = strchr(featurestr, '=');
if (!*val || *err) { name = featurestr;
error_setg(errp, "bad numerical value %s", val); if (eq) {
return; *eq++ = 0;
} val = eq;
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;
fpu_version = strtol(val, &err, 0); /*
if (!*val || *err) { * Temporarily, only +feat/-feat will be supported
error_setg(errp, "bad numerical value %s", val); * for boolean properties until we remove the
return; * minus-overrides-plus semantics and just follow
} * the order options appear on the command-line.
cpu_def->fpu_version = fpu_version; *
#ifdef DEBUG_FEATURES * TODO: warn if user is relying on minus-override-plus semantics
fprintf(stderr, "fpu_version %x\n", fpu_version); * TODO: remove minus-override-plus semantics after
#endif * warning for a few releases
} else if (!strcmp(featurestr, "mmu_version")) { */
char *err; if (!strcasecmp(val, "on") ||
!strcasecmp(val, "off") ||
mmu_version = strtol(val, &err, 0); !strcasecmp(val, "true") ||
if (!*val || *err) { !strcasecmp(val, "false")) {
error_setg(errp, "bad numerical value %s", val); error_setg(errp, "Boolean properties in format %s=%s"
return; " are not supported", name, val);
}
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);
return; return;
} }
} else { } else {
error_setg(errp, "feature string `%s' not in format " error_setg(errp, "Unsupported property format: %s", name);
"(+feature|-feature|feature=xyz)", featurestr);
return; return;
} }
featurestr = strtok(NULL, ","); cpu_add_feat_as_prop(typename, name, val);
} }
cpu_def->features |= plus_features;
cpu_def->features &= ~minus_features; for (l = plus_features; l; l = l->next) {
#ifdef DEBUG_FEATURES const char *name = l->data;
print_features(stderr, fprintf, cpu_def->features, NULL); cpu_add_feat_as_prop(typename, name, "on");
#endif }
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 #if 0

View file

@ -162,12 +162,8 @@ int machine_initialize(struct uc_struct *uc)
machine_class->max_cpus = 1; machine_class->max_cpus = 1;
configure_accelerator(current_machine); configure_accelerator(current_machine);
current_machine->cpu_model = NULL;
/* parse features once if machine provides default cpu_type */ /* 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); return machine_class->init(uc, current_machine);
} }

View file

@ -1947,6 +1947,7 @@
#define page_size_init page_size_init_x86_64 #define page_size_init page_size_init_x86_64
#define par_write par_write_x86_64 #define par_write par_write_x86_64
#define parse_array parse_array_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_error parse_error_x86_64
#define parse_escape parse_escape_x86_64 #define parse_escape parse_escape_x86_64
#define parse_keyword parse_keyword_x86_64 #define parse_keyword parse_keyword_x86_64