| /* |
| * QEMU ARM CPU |
| * |
| * Copyright (c) 2012 SUSE LINUX Products GmbH |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, see |
| * <http://www.gnu.org/licenses/gpl-2.0.html> |
| */ |
| |
| #include "cpu-qom.h" |
| #include "qemu-common.h" |
| |
| /* CPUClass::reset() */ |
| static void arm_cpu_reset(CPUState *s) |
| { |
| ARMCPU *cpu = ARM_CPU(s); |
| ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu); |
| |
| acc->parent_reset(s); |
| |
| /* TODO Inline the current contents of cpu_state_reset(), |
| once cpu_reset_model_id() is eliminated. */ |
| 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 an 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); |
| CPUClass *cc = CPU_CLASS(acc); |
| |
| acc->parent_reset = cc->reset; |
| 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), |
| .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) |