Create a block of cpregs in ARMCPUClass and copy to the instance in arm_cpu_init. Settings of these values will come in a future patch.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/arm/cpu-qom.h | 98 ++++++++++++++++++++++++++++++++++++++++++++ target/arm/cpu.h | 43 ++----------------- target/arm/cpu.c | 28 ++++++++++++- 3 files changed, 128 insertions(+), 41 deletions(-) diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h index ac58cc3a87..832b2cccf9 100644 --- a/target/arm/cpu-qom.h +++ b/target/arm/cpu-qom.h @@ -56,6 +56,45 @@ static inline void aarch64_cpu_register(const ARMCPUInfo *info) arm_cpu_register_parent(info, TYPE_AARCH64_CPU); } +typedef struct ARMISARegisters { + uint32_t id_isar0; + uint32_t id_isar1; + uint32_t id_isar2; + uint32_t id_isar3; + uint32_t id_isar4; + uint32_t id_isar5; + uint32_t id_isar6; + uint32_t id_mmfr0; + uint32_t id_mmfr1; + uint32_t id_mmfr2; + uint32_t id_mmfr3; + uint32_t id_mmfr4; + uint32_t id_mmfr5; + uint32_t id_pfr0; + uint32_t id_pfr1; + uint32_t id_pfr2; + uint32_t mvfr0; + uint32_t mvfr1; + uint32_t mvfr2; + uint32_t id_dfr0; + uint32_t id_dfr1; + uint32_t dbgdidr; + uint32_t dbgdevid; + uint32_t dbgdevid1; + uint64_t id_aa64isar0; + uint64_t id_aa64isar1; + uint64_t id_aa64pfr0; + uint64_t id_aa64pfr1; + uint64_t id_aa64mmfr0; + uint64_t id_aa64mmfr1; + uint64_t id_aa64mmfr2; + uint64_t id_aa64dfr0; + uint64_t id_aa64dfr1; + uint64_t id_aa64zfr0; + uint64_t id_aa64smfr0; + uint64_t reset_pmcr_el0; +} ARMISARegisters; + /** * ARMCPUClass: * @parent_realize: The parent class' realize handler. @@ -77,6 +116,65 @@ struct ARMCPUClass { /* Internal CPU feature flags. */ uint64_t features; + + /* + * 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. + * Some of these registers are split out into a substructure that + * is shared with the translators to control the ISA. + * + * Note that if you add an ID register to the ARMISARegisters struct + * you need to also update the 32-bit and 64-bit versions of the + * kvm_arm_get_host_cpu_features() function to correctly populate the + * field by reading the value from the KVM vCPU. + */ + ARMISARegisters isar; + + uint64_t midr; + uint64_t ctr; + uint64_t pmceid0; + uint64_t pmceid1; + uint64_t id_aa64afr0; + uint64_t id_aa64afr1; + uint64_t clidr; + /* + * The elements of this array are the CCSIDR values for each cache, + * in the order L1DCache, L1ICache, L2DCache, L2ICache, etc. + */ + uint64_t ccsidr[16]; + + uint32_t revidr; + uint32_t id_afr0; + uint32_t reset_fpsid; + uint32_t reset_sctlr; + uint32_t reset_auxcr; + + /* PMSAv7 MPU number of supported regions */ + uint32_t pmsav7_dregion; + /* v8M SAU number of supported regions */ + uint32_t sau_sregion; + + /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */ + uint32_t dcz_blocksize; + + /* Configurable aspects of GIC cpu interface (which is part of the CPU) */ + int gic_num_lrs; /* number of list registers */ + int gic_vpribits; /* number of virtual priority bits */ + int gic_vprebits; /* number of virtual preemption bits */ + int gic_pribits; /* number of physical priority bits */ + + /* + * [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or + * QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type. + */ + uint32_t kvm_target; }; static inline int arm_class_feature(ARMCPUClass *acc, int feature) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 3ac650092f..2d9bddf197 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -799,8 +799,6 @@ typedef enum ARMPSCIState { PSCI_ON_PENDING = 2 } ARMPSCIState; -typedef struct ARMISARegisters ARMISARegisters; - /* * In map, each set bit is a supported vector length of (bit-number + 1) * 16 * bytes, i.e. each bit number + 1 is the vector length in quadwords. @@ -967,44 +965,7 @@ struct ArchCPU { * kvm_arm_get_host_cpu_features() function to correctly populate the * field by reading the value from the KVM vCPU. */ - struct ARMISARegisters { - uint32_t id_isar0; - uint32_t id_isar1; - uint32_t id_isar2; - uint32_t id_isar3; - uint32_t id_isar4; - uint32_t id_isar5; - uint32_t id_isar6; - uint32_t id_mmfr0; - uint32_t id_mmfr1; - uint32_t id_mmfr2; - uint32_t id_mmfr3; - uint32_t id_mmfr4; - uint32_t id_mmfr5; - uint32_t id_pfr0; - uint32_t id_pfr1; - uint32_t id_pfr2; - uint32_t mvfr0; - uint32_t mvfr1; - uint32_t mvfr2; - uint32_t id_dfr0; - uint32_t id_dfr1; - uint32_t dbgdidr; - uint32_t dbgdevid; - uint32_t dbgdevid1; - uint64_t id_aa64isar0; - uint64_t id_aa64isar1; - uint64_t id_aa64pfr0; - uint64_t id_aa64pfr1; - uint64_t id_aa64mmfr0; - uint64_t id_aa64mmfr1; - uint64_t id_aa64mmfr2; - uint64_t id_aa64dfr0; - uint64_t id_aa64dfr1; - uint64_t id_aa64zfr0; - uint64_t id_aa64smfr0; - uint64_t reset_pmcr_el0; - } isar; + ARMISARegisters isar; uint64_t midr; uint32_t revidr; uint32_t reset_fpsid; @@ -4346,5 +4307,7 @@ static inline bool isar_feature_any_evt(const ARMISARegisters *id) */ #define cpu_isar_feature(name, cpu) \ ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); }) +#define class_isar_feature(name, acc) \ + ({ ARMCPUClass *acc_ = (acc); isar_feature_##name(&acc_->isar); }) #endif diff --git a/target/arm/cpu.c b/target/arm/cpu.c index d64b86b6a5..8463c45d87 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1192,6 +1192,32 @@ static void arm_cpu_initfn(Object *obj) cpu->dtb_compatible = acc->dtb_compatible; cpu->env.features = acc->features; + cpu->isar = acc->isar; + + cpu->midr = acc->midr; + cpu->ctr = acc->ctr; + cpu->pmceid0 = acc->pmceid0; + cpu->pmceid1 = acc->pmceid1; + cpu->id_aa64afr0 = acc->id_aa64afr0; + cpu->id_aa64afr1 = acc->id_aa64afr1; + cpu->clidr = acc->clidr; + + QEMU_BUILD_BUG_ON(sizeof(cpu->ccsidr) != sizeof(acc->ccsidr)); + memcpy(cpu->ccsidr, acc->ccsidr, sizeof(acc->ccsidr)); + + cpu->revidr = acc->revidr; + cpu->id_afr0 = acc->id_afr0; + cpu->reset_fpsid = acc->reset_fpsid; + cpu->reset_sctlr = acc->reset_sctlr; + cpu->reset_auxcr = acc->reset_auxcr; + cpu->pmsav7_dregion = acc->pmsav7_dregion; + cpu->sau_sregion = acc->sau_sregion; + cpu->dcz_blocksize = acc->dcz_blocksize; + cpu->gic_num_lrs = acc->gic_num_lrs; + cpu->gic_vpribits = acc->gic_vpribits; + cpu->gic_vprebits = acc->gic_vprebits; + cpu->gic_pribits = acc->gic_pribits; + cpu->kvm_target = acc->kvm_target; #ifdef CONFIG_USER_ONLY # ifdef TARGET_AARCH64 @@ -1225,7 +1251,6 @@ static void arm_cpu_initfn(Object *obj) #endif cpu->psci_version = QEMU_PSCI_VERSION_0_1; /* By default assume PSCI v0.1 */ - cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; if (tcg_enabled() || hvf_enabled()) { /* TCG and HVF implement PSCI 1.1 */ @@ -2249,6 +2274,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) * picky DTB consumer will also provide a helpful error message. */ acc->dtb_compatible = "qemu,unknown"; + acc->kvm_target = QEMU_KVM_ARM_TARGET_NONE; } static void arm_cpu_leaf_class_init(ObjectClass *oc, void *data) -- 2.34.1