diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h index b9896f2647..1b9479eb9c 100644 --- a/target-xtensa/cpu-qom.h +++ b/target-xtensa/cpu-qom.h @@ -45,6 +45,7 @@ * XtensaCPUClass: * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. + * @config: The CPU core configuration. * * An Xtensa CPU model. */ @@ -55,6 +56,8 @@ typedef struct XtensaCPUClass { DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); + + const XtensaConfig *config; } XtensaCPUClass; /** diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c index d2bcfc69a2..5a39971d2c 100644 --- a/target-xtensa/cpu.c +++ b/target-xtensa/cpu.c @@ -64,6 +64,25 @@ static void xtensa_cpu_reset(CPUState *s) reset_mmu(env); } +static ObjectClass *xtensa_cpu_class_by_name(const char *cpu_model) +{ + ObjectClass *oc; + char *typename; + + if (cpu_model == NULL) { + return NULL; + } + + typename = g_strdup_printf("%s-" TYPE_XTENSA_CPU, cpu_model); + oc = object_class_by_name(typename); + g_free(typename); + if (oc == NULL || !object_class_dynamic_cast(oc, TYPE_XTENSA_CPU) || + object_class_is_abstract(oc)) { + return NULL; + } + return oc; +} + static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp) { XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev); @@ -75,10 +94,12 @@ static void xtensa_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); XtensaCPU *cpu = XTENSA_CPU(obj); + XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(obj); CPUXtensaState *env = &cpu->env; static bool tcg_inited; cs->env_ptr = env; + env->config = xcc->config; cpu_exec_init(env); if (tcg_enabled() && !tcg_inited) { @@ -105,6 +126,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) xcc->parent_reset = cc->reset; cc->reset = xtensa_cpu_reset; + cc->class_by_name = xtensa_cpu_class_by_name; cc->do_interrupt = xtensa_cpu_do_interrupt; cc->dump_state = xtensa_cpu_dump_state; cc->set_pc = xtensa_cpu_set_pc; @@ -119,7 +141,7 @@ static const TypeInfo xtensa_cpu_type_info = { .parent = TYPE_CPU, .instance_size = sizeof(XtensaCPU), .instance_init = xtensa_cpu_initfn, - .abstract = false, + .abstract = true, .class_size = sizeof(XtensaCPUClass), .class_init = xtensa_cpu_class_init, }; diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index de6cc3b7c5..e3098798af 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -35,10 +35,27 @@ static struct XtensaConfigList *xtensa_cores; +static void xtensa_core_class_init(ObjectClass *oc, void *data) +{ + XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc); + const XtensaConfig *config = data; + + xcc->config = config; +} + void xtensa_register_core(XtensaConfigList *node) { + TypeInfo type = { + .parent = TYPE_XTENSA_CPU, + .class_init = xtensa_core_class_init, + .class_data = (void *)node->config, + }; + node->next = xtensa_cores; xtensa_cores = node; + type.name = g_strdup_printf("%s-" TYPE_XTENSA_CPU, node->config->name); + type_register(&type); + g_free((gpointer)type.name); } static uint32_t check_hw_breakpoints(CPUXtensaState *env) @@ -72,24 +89,17 @@ void xtensa_breakpoint_handler(CPUXtensaState *env) XtensaCPU *cpu_xtensa_init(const char *cpu_model) { + ObjectClass *oc; XtensaCPU *cpu; CPUXtensaState *env; - const XtensaConfig *config = NULL; - XtensaConfigList *core = xtensa_cores; - for (; core; core = core->next) - if (strcmp(core->config->name, cpu_model) == 0) { - config = core->config; - break; - } - - if (config == NULL) { + oc = cpu_class_by_name(TYPE_XTENSA_CPU, cpu_model); + if (oc == NULL) { return NULL; } - cpu = XTENSA_CPU(object_new(TYPE_XTENSA_CPU)); + cpu = XTENSA_CPU(object_new(object_class_get_name(oc))); env = &cpu->env; - env->config = config; xtensa_irq_init(env);