diff mbox

[v2,01/14] target-arm: Add QOM subclasses for each ARM cpu implementation

Message ID 1334421743-31146-3-git-send-email-peter.maydell@linaro.org
State New
Headers show

Commit Message

Peter Maydell April 14, 2012, 4:42 p.m. UTC
Register subclasses for each ARM CPU implementation (with the
exception of "pxa270", which is an alias for "pxa270-a0").

Let arm_cpu_list() enumerate CPU subclasses in alphabetical order,
except for special value "any".

Replace cpu_arm_find_by_name()'s string -> CPUID lookup by storing the
CPUID (aka MIDR, Main ID Register) value in the class.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/cpu-qom.h |   12 +++
 target-arm/cpu.c     |  226 +++++++++++++++++++++++++++++++++++++++++++++++++-
 target-arm/helper.c  |  109 ++++++++++--------------
 3 files changed, 282 insertions(+), 65 deletions(-)

Comments

Peter Maydell April 14, 2012, 11:18 p.m. UTC | #1
On 14 April 2012 18:39, Andreas Färber <afaerber@suse.de> wrote:
> Am 14.04.2012 18:42, schrieb Peter Maydell:
>> Register subclasses for each ARM CPU implementation (with the
>> exception of "pxa270", which is an alias for "pxa270-a0").
>
> This is no longer accurate, we do have a subclass for "pxa270" again.

Oops, yes.

>> +    /* "pxa270" is a legacy alias for "pxa270-a0" */
>> +    { .name = "pxa270",      .initfn = pxa270a0_initfn },
>> +    { .name = "pxa270-a0",   .initfn = pxa270a0_initfn },
>> +    { .name = "pxa270-a1",   .initfn = pxa270a1_initfn },
>> +    { .name = "pxa270-b0",   .initfn = pxa270b0_initfn },
>> +    { .name = "pxa270-b1",   .initfn = pxa270b1_initfn },
>> +    { .name = "pxa270-c0",   .initfn = pxa270c0_initfn },
>> +    { .name = "pxa270-c5",   .initfn = pxa270c5_initfn },
>
> Wrt the comment: What's your plan for these? I think an earlier patch of
> mine went back to keeping only "pxa270" and having the other ones be
> aliases for "pxa270" plus some object_property_set_int()s. Are you
> planning to keep their initfns around instead?

I don't really have a plan here -- these are a little ugly but not
horrifically or wide-rangingly so, so I will probably leave them be
in favour of trying to deal with other bits of the codebase, unless
fixing them falls out in the wash of some kind of rev/patchlevel
property at some point.

> Maybe just say "an alias for"? (no need to resend)

Agreed.

-- PMM
Andreas Färber April 20, 2012, 2:28 p.m. UTC | #2
Am 15.04.2012 01:18, schrieb Peter Maydell:
> On 14 April 2012 18:39, Andreas Färber <afaerber@suse.de> wrote:
>> Am 14.04.2012 18:42, schrieb Peter Maydell:
>>> Register subclasses for each ARM CPU implementation (with the
>>> exception of "pxa270", which is an alias for "pxa270-a0").
>>
>> This is no longer accurate, we do have a subclass for "pxa270" again.
> 
> Oops, yes.
> 
>>> +    /* "pxa270" is a legacy alias for "pxa270-a0" */
>>> +    { .name = "pxa270",      .initfn = pxa270a0_initfn },
>>> +    { .name = "pxa270-a0",   .initfn = pxa270a0_initfn },
>>> +    { .name = "pxa270-a1",   .initfn = pxa270a1_initfn },
>>> +    { .name = "pxa270-b0",   .initfn = pxa270b0_initfn },
>>> +    { .name = "pxa270-b1",   .initfn = pxa270b1_initfn },
>>> +    { .name = "pxa270-c0",   .initfn = pxa270c0_initfn },
>>> +    { .name = "pxa270-c5",   .initfn = pxa270c5_initfn },
>>
>> Wrt the comment: What's your plan for these? I think an earlier patch of
>> mine went back to keeping only "pxa270" and having the other ones be
>> aliases for "pxa270" plus some object_property_set_int()s. Are you
>> planning to keep their initfns around instead?
> 
> I don't really have a plan here -- these are a little ugly but not
> horrifically or wide-rangingly so, so I will probably leave them be
> in favour of trying to deal with other bits of the codebase, unless
> fixing them falls out in the wash of some kind of rev/patchlevel
> property at some point.
> 
>> Maybe just say "an alias for"? (no need to resend)
> 
> Agreed.

