@@ -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)
@@ -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
@@ -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)
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.henderson@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(-)