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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)
{

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 *i;

View file

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

View file

@ -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;

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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 = {

View file

@ -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)

View file

@ -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;

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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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