Updated version

Acked-by: Andreas Färber <afaerber@suse.de>

Thanks,
/-F

> 
> -- PMM
>
Eduardo Habkost Nov. 12, 2012, 10:16 p.m. UTC | #3
Sorry for replying to a patch 7 months later, but I just have a question
related to how we will handle CPU model classes on all targets:

On Sat, Apr 14, 2012 at 05:42:10PM +0100, Peter Maydell wrote:
> Register subclasses for each ARM CPU implementation (with the
> exception of "pxa270", which is an alias for "pxa270-a0").
> 
> Let arm_cpu_list() enumerate CPU subclasses in alphabetical order,
> except for special value "any".
> 
> Replace cpu_arm_find_by_name()'s string -> CPUID lookup by storing the
> CPUID (aka MIDR, Main ID Register) value in the class.
> 
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/cpu-qom.h |   12 +++
>  target-arm/cpu.c     |  226 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  target-arm/helper.c  |  109 ++++++++++--------------
>  3 files changed, 282 insertions(+), 65 deletions(-)
> 
> diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
> index 42d2a6b..a4bcb31 100644
> --- a/target-arm/cpu-qom.h
> +++ b/target-arm/cpu-qom.h
> @@ -58,6 +58,18 @@ typedef struct ARMCPU {
[...]
> +typedef struct ARMCPUInfo {
> +    const char *name;
> +    void (*initfn)(Object *obj);
> +} ARMCPUInfo;
> +
> +static const ARMCPUInfo arm_cpus[] = {
[...]
> +    { .name = "any",         .initfn = arm_any_initfn },
> +};
> +

Do we really want to use "any" as the class name? Maybe we should use
"cpu-<model>" as the namespace for the CPU model class names? Or maybe
try "cpu-<model>" first, and then "<model>" as a fallback (making sure
that the class we found is a subclass of TYPE_<arch>_CPU).

I guess we will want address this before qdevifying the CPU class, as
the qdevification will make the CPU class names visible through the
monitor.


>  static void arm_cpu_class_init(ObjectClass *oc, void *data)
>  {
>      ARMCPUClass *acc = ARM_CPU_CLASS(oc);
> @@ -43,18 +248,37 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
>      cc->reset = arm_cpu_reset;
>  }
>  
> +static void cpu_register(const ARMCPUInfo *info)
> +{
> +    TypeInfo type_info = {
> +        .name = info->name,
> +        .parent = TYPE_ARM_CPU,
> +        .instance_size = sizeof(ARMCPU),
> +        .instance_init = info->initfn,
> +        .class_size = sizeof(ARMCPUClass),
> +    };
> +
> +    type_register_static(&type_info);
> +}
> +
>  static const TypeInfo arm_cpu_type_info = {
>      .name = TYPE_ARM_CPU,
>      .parent = TYPE_CPU,
>      .instance_size = sizeof(ARMCPU),
> -    .abstract = false,
> +    .instance_init = arm_cpu_initfn,
> +    .abstract = true,
>      .class_size = sizeof(ARMCPUClass),
>      .class_init = arm_cpu_class_init,
>  };
>  
>  static void arm_cpu_register_types(void)
>  {
> +    int i;
> +
>      type_register_static(&arm_cpu_type_info);
> +    for (i = 0; i < ARRAY_SIZE(arm_cpus); i++) {
> +        cpu_register(&arm_cpus[i]);
> +    }
>  }
>  
>  type_init(arm_cpu_register_types)
Peter Maydell Nov. 12, 2012, 10:18 p.m. UTC | #4
On 12 November 2012 22:16, Eduardo Habkost <ehabkost@redhat.com> wrote:
>
> Sorry for replying to a patch 7 months later, but I just have a question
> related to how we will handle CPU model classes on all targets:
>
> On Sat, Apr 14, 2012 at 05:42:10PM +0100, Peter Maydell wrote:
>> Register subclasses for each ARM CPU implementation (with the
>> exception of "pxa270", which is an alias for "pxa270-a0").
>>
>> Let arm_cpu_list() enumerate CPU subclasses in alphabetical order,
>> except for special value "any".
>>
>> Replace cpu_arm_find_by_name()'s string -> CPUID lookup by storing the
>> CPUID (aka MIDR, Main ID Register) value in the class.
>>
>> Signed-off-by: Andreas Färber <afaerber@suse.de>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>> ---
>>  target-arm/cpu-qom.h |   12 +++
>>  target-arm/cpu.c     |  226 +++++++++++++++++++++++++++++++++++++++++++++++++-
>>  target-arm/helper.c  |  109 ++++++++++--------------
>>  3 files changed, 282 insertions(+), 65 deletions(-)
>>
>> diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
>> index 42d2a6b..a4bcb31 100644
>> --- a/target-arm/cpu-qom.h
>> +++ b/target-arm/cpu-qom.h
>> @@ -58,6 +58,18 @@ typedef struct ARMCPU {
> [...]
>> +typedef struct ARMCPUInfo {
>> +    const char *name;
>> +    void (*initfn)(Object *obj);
>> +} ARMCPUInfo;
>> +
>> +static const ARMCPUInfo arm_cpus[] = {
> [...]
>> +    { .name = "any",         .initfn = arm_any_initfn },
>> +};
>> +
>
> Do we really want to use "any" as the class name?

Probably not, since it would make it tricky to (in some future
utopia) have a QEMU which supported more than one CPU architecture
in the same binary if they all wanted to use "any"...

> Maybe we should use
> "cpu-<model>" as the namespace for the CPU model class names?

Sounds reasonable.

-- PMM
Eduardo Habkost Nov. 12, 2012, 10:33 p.m. UTC | #5
On Mon, Nov 12, 2012 at 10:18:29PM +0000, Peter Maydell wrote:
> On 12 November 2012 22:16, Eduardo Habkost <ehabkost@redhat.com> wrote:
> >
> > Sorry for replying to a patch 7 months later, but I just have a question
> > related to how we will handle CPU model classes on all targets:
> >
> > On Sat, Apr 14, 2012 at 05:42:10PM +0100, Peter Maydell wrote:
> >> Register subclasses for each ARM CPU implementation (with the
> >> exception of "pxa270", which is an alias for "pxa270-a0").
> >>
> >> Let arm_cpu_list() enumerate CPU subclasses in alphabetical order,
> >> except for special value "any".
> >>
> >> Replace cpu_arm_find_by_name()'s string -> CPUID lookup by storing the
> >> CPUID (aka MIDR, Main ID Register) value in the class.
> >>
> >> Signed-off-by: Andreas Färber <afaerber@suse.de>
> >> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> >> ---
> >>  target-arm/cpu-qom.h |   12 +++
> >>  target-arm/cpu.c     |  226 +++++++++++++++++++++++++++++++++++++++++++++++++-
> >>  target-arm/helper.c  |  109 ++++++++++--------------
> >>  3 files changed, 282 insertions(+), 65 deletions(-)
> >>
> >> diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
> >> index 42d2a6b..a4bcb31 100644
> >> --- a/target-arm/cpu-qom.h
> >> +++ b/target-arm/cpu-qom.h
> >> @@ -58,6 +58,18 @@ typedef struct ARMCPU {
> > [...]
> >> +typedef struct ARMCPUInfo {
> >> +    const char *name;
> >> +    void (*initfn)(Object *obj);
> >> +} ARMCPUInfo;
> >> +
> >> +static const ARMCPUInfo arm_cpus[] = {
> > [...]
> >> +    { .name = "any",         .initfn = arm_any_initfn },
> >> +};
> >> +
> >
> > Do we really want to use "any" as the class name?
> 
> Probably not, since it would make it tricky to (in some future
> utopia) have a QEMU which supported more than one CPU architecture
> in the same binary if they all wanted to use "any"...

In that case, "cpu-any" wouldn't work, either. What about
"<arch>-cpu-<model>"?

> 
> > Maybe we should use
> > "cpu-<model>" as the namespace for the CPU model class names?
> 
> Sounds reasonable.
> 
> -- PMM
Andreas Färber Nov. 13, 2012, 11:51 a.m. UTC | #6
Am 12.11.2012 23:33, schrieb Eduardo Habkost:
> On Mon, Nov 12, 2012 at 10:18:29PM +0000, Peter Maydell wrote:
>> On 12 November 2012 22:16, Eduardo Habkost <ehabkost@redhat.com> wrote:
>>> On Sat, Apr 14, 2012 at 05:42:10PM +0100, Peter Maydell wrote:
>>>> +static const ARMCPUInfo arm_cpus[] = {
>>> [...]
>>>> +    { .name = "any",         .initfn = arm_any_initfn },
>>>> +};
>>>> +
>>>
>>> Do we really want to use "any" as the class name?
>>
>> Probably not, since it would make it tricky to (in some future
>> utopia) have a QEMU which supported more than one CPU architecture
>> in the same binary if they all wanted to use "any"...
> 
> In that case, "cpu-any" wouldn't work, either. What about
> "<arch>-cpu-<model>"?

Fine with me. However, keep in mind the previous approach was used for
command line compatibility: I would like to continue using -cpu
cortex-a9 rather than -cpu arm-cpu-cortex-a9. :)

If we introduce a more complex command-line-to-class mapping, can't we
drop these ominous "any" CPUs altogether? For my understanding they were
used as wildcard CPUs for *-user. We could do the same by instantiating
a real CPU like "cortex-a15" and possibly enabling some additional
features afterwards.

Andreas

>>> Maybe we should use
>>> "cpu-<model>" as the namespace for the CPU model class names?
>>
>> Sounds reasonable.
>>
>> -- PMM
Peter Maydell Nov. 13, 2012, 12:17 p.m. UTC | #7
On 13 November 2012 11:51, Andreas Färber <afaerber@suse.de> wrote:
> Am 12.11.2012 23:33, schrieb Eduardo Habkost:
>> In that case, "cpu-any" wouldn't work, either. What about
>> "<arch>-cpu-<model>"?
>
> Fine with me. However, keep in mind the previous approach was used for
> command line compatibility: I would like to continue using -cpu
> cortex-a9 rather than -cpu arm-cpu-cortex-a9. :)

Yes, we need to maintain the command line names as-is.

> If we introduce a more complex command-line-to-class mapping, can't we
> drop these ominous "any" CPUs altogether? For my understanding they were
> used as wildcard CPUs for *-user. We could do the same by instantiating
> a real CPU like "cortex-a15" and possibly enabling some additional
> features afterwards.

I don't see what that gains us. The easiest way to say "it's
a cpu with all the feature bits turned on" is to define it as
a cpu with all the feature bits turned on :-)

-- PMM
Eduardo Habkost Nov. 13, 2012, 12:22 p.m. UTC | #8
On Tue, Nov 13, 2012 at 12:51:43PM +0100, Andreas Färber wrote:
> Am 12.11.2012 23:33, schrieb Eduardo Habkost:
> > On Mon, Nov 12, 2012 at 10:18:29PM +0000, Peter Maydell wrote:
> >> On 12 November 2012 22:16, Eduardo Habkost <ehabkost@redhat.com> wrote:
> >>> On Sat, Apr 14, 2012 at 05:42:10PM +0100, Peter Maydell wrote:
> >>>> +static const ARMCPUInfo arm_cpus[] = {
> >>> [...]
> >>>> +    { .name = "any",         .initfn = arm_any_initfn },
> >>>> +};
> >>>> +
> >>>
> >>> Do we really want to use "any" as the class name?
> >>
> >> Probably not, since it would make it tricky to (in some future
> >> utopia) have a QEMU which supported more than one CPU architecture
> >> in the same binary if they all wanted to use "any"...
> > 
> > In that case, "cpu-any" wouldn't work, either. What about
> > "<arch>-cpu-<model>"?
> 
> Fine with me. However, keep in mind the previous approach was used for
> command line compatibility: I would like to continue using -cpu
> cortex-a9 rather than -cpu arm-cpu-cortex-a9. :)

