diff options
Diffstat (limited to 'target/arm/cpu.c')
-rw-r--r-- | target/arm/cpu.c | 86 |
1 files changed, 67 insertions, 19 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 60411f6bfe..7e1f3dd637 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -162,6 +162,9 @@ static void arm_cpu_reset(CPUState *s) env->pstate = PSTATE_MODE_EL0t; /* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */ env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE; + /* Enable all PAC instructions */ + env->cp15.hcr_el2 |= HCR_API; + env->cp15.scr_el3 |= SCR_API; /* and to the FP/Neon instructions */ env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3); /* and to the SVE instructions */ @@ -642,6 +645,20 @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz) return (Aff1 << ARM_AFF1_SHIFT) | Aff0; } +static void cpreg_hashtable_data_destroy(gpointer data) +{ + /* + * Destroy function for cpu->cp_regs hashtable data entries. + * We must free the name string because it was g_strdup()ed in + * add_cpreg_to_hashtable(). It's OK to cast away the 'const' + * from r->name because we know we definitely allocated it. + */ + ARMCPRegInfo *r = data; + + g_free((void *)r->name); + g_free(r); +} + static void arm_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); @@ -649,7 +666,7 @@ static void arm_cpu_initfn(Object *obj) cs->env_ptr = &cpu->env; cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal, - g_free, g_free); + g_free, cpreg_hashtable_data_destroy); QLIST_INIT(&cpu->pre_el_change_hooks); QLIST_INIT(&cpu->el_change_hooks); @@ -665,14 +682,6 @@ static void arm_cpu_initfn(Object *obj) qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4); } - cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_ptimer_cb, cpu); - cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_vtimer_cb, cpu); - cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_htimer_cb, cpu); - cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, - arm_gt_stimer_cb, cpu); qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs, ARRAY_SIZE(cpu->gt_timer_outputs)); @@ -734,7 +743,7 @@ static Property arm_cpu_pmsav7_dregion_property = static Property arm_cpu_initsvtor_property = DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0); -static void arm_cpu_post_init(Object *obj) +void arm_cpu_post_init(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); @@ -868,6 +877,15 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) return; } } + + cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, + arm_gt_ptimer_cb, cpu); + cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, + arm_gt_vtimer_cb, cpu); + cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, + arm_gt_htimer_cb, cpu); + cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, + arm_gt_stimer_cb, cpu); #endif cpu_exec_realizefn(cs, &local_err); @@ -1019,7 +1037,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) if (!cpu->has_pmu) { unset_feature(env, ARM_FEATURE_PMU); + } + if (arm_feature(env, ARM_FEATURE_PMU)) { + cpu->pmceid0 = get_pmceid(&cpu->env, 0); + cpu->pmceid1 = get_pmceid(&cpu->env, 1); + + if (!kvm_enabled()) { + arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0); + arm_register_el_change_hook(cpu, &pmu_post_el_change, 0); + } + } else { cpu->id_aa64dfr0 &= ~0xf00; + cpu->pmceid0 = 0; + cpu->pmceid1 = 0; } if (!arm_feature(env, ARM_FEATURE_EL2)) { @@ -1442,8 +1472,10 @@ static void cortex_m33_initfn(Object *obj) static void arm_v7m_class_init(ObjectClass *oc, void *data) { + ARMCPUClass *acc = ARM_CPU_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); + acc->info = data; #ifndef CONFIG_USER_ONLY cc->do_interrupt = arm_v7m_cpu_do_interrupt; #endif @@ -1662,8 +1694,6 @@ static void cortex_a7_initfn(Object *obj) cpu->id_pfr0 = 0x00001131; cpu->id_pfr1 = 0x00011011; cpu->id_dfr0 = 0x02010555; - cpu->pmceid0 = 0x00000000; - cpu->pmceid1 = 0x00000000; cpu->id_afr0 = 0x00000000; cpu->id_mmfr0 = 0x10101105; cpu->id_mmfr1 = 0x40000000; @@ -1709,8 +1739,6 @@ static void cortex_a15_initfn(Object *obj) cpu->id_pfr0 = 0x00001131; cpu->id_pfr1 = 0x00011011; cpu->id_dfr0 = 0x02010555; - cpu->pmceid0 = 0x0000000; - cpu->pmceid1 = 0x00000000; cpu->id_afr0 = 0x00000000; cpu->id_mmfr0 = 0x10201105; cpu->id_mmfr1 = 0x20000000; @@ -1932,6 +1960,10 @@ static void arm_max_initfn(Object *obj) t = cpu->isar.id_isar6; t = FIELD_DP32(t, ID_ISAR6, DP, 1); cpu->isar.id_isar6 = t; + + t = cpu->id_mmfr4; + t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ + cpu->id_mmfr4 = t; } #endif } @@ -1940,11 +1972,11 @@ static void arm_max_initfn(Object *obj) #endif /* !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) */ -typedef struct ARMCPUInfo { +struct ARMCPUInfo { const char *name; void (*initfn)(Object *obj); void (*class_init)(ObjectClass *oc, void *data); -} ARMCPUInfo; +}; static const ARMCPUInfo arm_cpus[] = { #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) @@ -2094,6 +2126,7 @@ static void arm_host_initfn(Object *obj) ARMCPU *cpu = ARM_CPU(obj); kvm_arm_set_cpu_features_from_host(cpu); + arm_cpu_post_init(obj); } static const TypeInfo host_arm_cpu_type_info = { @@ -2108,14 +2141,30 @@ static const TypeInfo host_arm_cpu_type_info = { #endif +static void arm_cpu_instance_init(Object *obj) +{ + ARMCPUClass *acc = ARM_CPU_GET_CLASS(obj); + + acc->info->initfn(obj); + arm_cpu_post_init(obj); +} + +static void cpu_register_class_init(ObjectClass *oc, void *data) +{ + ARMCPUClass *acc = ARM_CPU_CLASS(oc); + + acc->info = data; +} + static void cpu_register(const ARMCPUInfo *info) { TypeInfo type_info = { .parent = TYPE_ARM_CPU, .instance_size = sizeof(ARMCPU), - .instance_init = info->initfn, + .instance_init = arm_cpu_instance_init, .class_size = sizeof(ARMCPUClass), - .class_init = info->class_init, + .class_init = info->class_init ?: cpu_register_class_init, + .class_data = (void *)info, }; type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name); @@ -2128,7 +2177,6 @@ static const TypeInfo arm_cpu_type_info = { .parent = TYPE_CPU, .instance_size = sizeof(ARMCPU), .instance_init = arm_cpu_initfn, - .instance_post_init = arm_cpu_post_init, .instance_finalize = arm_cpu_finalizefn, .abstract = true, .class_size = sizeof(ARMCPUClass), |