diff options
-rw-r--r-- | target-arm/cpu-qom.h | 12 | ||||
-rw-r--r-- | target-arm/cpu.c | 82 | ||||
-rw-r--r-- | target-arm/helper.c | 75 |
3 files changed, 100 insertions, 69 deletions
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h index b2917ea935..9e33b6a2e3 100644 --- a/target-arm/cpu-qom.h +++ b/target-arm/cpu-qom.h @@ -21,6 +21,7 @@ #define QEMU_ARM_CPU_QOM_H #include "qemu/cpu.h" +#include "cpu.h" #define TYPE_ARM_CPU "arm-cpu" @@ -51,6 +52,7 @@ typedef struct ARMCPUClass { /** * ARMCPU: + * @env: Legacy CPU state. * * An ARM CPU core. */ @@ -58,7 +60,17 @@ typedef struct ARMCPU { /*< private >*/ CPUState parent_obj; /*< public >*/ + + /* TODO Inline this and split off common state */ + CPUARMState env; } ARMCPU; +static inline ARMCPU *arm_env_get_cpu(CPUARMState *env) +{ + return ARM_CPU(container_of(env, ARMCPU, env)); +} + +#define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e)) + #endif diff --git a/target-arm/cpu.c b/target-arm/cpu.c index dabc094835..00b7ecc836 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -20,12 +20,81 @@ #include "cpu-qom.h" #include "qemu-common.h" +#if !defined(CONFIG_USER_ONLY) +#include "hw/loader.h" +#endif static void arm_cpu_reset(CPUState *c) { ARMCPUClass *klass = ARM_CPU_GET_CLASS(c); + ARMCPU *cpu = ARM_CPU(c); + CPUARMState *env = &cpu->env; + uint32_t id; + uint32_t tmp; + + if (qemu_loglevel_mask(CPU_LOG_RESET)) { + qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); + log_cpu_state(env, 0); + } klass->parent_reset(c); + + id = env->cp15.c0_cpuid; + tmp = env->cp15.c15_config_base_address; + memset(env, 0, offsetof(CPUARMState, breakpoints)); + env->cp15.c0_cpuid = id; + env->cp15.c15_config_base_address = tmp; + +#if defined(CONFIG_USER_ONLY) + env->uncached_cpsr = ARM_CPU_MODE_USR; + /* For user mode we must enable access to coprocessors */ + env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30; + if (arm_feature(env, ARM_FEATURE_IWMMXT)) { + env->cp15.c15_cpar = 3; + } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { + env->cp15.c15_cpar = 1; + } +#else + /* SVC mode with interrupts disabled. */ + env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; + /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is + clear at reset. Initial SP and PC are loaded from ROM. */ + if (IS_M(env)) { + uint32_t pc; + uint8_t *rom; + env->uncached_cpsr &= ~CPSR_I; + rom = rom_ptr(0); + if (rom) { + /* We should really use ldl_phys here, in case the guest + modified flash and reset itself. However images + loaded via -kernel have not been copied yet, so load the + values directly from there. */ + env->regs[13] = ldl_p(rom); + pc = ldl_p(rom + 4); + env->thumb = pc & 1; + env->regs[15] = pc & ~1; + } + } + env->vfp.xregs[ARM_VFP_FPEXC] = 0; + env->cp15.c2_base_mask = 0xffffc000u; + /* v7 performance monitor control register: same implementor + * field as main ID register, and we implement no event counters. + */ + env->cp15.c9_pmcr = (id & 0xff000000); +#endif + set_flush_to_zero(1, &env->vfp.standard_fp_status); + set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); + set_default_nan_mode(1, &env->vfp.standard_fp_status); + set_float_detect_tininess(float_tininess_before_rounding, + &env->vfp.fp_status); + set_float_detect_tininess(float_tininess_before_rounding, + &env->vfp.standard_fp_status); + tlb_flush(env, 1); + /* Reset is a state change for some CPUState fields which we + * bake assumptions about into translated code, so we need to + * tb_flush(). + */ + tb_flush(env); } /* CPU models */ @@ -146,6 +215,18 @@ static const ARMCPUInfo arm_cpus[] = { }, }; +static void arm_cpu_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + ARMCPUClass *cpu_class = ARM_CPU_GET_CLASS(obj); + + memset(&cpu->env, 0, sizeof(CPUARMState)); + cpu_exec_init(&cpu->env); + + cpu->env.cpu_model_str = object_get_typename(obj); + cpu->env.cp15.c0_cpuid = cpu_class->cp15.c0_cpuid; +} + static void arm_cpu_class_init(ObjectClass *klass, void *data) { ARMCPUClass *k = ARM_CPU_CLASS(klass); @@ -164,6 +245,7 @@ static void cpu_register(const ARMCPUInfo *info) .name = info->name, .parent = TYPE_ARM_CPU, .instance_size = sizeof(ARMCPU), + .instance_init = arm_cpu_initfn, .class_size = sizeof(ARMCPUClass), .class_init = arm_cpu_class_init, .class_data = (void *)info, diff --git a/target-arm/helper.c b/target-arm/helper.c index 00e018cc46..c3b84978b8 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2,9 +2,6 @@ #include "gdbstub.h" #include "helper.h" #include "host-utils.h" -#if !defined(CONFIG_USER_ONLY) -#include "hw/loader.h" -#endif #include "sysemu.h" #include "cpu-qom.h" @@ -54,7 +51,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); @@ -280,69 +276,12 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) void cpu_state_reset(CPUARMState *env) { uint32_t id; - uint32_t tmp = 0; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", env->cpu_index); - log_cpu_state(env, 0); - } + cpu_reset(ENV_GET_CPU(env)); id = env->cp15.c0_cpuid; - 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; -#if defined (CONFIG_USER_ONLY) - env->uncached_cpsr = ARM_CPU_MODE_USR; - /* For user mode we must enable access to coprocessors */ - env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30; - if (arm_feature(env, ARM_FEATURE_IWMMXT)) { - env->cp15.c15_cpar = 3; - } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { - env->cp15.c15_cpar = 1; - } -#else - /* SVC mode with interrupts disabled. */ - env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I; - /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is - clear at reset. Initial SP and PC are loaded from ROM. */ - if (IS_M(env)) { - uint32_t pc; - uint8_t *rom; - env->uncached_cpsr &= ~CPSR_I; - rom = rom_ptr(0); - if (rom) { - /* We should really use ldl_phys here, in case the guest - modified flash and reset itself. However images - loaded via -kernel have not been copied yet, so load the - values directly from there. */ - env->regs[13] = ldl_p(rom); - pc = ldl_p(rom + 4); - env->thumb = pc & 1; - env->regs[15] = pc & ~1; - } - } - env->vfp.xregs[ARM_VFP_FPEXC] = 0; - env->cp15.c2_base_mask = 0xffffc000u; - /* v7 performance monitor control register: same implementor - * field as main ID register, and we implement no event counters. - */ - env->cp15.c9_pmcr = (id & 0xff000000); -#endif - set_flush_to_zero(1, &env->vfp.standard_fp_status); - set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); - set_default_nan_mode(1, &env->vfp.standard_fp_status); - set_float_detect_tininess(float_tininess_before_rounding, - &env->vfp.fp_status); - set_float_detect_tininess(float_tininess_before_rounding, - &env->vfp.standard_fp_status); - tlb_flush(env, 1); - /* Reset is a state change for some CPUARMState fields which we - * bake assumptions about into translated code, so we need to - * tb_flush(). - */ - tb_flush(env); } static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg) @@ -400,7 +339,7 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) CPUARMState *cpu_arm_init(const char *cpu_model) { ObjectClass *klass; - ARMCPUClass *cpu_class; + ARMCPU *cpu; CPUARMState *env; static int inited = 0; @@ -413,16 +352,14 @@ CPUARMState *cpu_arm_init(const char *cpu_model) if (klass == NULL) { return NULL; } - cpu_class = ARM_CPU_CLASS(klass); - env = g_malloc0(sizeof(CPUARMState)); - cpu_exec_init(env); + cpu = ARM_CPU(object_new(cpu_model)); + env = &cpu->env; + if (tcg_enabled() && !inited) { inited = 1; arm_translate_init(); } - env->cpu_model_str = cpu_model; - env->cp15.c0_cpuid = cpu_class->cp15.c0_cpuid; cpu_state_reset(env); if (arm_feature(env, ARM_FEATURE_NEON)) { gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg, @@ -487,7 +424,7 @@ void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf) void cpu_arm_close(CPUARMState *env) { - g_free(env); + object_delete(OBJECT(ENV_GET_CPU(env))); } static int bad_mode_switch(CPUARMState *env, int mode) |