Me too. We need keep "-cpu SandyBridge" working, instead of requiring
"-cpu x86_64-cpu-SandyBridge".

"-cpu FOO" could first try a class named "<arch>-cpu-FOO" (for
compatibility), then fallback to "FOO".

> 
> If we introduce a more complex command-line-to-class mapping, can't we
> drop these ominous "any" CPUs altogether? For my understanding they were
> used as wildcard CPUs for *-user. We could do the same by instantiating
> a real CPU like "cortex-a15" and possibly enabling some additional
> features afterwards.

I didn't look so deeply at the code, to understand what "any" does, and
why it exists. But whatever we do, I suppose we need to keep "-cpu any"
working, for compatibility.

> 
> Andreas
> 
> >>> Maybe we should use
> >>> "cpu-<model>" as the namespace for the CPU model class names?
> >>
> >> Sounds reasonable.
> >>
> >> -- PMM
> 
> -- 
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Eduardo Habkost Nov. 13, 2012, 12:25 p.m. UTC | #9
On Tue, Nov 13, 2012 at 12:17:00PM +0000, Peter Maydell wrote:
> On 13 November 2012 11:51, Andreas Färber <afaerber@suse.de> wrote:
> > Am 12.11.2012 23:33, schrieb Eduardo Habkost:
> >> In that case, "cpu-any" wouldn't work, either. What about
> >> "<arch>-cpu-<model>"?
> >
> > Fine with me. However, keep in mind the previous approach was used for
> > command line compatibility: I would like to continue using -cpu
> > cortex-a9 rather than -cpu arm-cpu-cortex-a9. :)
> 
> Yes, we need to maintain the command line names as-is.

ACK.

> 
> > If we introduce a more complex command-line-to-class mapping, can't we
> > drop these ominous "any" CPUs altogether? For my understanding they were
> > used as wildcard CPUs for *-user. We could do the same by instantiating
> > a real CPU like "cortex-a15" and possibly enabling some additional
> > features afterwards.
> 
> I don't see what that gains us. The easiest way to say "it's
> a cpu with all the feature bits turned on" is to define it as
> a cpu with all the feature bits turned on :-)

This sounds similar to "-cpu host" on x86. The difference is that on x86
with KVM, we depend on host capabilities to know which features can be
enabled (so on x86 it's not "a cpu with all the feature bits turned on",
but "a cpu with all the feature bits _we can safely enable_ turned on").

> 
> -- PMM
diff mbox

Patch

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 42d2a6b..a4bcb31 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -58,6 +58,18 @@  typedef struct ARMCPU {
     /*< public >*/
 
     CPUARMState env;
+
+    /* The instance init functions for implementation-specific subclasses
+     * set these fields to specify the implementation-dependent values of
+     * various constant registers and reset values of non-constant
+     * registers.
+     * Some of these might become QOM properties eventually.
+     * Field names match the official register names as defined in the
+     * ARMv7AR ARM Architecture Reference Manual. A reset_ prefix
+     * is used for reset values of non-constant registers; no reset_
+     * prefix means a constant register.
+     */
+    uint32_t midr;
 } ARMCPU;
 
 static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index c3ed45b..3565472 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -34,6 +34,211 @@  static void arm_cpu_reset(CPUState *s)
     cpu_state_reset(&cpu->env);
 }
 
