The Phytium E2000Q combines two FTC310 cores and two FTC664 cores. Its EL3 firmware accesses implementation-defined system registers while setting up the cores. Using generic Cortex-A72 CPUs leaves these registers undefined and traps firmware before it can reach U-Boot.
Add FTC310 and FTC664 CPU types using Cortex-A72 as their common execution base. Provide conservative RAZ/WI and NOP stubs for the firmware-visible E2000 controls that have no modeled behavior. Set each CPU DT compatible string, MIDR, instruction feature fields, AArch32 floating-point feature fields, and CTR_EL0.L1Ip field to values observed on an E2000Q board. The FTC310 reports a VIPT instruction cache, while the FTC664 reports a PIPT instruction cache. Signed-off-by: Bin Meng <[email protected]> --- target/arm/tcg/cpu64.c | 81 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index affd87a3ae..0fd2f79bbc 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -336,6 +336,85 @@ static void aarch64_a72_initfn(Object *obj) define_cortex_a72_a57_a53_cp_reginfo(cpu); } +static const ARMCPRegInfo phytium_e2000_cp_reginfo[] = { + /* + * The E2000 EL3 firmware touches implementation-defined CPU registers + * during the PBF/BL1 cache and core setup. QEMU does not model these + * controls, so expose conservative RAZ/WI stubs for the boot firmware. + * + * PBF reads these identification and cluster controls after writing + * them. Returning zero preserves the reset state without claiming that + * QEMU implements the associated cache or coherency controls. + */ + { .name = "E2000_CPUID_CTL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 1, .crn = 15, .crm = 1, .opc2 = 0, + .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_NO_RAW, + .resetvalue = 0 }, + { .name = "E2000_CLUSTER_CTL", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 1, .crn = 11, .crm = 8, .opc2 = 6, + .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_NO_RAW, + .resetvalue = 0 }, + /* + * The remaining controls are only programmed as part of firmware setup. + * Accept the writes without retaining state because no modeled CPU + * behavior depends on their values. + */ + { .name = "E2000_EL1_CTL", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 2, .crn = 15, .crm = 15, .opc2 = 0, + .access = PL1_RW, .type = ARM_CP_NOP | ARM_CP_NO_RAW }, + { .name = "E2000_EL2_CTL", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 15, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_NOP | ARM_CP_NO_RAW }, + { .name = "E2000_EL2_CTL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 2, .opc2 = 4, + .access = PL2_RW, .type = ARM_CP_NOP | ARM_CP_NO_RAW }, + { .name = "E2000_EL3_CTL", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 15, .opc2 = 0, + .access = PL3_RW, .type = ARM_CP_NOP | ARM_CP_NO_RAW }, +}; + +/* + * Use the Cortex-A72 execution model as the common E2000 TCG base, then + * replace the architected identity fields that differ between the two + * physical core types. + */ +static void aarch64_phytium_e2000_base_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + aarch64_a72_initfn(obj); + define_arm_cp_regs(cpu, phytium_e2000_cp_reginfo); +} + +static void aarch64_phytium_ftc310_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; + + aarch64_phytium_e2000_base_initfn(obj); + + /* FTC310 cores identify with the FTC303 part number */ + cpu->dtb_compatible = "phytium,ftc310"; + cpu->midr = 0x700f3034; + SET_IDREG(isar, ID_AA64ISAR0, 0x00011100012120); + cpu->isar.mvfr0 = 0x10110222; + cpu->ctr = FIELD_DP64(cpu->ctr, CTR_EL0, L1IP, 2); /* VIPT */ +} + +static void aarch64_phytium_ftc664_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; + + aarch64_phytium_e2000_base_initfn(obj); + + cpu->dtb_compatible = "phytium,ftc664"; + cpu->midr = 0x701f6643; + SET_IDREG(isar, ID_AA64ISAR0, 0x00000100012120); + cpu->isar.mvfr0 = 0x10111222; + cpu->ctr = FIELD_DP64(cpu->ctr, CTR_EL0, L1IP, 3); /* PIPT */ +} + static void aarch64_a76_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); @@ -1533,6 +1612,8 @@ static const ARMCPUInfo aarch64_cpus[] = { { .name = "cortex-a55", .initfn = aarch64_a55_initfn }, { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, { .name = "cortex-a76", .initfn = aarch64_a76_initfn }, + { .name = "phytium-ftc310", .initfn = aarch64_phytium_ftc310_initfn }, + { .name = "phytium-ftc664", .initfn = aarch64_phytium_ftc664_initfn }, /* * The Cortex-A78AE differs slightly from the plain Cortex-A78. We don't * currently model the latter. -- 2.53.0
