For SME2, we need to expose the new ZT0 register in the gdbstub XML. gdb documents that the requirements are:
> The ‘org.gnu.gdb.aarch64.sme2’ feature is optional. If present, > then the ‘org.gnu.gdb.aarch64.sme’ feature must also be present. > The ‘org.gnu.gdb.aarch64.sme2’ feature should contain the > following: > > - ZT0 is a register of 512 bits (64 bytes). It is defined as a > vector of bytes. Implement this. Signed-off-by: Peter Maydell <[email protected]> --- target/arm/cpu.h | 1 + target/arm/internals.h | 3 ++ target/arm/gdbstub.c | 7 ++++ target/arm/gdbstub64.c | 76 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index bf221e6f973..912f7a87e42 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -939,6 +939,7 @@ struct ArchCPU { DynamicGDBFeatureInfo dyn_sysreg_feature; DynamicGDBFeatureInfo dyn_svereg_feature; DynamicGDBFeatureInfo dyn_smereg_feature; + DynamicGDBFeatureInfo dyn_sme2reg_feature; DynamicGDBFeatureInfo dyn_m_systemreg_feature; DynamicGDBFeatureInfo dyn_m_secextreg_feature; diff --git a/target/arm/internals.h b/target/arm/internals.h index f539bbe58e1..c41c1f224a5 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1715,10 +1715,13 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env) GDBFeature *arm_gen_dynamic_svereg_feature(CPUState *cpu, int base_reg); GDBFeature *arm_gen_dynamic_smereg_feature(CPUState *cpu, int base_reg); +GDBFeature *arm_gen_dynamic_sme2reg_feature(CPUState *cpu, int base_reg); int aarch64_gdb_get_sve_reg(CPUState *cs, GByteArray *buf, int reg); int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg); int aarch64_gdb_get_sme_reg(CPUState *cs, GByteArray *buf, int reg); int aarch64_gdb_set_sme_reg(CPUState *cs, uint8_t *buf, int reg); +int aarch64_gdb_get_sme2_reg(CPUState *cs, GByteArray *buf, int reg); +int aarch64_gdb_set_sme2_reg(CPUState *cs, uint8_t *buf, int reg); int aarch64_gdb_get_fpu_reg(CPUState *cs, GByteArray *buf, int reg); int aarch64_gdb_set_fpu_reg(CPUState *cs, uint8_t *buf, int reg); int aarch64_gdb_get_pauth_reg(CPUState *cs, GByteArray *buf, int reg); diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index 8d2229f5192..7cac2a5965e 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -554,6 +554,13 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) arm_gen_dynamic_smereg_feature(cs, cs->gdb_num_regs); gdb_register_coprocessor(cs, aarch64_gdb_get_sme_reg, aarch64_gdb_set_sme_reg, sme_feature, 0); + if (isar_feature_aa64_sme2(&cpu->isar)) { + GDBFeature *sme2_feature = + arm_gen_dynamic_sme2reg_feature(cs, cs->gdb_num_regs); + gdb_register_coprocessor(cs, aarch64_gdb_get_sme2_reg, + aarch64_gdb_set_sme2_reg, + sme2_feature, 0); + } } /* * Note that we report pauth information via the feature name diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index 65d6bbe65fb..7f7d706324e 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -335,6 +335,58 @@ int aarch64_gdb_set_sme_reg(CPUState *cs, uint8_t *buf, int reg) return 0; } +int aarch64_gdb_get_sme2_reg(CPUState *cs, GByteArray *buf, int reg) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + int len = 0; + + switch (reg) { + case 0: /* ZT0 */ + for (int i = 0; i < ARRAY_SIZE(env->za_state.zt0); i+= 2) { + len += gdb_get_reg128(buf, env->za_state.zt0[i + 1], + env->za_state.zt0[i]); + } + return len; + default: + /* gdbstub asked for something out of range */ + qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg); + break; + } + + return 0; +} + +int aarch64_gdb_set_sme2_reg(CPUState *cs, uint8_t *buf, int reg) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + int len = 0; + + switch (reg) { + case 0: /* ZT0 */ + for (int i = 0; i < ARRAY_SIZE(env->za_state.zt0); i += 2) { + if (target_big_endian()) { + env->za_state.zt0[i + 1] = ldq_p(buf); + buf += 8; + env->za_state.zt0[i] = ldq_p(buf); + } else { + env->za_state.zt0[i] = ldq_p(buf); + buf += 8; + env->za_state.zt0[i + 1] = ldq_p(buf); + } + buf += 8; + len += 16; + } + return len; + default: + /* gdbstub asked for something out of range */ + break; + } + + return 0; +} + int aarch64_gdb_get_pauth_reg(CPUState *cs, GByteArray *buf, int reg) { ARMCPU *cpu = ARM_CPU(cs); @@ -534,6 +586,30 @@ GDBFeature *arm_gen_dynamic_smereg_feature(CPUState *cs, int base_reg) return &cpu->dyn_smereg_feature.desc; } +GDBFeature *arm_gen_dynamic_sme2reg_feature(CPUState *cs, int base_reg) +{ + ARMCPU *cpu = ARM_CPU(cs); + GDBFeatureBuilder builder; + int reg = 0; + + gdb_feature_builder_init(&builder, &cpu->dyn_sme2reg_feature.desc, + "org.gnu.gdb.aarch64.sme2", "sme2-registers.xml", + base_reg); + + + /* Create the sme2_bv vector type (a 64 byte vector) */ + gdb_feature_builder_append_tag( + &builder, "<vector id=\"sme2_bv\" type=\"uint8\" count=\"64\"/>"); + + /* Define the ZT0 register */ + gdb_feature_builder_append_reg(&builder, "zt0", 64 * 8, reg++, + "sme2_bv", NULL); + + gdb_feature_builder_end(&builder); + + return &cpu->dyn_sme2reg_feature.desc; +} + #ifdef CONFIG_USER_ONLY int aarch64_gdb_get_tag_ctl_reg(CPUState *cs, GByteArray *buf, int reg) { -- 2.43.0
