* [PATCH v3 1/5] target/arm: Implement RMR_ELx
2023-08-31 23:24 [PATCH v3 0/5] target/arm: Implement cortex-a710 Richard Henderson
@ 2023-08-31 23:24 ` Richard Henderson
2023-09-08 13:29 ` Peter Maydell
2023-08-31 23:24 ` [PATCH v3 2/5] target/arm: Implement cortex-a710 Richard Henderson
` (4 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2023-08-31 23:24 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Provide a stub implementation, as a write is a "request".
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 64 +++++++++++++++++++++++++++++----------------
1 file changed, 41 insertions(+), 23 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e3f5a7d2bd..654e7d06a8 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8682,16 +8682,25 @@ void register_cp_regs_for_features(ARMCPU *cpu)
};
modify_arm_cp_regs(v8_idregs, v8_user_idregs);
#endif
- /* RVBAR_EL1 is only implemented if EL1 is the highest EL */
+ /*
+ * RVBAR_EL1 and RMR_EL1 only implemented if EL1 is the highest EL.
+ * TODO: For RMR, a write with bit 1 set should do something with
+ * cpu_reset(). In the meantime, "the bit is strictly a request",
+ * so we are in spec just ignoring writes.
+ */
if (!arm_feature(env, ARM_FEATURE_EL3) &&
!arm_feature(env, ARM_FEATURE_EL2)) {
- ARMCPRegInfo rvbar = {
- .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
- .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
- .access = PL1_R,
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
+ ARMCPRegInfo el1_reset_regs[] = {
+ { .name = "RVBAR_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
+ .access = PL1_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
+ { .name = "RMR_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 2,
+ .access = PL1_RW, .type = ARM_CP_CONST,
+ .resetvalue = arm_feature(env, ARM_FEATURE_AARCH64) }
};
- define_one_arm_cp_reg(cpu, &rvbar);
+ define_arm_cp_regs(cpu, el1_reset_regs);
}
define_arm_cp_regs(cpu, v8_idregs);
define_arm_cp_regs(cpu, v8_cp_reginfo);
@@ -8775,22 +8784,25 @@ void register_cp_regs_for_features(ARMCPU *cpu)
if (cpu_isar_feature(aa64_sel2, cpu)) {
define_arm_cp_regs(cpu, el2_sec_cp_reginfo);
}
- /* RVBAR_EL2 is only implemented if EL2 is the highest EL */
+ /*
+ * RVBAR_EL2 and RMR_EL2 only implemented if EL2 is the highest EL.
+ * See commentary near RMR_EL1.
+ */
if (!arm_feature(env, ARM_FEATURE_EL3)) {
- ARMCPRegInfo rvbar[] = {
- {
- .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
- .access = PL2_R,
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
- },
- { .name = "RVBAR", .type = ARM_CP_ALIAS,
- .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
- .access = PL2_R,
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
- },
+ static const ARMCPRegInfo el2_reset_regs[] = {
+ { .name = "RVBAR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 1,
+ .access = PL2_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
+ { .name = "RVBAR", .type = ARM_CP_ALIAS,
+ .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 1,
+ .access = PL2_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar) },
+ { .name = "RMR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 2,
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 1 },
};
- define_arm_cp_regs(cpu, rvbar);
+ define_arm_cp_regs(cpu, el2_reset_regs);
}
}
@@ -8801,8 +8813,14 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .name = "RVBAR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 1,
.access = PL3_R,
- .fieldoffset = offsetof(CPUARMState, cp15.rvbar),
- },
+ .fieldoffset = offsetof(CPUARMState, cp15.rvbar), },
+ { .name = "RMR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 2,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 1 },
+ { .name = "RMR", .state = ARM_CP_STATE_AA32,
+ .cp = 15, .opc1 = 0, .crn = 12, .crm = 0, .opc2 = 2,
+ .access = PL3_RW, .type = ARM_CP_CONST,
+ .resetvalue = arm_feature(env, ARM_FEATURE_AARCH64) },
{ .name = "SCTLR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 0, .opc2 = 0,
.access = PL3_RW,
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 2/5] target/arm: Implement cortex-a710
2023-08-31 23:24 [PATCH v3 0/5] target/arm: Implement cortex-a710 Richard Henderson
2023-08-31 23:24 ` [PATCH v3 1/5] target/arm: Implement RMR_ELx Richard Henderson
@ 2023-08-31 23:24 ` Richard Henderson
2023-09-08 13:23 ` Peter Maydell
2023-08-31 23:24 ` [PATCH v3 3/5] target/arm: Implement HCR_EL2.TIDCP Richard Henderson
` (3 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2023-08-31 23:24 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
The cortex-a710 is a first generation ARMv9.0-A processor.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
docs/system/arm/virt.rst | 1 +
hw/arm/virt.c | 1 +
target/arm/tcg/cpu64.c | 212 +++++++++++++++++++++++++++++++++++++++
3 files changed, 214 insertions(+)
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
index 51cdac6841..e1697ac8f4 100644
--- a/docs/system/arm/virt.rst
+++ b/docs/system/arm/virt.rst
@@ -58,6 +58,7 @@ Supported guest CPU types:
- ``cortex-a57`` (64-bit)
- ``cortex-a72`` (64-bit)
- ``cortex-a76`` (64-bit)
+- ``cortex-a710`` (64-bit)
- ``a64fx`` (64-bit)
- ``host`` (with KVM only)
- ``neoverse-n1`` (64-bit)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a13c658bbf..8ad78b23c2 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -211,6 +211,7 @@ static const char *valid_cpus[] = {
ARM_CPU_TYPE_NAME("cortex-a55"),
ARM_CPU_TYPE_NAME("cortex-a72"),
ARM_CPU_TYPE_NAME("cortex-a76"),
+ ARM_CPU_TYPE_NAME("cortex-a710"),
ARM_CPU_TYPE_NAME("a64fx"),
ARM_CPU_TYPE_NAME("neoverse-n1"),
ARM_CPU_TYPE_NAME("neoverse-v1"),
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 0f8972950d..ab63526bea 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -745,6 +745,217 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
aarch64_add_sve_properties(obj);
}
+static const ARMCPRegInfo cortex_a710_cp_reginfo[] = {
+ { .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 0,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUACTLR2_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 1,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUACTLR3_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 2,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUACTLR4_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 3,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 4,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUECTLR2_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 5,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 4,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPWRCTLR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 7,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "ATCR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 7, .opc2 = 0,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUACTLR5_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 0,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUACTLR6_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 1,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "CPUACTLR7_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 15, .crm = 8, .opc2 = 2,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
+ .accessfn = access_actlr_w },
+ { .name = "ATCR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 0,
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "AVTCR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 1,
+ .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 0,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPPMCR2_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 1,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPPMCR4_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 4,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPPMCR5_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 5,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPPMCR6_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 6,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUACTLR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 4, .opc2 = 0,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "ATCR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 7, .opc2 = 0,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPSELR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 0,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPCR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 1,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPOR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 2,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPMR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 3,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPOR2_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 4,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPMR2_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 5,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "CPUPFR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 6,
+ .access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+
+ /*
+ * Stub RAMINDEX, as we don't actually implement caches, BTB,
+ * or anything else with cpu internal memory.
+ * "Read" zeros into the IDATA* and DDATA* output registers.
+ */
+ { .name = "RAMINDEX_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 0,
+ .access = PL3_W, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "IDATA0_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 0,
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "IDATA1_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 1,
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "IDATA2_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 0, .opc2 = 2,
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "DDATA0_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 1, .opc2 = 0,
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "DDATA1_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 1, .opc2 = 1,
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "DDATA2_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 15, .crm = 1, .opc2 = 2,
+ .access = PL3_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+};
+
+static void aarch64_a710_initfn(Object *obj)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ cpu->dtb_compatible = "arm,cortex-a710";
+ set_feature(&cpu->env, ARM_FEATURE_V8);
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
+ set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
+
+ /* Ordered by Section B.4: AArch64 registers */
+ cpu->midr = 0x412FD471; /* r2p1 */
+ cpu->revidr = 0;
+ cpu->isar.id_pfr0 = 0x21110131;
+ cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */
+ cpu->isar.id_dfr0 = 0x16011099;
+ cpu->id_afr0 = 0;
+ cpu->isar.id_mmfr0 = 0x10201105;
+ cpu->isar.id_mmfr1 = 0x40000000;
+ cpu->isar.id_mmfr2 = 0x01260000;
+ cpu->isar.id_mmfr3 = 0x02122211;
+ cpu->isar.id_isar0 = 0x02101110;
+ cpu->isar.id_isar1 = 0x13112111;
+ cpu->isar.id_isar2 = 0x21232042;
+ cpu->isar.id_isar3 = 0x01112131;
+ cpu->isar.id_isar4 = 0x00010142;
+ cpu->isar.id_isar5 = 0x11011121; /* with Crypto */
+ cpu->isar.id_mmfr4 = 0x21021110;
+ cpu->isar.id_isar6 = 0x01111111;
+ cpu->isar.mvfr0 = 0x10110222;
+ cpu->isar.mvfr1 = 0x13211111;
+ cpu->isar.mvfr2 = 0x00000043;
+ cpu->isar.id_pfr2 = 0x00000011;
+ cpu->isar.id_aa64pfr0 = 0x1201111120111112ull; /* GIC filled in later */
+ cpu->isar.id_aa64pfr1 = 0x0000000000000221ull;
+ cpu->isar.id_aa64zfr0 = 0x0000110100110021ull; /* with Crypto */
+ cpu->isar.id_aa64dfr0 = 0x000011f010305611ull;
+ cpu->isar.id_aa64dfr1 = 0;
+ cpu->id_aa64afr0 = 0;
+ cpu->id_aa64afr1 = 0;
+ cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */
+ cpu->isar.id_aa64isar1 = 0x0010111101211032ull;
+ cpu->isar.id_aa64mmfr0 = 0x0000022200101122ull;
+ cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull;
+ cpu->isar.id_aa64mmfr2 = 0x1221011110101011ull;
+ cpu->clidr = 0x0000001482000023ull;
+ cpu->gm_blocksize = 4;
+ cpu->ctr = 0x000000049444c004ull;
+ cpu->dcz_blocksize = 4;
+ /* TODO FEAT_MPAM: mpamidr_el1 = 0x0000_0001_0006_003f */
+
+ /* Section B.5.2: PMCR_EL0 */
+ cpu->isar.reset_pmcr_el0 = 0xa000; /* with 20 counters */
+
+ /* Section B.6.7: ICH_VTR_EL2 */
+ cpu->gic_num_lrs = 4;
+ cpu->gic_vpribits = 5;
+ cpu->gic_vprebits = 5;
+ cpu->gic_pribits = 5;
+
+ /* Section 14: Scalable Vector Extensions support */
+ cpu->sve_vq.supported = 1 << 0; /* 128bit */
+
+ /*
+ * The cortex-a710 TRM does not list CCSIDR values. The layout of
+ * the caches are in text in Table 7-1, Table 8-1, and Table 9-1.
+ *
+ * L1: 4-way set associative 64-byte line size, total either 32K or 64K.
+ * L2: 8-way set associative 64 byte line size, total either 256K or 512K.
+ */
+ cpu->ccsidr[0] = make_ccsidr64(4, 64, 64 * KiB); /* L1 dcache */
+ cpu->ccsidr[1] = cpu->ccsidr[0]; /* L1 icache */
+ cpu->ccsidr[2] = make_ccsidr64(8, 64, 512 * KiB); /* L2 cache */
+
+ /* FIXME: Not documented -- copied from neoverse-v1 */
+ cpu->reset_sctlr = 0x30c50838;
+
+ define_arm_cp_regs(cpu, cortex_a710_cp_reginfo);
+
+ aarch64_add_pauth_properties(obj);
+ aarch64_add_sve_properties(obj);
+}
+
/*
* -cpu max: a CPU with as many features enabled as our emulation supports.
* The version of '-cpu max' for qemu-system-arm is defined in cpu32.c;
@@ -934,6 +1145,7 @@ 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 = "cortex-a710", .initfn = aarch64_a710_initfn },
{ .name = "a64fx", .initfn = aarch64_a64fx_initfn },
{ .name = "neoverse-n1", .initfn = aarch64_neoverse_n1_initfn },
{ .name = "neoverse-v1", .initfn = aarch64_neoverse_v1_initfn },
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 3/5] target/arm: Implement HCR_EL2.TIDCP
2023-08-31 23:24 [PATCH v3 0/5] target/arm: Implement cortex-a710 Richard Henderson
2023-08-31 23:24 ` [PATCH v3 1/5] target/arm: Implement RMR_ELx Richard Henderson
2023-08-31 23:24 ` [PATCH v3 2/5] target/arm: Implement cortex-a710 Richard Henderson
@ 2023-08-31 23:24 ` Richard Henderson
2023-09-08 13:27 ` Peter Maydell
2023-08-31 23:24 ` [PATCH v3 4/5] target/arm: Implement FEAT_TIDCP1 Richard Henderson
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2023-08-31 23:24 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Perform the check for EL2 enabled in the security space and the
TIDCP bit in an out-of-line helper.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.h | 1 +
target/arm/tcg/op_helper.c | 13 +++++++++++++
target/arm/tcg/translate-a64.c | 16 ++++++++++++++--
target/arm/tcg/translate.c | 27 +++++++++++++++++++++++++++
4 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 95e32a697a..cf5c55a12b 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -81,6 +81,7 @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
+DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
DEF_HELPER_2(get_cp_reg, i32, env, cptr)
DEF_HELPER_3(set_cp_reg64, void, env, cptr, i64)
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index 3baf8004f6..9014c3ca46 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -764,6 +764,19 @@ const void *HELPER(lookup_cp_reg)(CPUARMState *env, uint32_t key)
return ri;
}
+/*
+ * Test for HCR_EL2.TIDCP at EL1.
+ * Since implementation defined registers are rare, and within QEMU
+ * most of them are no-op, do not waste HFLAGS space for this and
+ * always use a helper.
+ */
+void HELPER(tidcp_el1)(CPUARMState *env, uint32_t syndrome)
+{
+ if (arm_hcr_el2_eff(env) & HCR_TIDCP) {
+ raise_exception_ra(env, EXCP_UDEF, syndrome, 2, GETPC());
+ }
+}
+
void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
{
const ARMCPRegInfo *ri = rip;
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 0b77c92437..786a568d31 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2154,6 +2154,20 @@ static void handle_sys(DisasContext *s, bool isread,
bool need_exit_tb = false;
TCGv_ptr tcg_ri = NULL;
TCGv_i64 tcg_rt;
+ uint32_t syndrome;
+
+ if (crn == 11 || crn == 15) {
+ /*
+ * Check for TIDCP trap, which must take precedence over
+ * the UNDEF for "no such register" etc.
+ */
+ syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
+ switch (s->current_el) {
+ case 1:
+ gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
+ break;
+ }
+ }
if (!ri) {
/* Unknown register; this might be a guest error or a QEMU
@@ -2176,8 +2190,6 @@ static void handle_sys(DisasContext *s, bool isread,
/* Emit code to perform further access permissions checks at
* runtime; this may result in an exception.
*/
- uint32_t syndrome;
-
syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
gen_a64_update_pc(s, 0);
tcg_ri = tcg_temp_new_ptr();
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index 38ad8dd4bd..47d3bc5fd5 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -4538,6 +4538,20 @@ void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
}
+static bool aa32_cpreg_encoding_in_impdef_space(uint8_t crn, uint8_t crm)
+{
+ static const uint16_t mask[3] = {
+ 0b0000000111100111, /* crn == 9, crm == {c0-c2, c5-c8} */
+ 0b0000000100010011, /* crn == 10, crm == {c0, c1, c4, c8} */
+ 0b1000000111111111, /* crn == 11, crm == {c0-c8, c15} */
+ };
+
+ if (crn >= 9 && crn <= 11) {
+ return (mask[crn - 9] >> crm) & 1;
+ }
+ return false;
+}
+
static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
int opc1, int crn, int crm, int opc2,
bool isread, int rt, int rt2)
@@ -4619,6 +4633,19 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
}
}
+ if (cpnum == 15 && aa32_cpreg_encoding_in_impdef_space(crn, crm)) {
+ /*
+ * Check for TIDCP trap, which must take precedence over the UNDEF
+ * for "no such register" etc. It shares precedence with HSTR,
+ * but raises the same exception, so order doesn't matter.
+ */
+ switch (s->current_el) {
+ case 1:
+ gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
+ break;
+ }
+ }
+
if (!ri) {
/*
* Unknown register; this might be a guest error or a QEMU
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 4/5] target/arm: Implement FEAT_TIDCP1
2023-08-31 23:24 [PATCH v3 0/5] target/arm: Implement cortex-a710 Richard Henderson
` (2 preceding siblings ...)
2023-08-31 23:24 ` [PATCH v3 3/5] target/arm: Implement HCR_EL2.TIDCP Richard Henderson
@ 2023-08-31 23:24 ` Richard Henderson
2023-09-08 13:42 ` Peter Maydell
2023-08-31 23:24 ` [PATCH v3 5/5] target/arm: Enable SCTLR_EL1.TIDCP for user-only Richard Henderson
2023-09-08 13:43 ` [PATCH v3 0/5] target/arm: Implement cortex-a710 Peter Maydell
5 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2023-08-31 23:24 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
docs/system/arm/emulation.rst | 1 +
target/arm/cpu.h | 5 +++++
target/arm/helper.h | 1 +
target/arm/tcg/cpu64.c | 1 +
target/arm/tcg/op_helper.c | 20 ++++++++++++++++++++
target/arm/tcg/translate-a64.c | 5 +++++
target/arm/tcg/translate.c | 6 ++++++
7 files changed, 39 insertions(+)
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 2e6a7c8961..ce81fd82fc 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -85,6 +85,7 @@ the following architecture extensions:
- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
- FEAT_SPECRES (Speculation restriction instructions)
- FEAT_SSBS (Speculative Store Bypass Safe)
+- FEAT_TIDCP1 (EL0 use of IMPLEMENTATION DEFINED functionality)
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
- FEAT_TLBIRANGE (TLB invalidate range instructions)
- FEAT_TTCNP (Translation table Common not private translations)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 278cc135c2..c4ce1b915f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3947,6 +3947,11 @@ static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
}
+static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0;
+}
+
static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
diff --git a/target/arm/helper.h b/target/arm/helper.h
index cf5c55a12b..2b02733305 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -81,6 +81,7 @@ DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_4(access_check_cp_reg, cptr, env, i32, i32, i32)
DEF_HELPER_FLAGS_2(lookup_cp_reg, TCG_CALL_NO_RWG_SE, cptr, env, i32)
+DEF_HELPER_FLAGS_2(tidcp_el0, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_FLAGS_2(tidcp_el1, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_3(set_cp_reg, void, env, cptr, i32)
DEF_HELPER_2(get_cp_reg, i32, env, cptr)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index ab63526bea..b9691f24f8 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1069,6 +1069,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
+ t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */
cpu->isar.id_aa64mmfr1 = t;
t = cpu->isar.id_aa64mmfr2;
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index 9014c3ca46..403f8b09d3 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -777,6 +777,26 @@ void HELPER(tidcp_el1)(CPUARMState *env, uint32_t syndrome)
}
}
+/*
+ * Similarly, for FEAT_TIDCP1 at EL0.
+ * We have already checked for the presence of the feature.
+ */
+void HELPER(tidcp_el0)(CPUARMState *env, uint32_t syndrome)
+{
+ /* See arm_sctlr(), but we also need the sctlr el. */
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
+ int target_el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
+
+ /*
+ * The bit is not valid unless the target el is aa64, but since the
+ * bit test is simpler perform that first and check validity after.
+ */
+ if ((env->cp15.sctlr_el[target_el] & SCTLR_TIDCP)
+ && arm_el_is_aa64(env, target_el)) {
+ raise_exception_ra(env, EXCP_UDEF, syndrome, target_el, GETPC());
+ }
+}
+
void HELPER(set_cp_reg)(CPUARMState *env, const void *rip, uint32_t value)
{
const ARMCPRegInfo *ri = rip;
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 786a568d31..15d985d95e 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2163,6 +2163,11 @@ static void handle_sys(DisasContext *s, bool isread,
*/
syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
switch (s->current_el) {
+ case 0:
+ if (dc_isar_feature(aa64_tidcp1, s)) {
+ gen_helper_tidcp_el0(cpu_env, tcg_constant_i32(syndrome));
+ }
+ break;
case 1:
gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
break;
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index 47d3bc5fd5..976b704200 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -4640,6 +4640,12 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
* but raises the same exception, so order doesn't matter.
*/
switch (s->current_el) {
+ case 0:
+ if (arm_dc_feature(s, ARM_FEATURE_AARCH64)
+ && dc_isar_feature(aa64_tidcp1, s)) {
+ gen_helper_tidcp_el0(cpu_env, tcg_constant_i32(syndrome));
+ }
+ break;
case 1:
gen_helper_tidcp_el1(cpu_env, tcg_constant_i32(syndrome));
break;
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread