@@ -988,6 +988,8 @@ struct ArchCPU {
uint32_t mvfr2;
uint32_t id_dfr0;
uint32_t dbgdidr;
+ uint32_t dbgdevid;
+ uint32_t dbgdevid1;
uint64_t id_aa64isar0;
uint64_t id_aa64isar1;
uint64_t id_aa64pfr0;
@@ -3719,6 +3721,11 @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
}
+static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5;
+}
+
static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
{
return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
@@ -79,6 +79,8 @@ static void aarch64_a57_initfn(Object *obj)
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001124;
cpu->isar.dbgdidr = 0x3516d000;
+ cpu->isar.dbgdevid = 0x01110f13;
+ cpu->isar.dbgdevid1 = 0x2;
cpu->isar.reset_pmcr_el0 = 0x41013000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
@@ -134,6 +136,8 @@ static void aarch64_a53_initfn(Object *obj)
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
cpu->isar.dbgdidr = 0x3516d000;
+ cpu->isar.dbgdevid = 0x00110f13;
+ cpu->isar.dbgdevid1 = 0x1;
cpu->isar.reset_pmcr_el0 = 0x41033000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
@@ -187,6 +191,8 @@ static void aarch64_a72_initfn(Object *obj)
cpu->isar.id_aa64isar0 = 0x00011120;
cpu->isar.id_aa64mmfr0 = 0x00001124;
cpu->isar.dbgdidr = 0x3516d000;
+ cpu->isar.dbgdevid = 0x01110f13;
+ cpu->isar.dbgdevid1 = 0x2;
cpu->isar.reset_pmcr_el0 = 0x41023000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
@@ -563,6 +563,8 @@ static void cortex_a7_initfn(Object *obj)
cpu->isar.id_isar3 = 0x11112131;
cpu->isar.id_isar4 = 0x10011142;
cpu->isar.dbgdidr = 0x3515f005;
+ cpu->isar.dbgdevid = 0x01110f13;
+ cpu->isar.dbgdevid1 = 0x1;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
@@ -606,6 +608,8 @@ static void cortex_a15_initfn(Object *obj)
cpu->isar.id_isar3 = 0x11112131;
cpu->isar.id_isar4 = 0x10011142;
cpu->isar.dbgdidr = 0x3515f021;
+ cpu->isar.dbgdevid = 0x01110f13;
+ cpu->isar.dbgdevid1 = 0x0;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
@@ -1098,6 +1102,8 @@ static void arm_max_initfn(Object *obj)
cpu->isar.id_isar5 = 0x00011121;
cpu->isar.id_isar6 = 0;
cpu->isar.dbgdidr = 0x3516d000;
+ cpu->isar.dbgdevid = 0x00110f13;
+ cpu->isar.dbgdevid1 = 0x2;
cpu->isar.reset_pmcr_el0 = 0x41013000;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
@@ -999,6 +999,42 @@ void define_debug_regs(ARMCPU *cpu)
define_one_arm_cp_reg(cpu, &dbgdidr);
}
+ /*
+ * DBGDEVID is present in the v7 debug architecture if
+ * DBGDIDR.DEVID_imp is 1 (bit 15); from v7.1 and on it is
+ * mandatory (and bit 15 is RES1). DBGDEVID1 and DBGDEVID2 exist
+ * from v7.1 of the debug architecture. Because no fields have yet
+ * been defined in DBGDEVID2 (and quite possibly none will ever
+ * be) we don't define an ARMISARegisters field for it.
+ * These registers exist only if EL1 can use AArch32, but that
+ * happens naturally because they are only PL1 accessible anyway.
+ */
+ if (extract32(cpu->isar.dbgdidr, 15, 1)) {
+ ARMCPRegInfo dbgdevid = {
+ .name = "DBGDEVID",
+ .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 2, .crn = 7,
+ .access = PL1_R, .accessfn = access_tda,
+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid,
+ };
+ define_one_arm_cp_reg(cpu, &dbgdevid);
+ }
+ if (cpu_isar_feature(aa32_debugv7p1, cpu)) {
+ ARMCPRegInfo dbgdevid12[] = {
+ {
+ .name = "DBGDEVID1",
+ .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 1, .crn = 7,
+ .access = PL1_R, .accessfn = access_tda,
+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid1,
+ }, {
+ .name = "DBGDEVID2",
+ .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 0, .crn = 7,
+ .access = PL1_R, .accessfn = access_tda,
+ .type = ARM_CP_CONST, .resetvalue = 0,
+ },
+ };
+ define_arm_cp_regs(cpu, dbgdevid12);
+ }
+
brps = arm_num_brps(cpu);
wrps = arm_num_wrps(cpu);
ctx_cmps = arm_num_ctx_cmps(cpu);
Starting with v7 of the debug architecture, there are three extra ID registers that add information on top of that provided in DBGDIDR. These are DBGDEVID, DBGDEVID1 and DBGDEVID2. In the v7 debug architecture, DBGDEVID is optional, present only of DBGDIDR.DEVID_imp is set. In v7.1 all three must be present. Implement the missing registers. Note that we only need to set the values in the ARMISARegisters struct for the CPUs Cortex-A7, A15, A53, A57 and A72 (plus the 32-bit 'max' which uses the Cortex-A53 values): earlier CPUs didn't implement v7 of the architecture, and our other 64-bit CPUs (Cortex-A76, Neoverse-N1 and A64fx) don't have AArch32 support at EL1. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- Clearly no guest code users care about is trying to read these registers, or they'd have noticed the UNDEFs. But the AArch32 indicator that Feat_DoubleLock is present is in DBGDEVID, so I want it in ARMISARegisters so I can test against it. --- target/arm/cpu.h | 7 +++++++ target/arm/cpu64.c | 6 ++++++ target/arm/cpu_tcg.c | 6 ++++++ target/arm/debug_helper.c | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+)