+static void arm_cpu_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu_exec_init(&cpu->env);
+}
+
+/* CPU models */
+
+static void arm926_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ARM926;
+}
+
+static void arm946_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ARM946;
+}
+
+static void arm1026_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ARM1026;
+}
+
+static void arm1136_r2_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ARM1136_R2;
+}
+
+static void arm1136_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ARM1136;
+}
+
+static void arm1176_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ARM1176;
+}
+
+static void arm11mpcore_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ARM11MPCORE;
+}
+
+static void cortex_m3_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_CORTEXM3;
+}
+
+static void cortex_a8_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_CORTEXA8;
+}
+
+static void cortex_a9_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_CORTEXA9;
+}
+
+static void cortex_a15_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_CORTEXA15;
+}
+
+static void ti925t_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_TI925T;
+}
+
+static void sa1100_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_SA1100;
+}
+
+static void sa1110_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_SA1110;
+}
+
+static void pxa250_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA250;
+}
+
+static void pxa255_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA255;
+}
+
+static void pxa260_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA260;
+}
+
+static void pxa261_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA261;
+}
+
+static void pxa262_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA262;
+}
+
+static void pxa270a0_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA270_A0;
+}
+
+static void pxa270a1_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA270_A1;
+}
+
+static void pxa270b0_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA270_B0;
+}
+
+static void pxa270b1_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA270_B1;
+}
+
+static void pxa270c0_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA270_C0;
+}
+
+static void pxa270c5_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_PXA270_C5;
+}
+
+static void arm_any_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->midr = ARM_CPUID_ANY;
+}
+
+typedef struct ARMCPUInfo {
+    const char *name;
+    void (*initfn)(Object *obj);
+} ARMCPUInfo;
+
+static const ARMCPUInfo arm_cpus[] = {
+    { .name = "arm926",      .initfn = arm926_initfn },
+    { .name = "arm946",      .initfn = arm946_initfn },
+    { .name = "arm1026",     .initfn = arm1026_initfn },
+    /* What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an
+     * older core than plain "arm1136". In particular this does not
+     * have the v6K features.
+     */
+    { .name = "arm1136-r2",  .initfn = arm1136_r2_initfn },
+    { .name = "arm1136",     .initfn = arm1136_initfn },
+    { .name = "arm1176",     .initfn = arm1176_initfn },
+    { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
+    { .name = "cortex-m3",   .initfn = cortex_m3_initfn },
+    { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
+    { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
+    { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
+    { .name = "ti925t",      .initfn = ti925t_initfn },
+    { .name = "sa1100",      .initfn = sa1100_initfn },
+    { .name = "sa1110",      .initfn = sa1110_initfn },
+    { .name = "pxa250",      .initfn = pxa250_initfn },
+    { .name = "pxa255",      .initfn = pxa255_initfn },
+    { .name = "pxa260",      .initfn = pxa260_initfn },
+    { .name = "pxa261",      .initfn = pxa261_initfn },
+    { .name = "pxa262",      .initfn = pxa262_initfn },
+    /* "pxa270" is a legacy alias for "pxa270-a0" */
+    { .name = "pxa270",      .initfn = pxa270a0_initfn },
+    { .name = "pxa270-a0",   .initfn = pxa270a0_initfn },
+    { .name = "pxa270-a1",   .initfn = pxa270a1_initfn },
+    { .name = "pxa270-b0",   .initfn = pxa270b0_initfn },
+    { .name = "pxa270-b1",   .initfn = pxa270b1_initfn },
+    { .name = "pxa270-c0",   .initfn = pxa270c0_initfn },
+    { .name = "pxa270-c5",   .initfn = pxa270c5_initfn },
+    { .name = "any",         .initfn = arm_any_initfn },
+};
+
 static void arm_cpu_class_init(ObjectClass *oc, void *data)
 {
     ARMCPUClass *acc = ARM_CPU_CLASS(oc);
@@ -43,18 +248,37 @@  static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = arm_cpu_reset;
 }
 
+static void cpu_register(const ARMCPUInfo *info)
+{
+    TypeInfo type_info = {
+        .name = info->name,
+        .parent = TYPE_ARM_CPU,
+        .instance_size = sizeof(ARMCPU),
+        .instance_init = info->initfn,
+        .class_size = sizeof(ARMCPUClass),
+    };
+
+    type_register_static(&type_info);
+}
+
 static const TypeInfo arm_cpu_type_info = {
     .name = TYPE_ARM_CPU,
     .parent = TYPE_CPU,
     .instance_size = sizeof(ARMCPU),
-    .abstract = false,
+    .instance_init = arm_cpu_initfn,
+    .abstract = true,
     .class_size = sizeof(ARMCPUClass),
     .class_init = arm_cpu_class_init,
 };
 
 static void arm_cpu_register_types(void)
 {
+    int i;
+
     type_register_static(&arm_cpu_type_info);
+    for (i = 0; i < ARRAY_SIZE(arm_cpus); i++) {
+        cpu_register(&arm_cpus[i]);
+    }
 }
 
 type_init(arm_cpu_register_types)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 28f127b..afcd68c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -46,8 +46,6 @@  static uint32_t arm1176_cp15_c0_c1[8] =
 static uint32_t arm1176_cp15_c0_c2[8] =
 { 0x0140011, 0x12002111, 0x11231121, 0x01102131, 0x01141, 0, 0, 0 };
 
-static uint32_t cpu_arm_find_by_name(const char *name);
-
 static inline void set_feature(CPUARMState *env, int feature)
 {
     env->features |= 1u << feature;
@@ -55,7 +53,6 @@  static inline void set_feature(CPUARMState *env, int feature)
 
 static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
 {
-    env->cp15.c0_cpuid = id;
     switch (id) {
     case ARM_CPUID_ARM926:
         set_feature(env, ARM_FEATURE_V5);
@@ -201,7 +198,6 @@  static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_TI925T:
         set_feature(env, ARM_FEATURE_V4T);
         set_feature(env, ARM_FEATURE_OMAPCP);
-        env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring.  */
         env->cp15.c0_cachetype = 0x5109149;
         env->cp15.c1_sys = 0x00000070;
         env->cp15.c15_i_max = 0x000;
@@ -287,18 +283,20 @@  void cpu_state_reset(CPUARMState *env)
 {
     uint32_t id;
     uint32_t tmp = 0;
+    ARMCPU *cpu = arm_env_get_cpu(env);
 
     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
         qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
         log_cpu_state(env, 0);
     }
 
-    id = env->cp15.c0_cpuid;
+    id = cpu->midr;
     tmp = env->cp15.c15_config_base_address;
     memset(env, 0, offsetof(CPUARMState, breakpoints));
     if (id)
         cpu_reset_model_id(env, id);
     env->cp15.c15_config_base_address = tmp;
+    env->cp15.c0_cpuid = cpu->midr;
 #if defined (CONFIG_USER_ONLY)
     env->uncached_cpsr = ARM_CPU_MODE_USR;
     /* For user mode we must enable access to coprocessors */
@@ -407,22 +405,20 @@  CPUARMState *cpu_arm_init(const char *cpu_model)
 {
     ARMCPU *cpu;
     CPUARMState *env;
-    uint32_t id;
     static int inited = 0;
 
-    id = cpu_arm_find_by_name(cpu_model);
-    if (id == 0)
+    if (!object_class_by_name(cpu_model)) {
         return NULL;
-    cpu = ARM_CPU(object_new(TYPE_ARM_CPU));
+    }
+    cpu = ARM_CPU(object_new(cpu_model));
     env = &cpu->env;
-    cpu_exec_init(env);
+    env->cpu_model_str = cpu_model;
+
     if (tcg_enabled() && !inited) {
         inited = 1;
         arm_translate_init();
     }
 
-    env->cpu_model_str = cpu_model;
-    env->cp15.c0_cpuid = id;
     cpu_state_reset(env);
     if (arm_feature(env, ARM_FEATURE_NEON)) {
         gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
@@ -438,66 +434,51 @@  CPUARMState *cpu_arm_init(const char *cpu_model)
     return env;
 }
 
-struct arm_cpu_t {
-    uint32_t id;
-    const char *name;
-};
-
-static const struct arm_cpu_t arm_cpu_names[] = {
-    { ARM_CPUID_ARM926, "arm926"},
-    { ARM_CPUID_ARM946, "arm946"},
-    { ARM_CPUID_ARM1026, "arm1026"},
-    { ARM_CPUID_ARM1136, "arm1136"},
-    { ARM_CPUID_ARM1136_R2, "arm1136-r2"},
-    { ARM_CPUID_ARM1176, "arm1176"},
-    { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
-    { ARM_CPUID_CORTEXM3, "cortex-m3"},
-    { ARM_CPUID_CORTEXA8, "cortex-a8"},
-    { ARM_CPUID_CORTEXA9, "cortex-a9"},
-    { ARM_CPUID_CORTEXA15, "cortex-a15" },
-    { ARM_CPUID_TI925T, "ti925t" },
-    { ARM_CPUID_PXA250, "pxa250" },
-    { ARM_CPUID_SA1100,    "sa1100" },
-    { ARM_CPUID_SA1110,    "sa1110" },
-    { ARM_CPUID_PXA255, "pxa255" },
-    { ARM_CPUID_PXA260, "pxa260" },
-    { ARM_CPUID_PXA261, "pxa261" },
-    { ARM_CPUID_PXA262, "pxa262" },
-    { ARM_CPUID_PXA270, "pxa270" },
-    { ARM_CPUID_PXA270_A0, "pxa270-a0" },
-    { ARM_CPUID_PXA270_A1, "pxa270-a1" },
-    { ARM_CPUID_PXA270_B0, "pxa270-b0" },
-    { ARM_CPUID_PXA270_B1, "pxa270-b1" },
-    { ARM_CPUID_PXA270_C0, "pxa270-c0" },
-    { ARM_CPUID_PXA270_C5, "pxa270-c5" },
-    { ARM_CPUID_ANY, "any"},
-    { 0, NULL}
-};
+typedef struct ARMCPUListState {
+    fprintf_function cpu_fprintf;
+    FILE *file;
+} ARMCPUListState;
 
-void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+/* Sort alphabetically by type name, except for "any". */
+static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
 {
-    int i;
+    ObjectClass *class_a = (ObjectClass *)a;
+    ObjectClass *class_b = (ObjectClass *)b;
+    const char *name_a, *name_b;
 
-    (*cpu_fprintf)(f, "Available CPUs:\n");
-    for (i = 0; arm_cpu_names[i].name; i++) {
-        (*cpu_fprintf)(f, "  %s\n", arm_cpu_names[i].name);
+    name_a = object_class_get_name(class_a);
+    name_b = object_class_get_name(class_b);
+    if (strcmp(name_a, "any") == 0) {
+        return 1;
+    } else if (strcmp(name_b, "any") == 0) {
+        return -1;
+    } else {
+        return strcmp(name_a, name_b);
     }
 }
 
-/* return 0 if not found */
-static uint32_t cpu_arm_find_by_name(const char *name)
+static void arm_cpu_list_entry(gpointer data, gpointer user_data)
 {
-    int i;
-    uint32_t id;
+    ObjectClass *oc = data;
+    ARMCPUListState *s = user_data;
 
-    id = 0;
-    for (i = 0; arm_cpu_names[i].name; i++) {
-        if (strcmp(name, arm_cpu_names[i].name) == 0) {
-            id = arm_cpu_names[i].id;
-            break;
-        }
-    }
-    return id;
+    (*s->cpu_fprintf)(s->file, "  %s\n",
+                      object_class_get_name(oc));
+}
+
+void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    ARMCPUListState s = {
+        .file = f,
+        .cpu_fprintf = cpu_fprintf,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_ARM_CPU, false);
+    list = g_slist_sort(list, arm_cpu_list_compare);
+    (*cpu_fprintf)(f, "Available CPUs:\n");
+    g_slist_foreach(list, arm_cpu_list_entry, &s);
+    g_slist_free(list);
 }
 
 static int bad_mode_switch(CPUARMState *env, int mode)