mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-22 19:15:36 +00:00
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:
parent
7fe1504224
commit
f8eeacb280
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
23
qemu/exec.c
23
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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
*
|
||||
* |[
|
||||
* /* 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;
|
||||
|
|
|
@ -1953,6 +1953,7 @@ symbols = (
|
|||
'page_size_init',
|
||||
'par_write',
|
||||
'parse_array',
|
||||
'parse_cpu_model',
|
||||
'parse_error',
|
||||
'parse_escape',
|
||||
'parse_keyword',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
iu_version = strtoll(val, &err, 0);
|
||||
if (!*val || *err) {
|
||||
error_setg(errp, "bad numerical value %s", val);
|
||||
return;
|
||||
minus_features = g_list_append(minus_features,
|
||||
g_strdup(featurestr + 1));
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
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;
|
||||
eq = strchr(featurestr, '=');
|
||||
name = featurestr;
|
||||
if (eq) {
|
||||
*eq++ = 0;
|
||||
val = eq;
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
return machine_class->init(uc, current_machine);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue