Browse Source

target/arm: Implement org.gnu.gdb.aarch64.tls XML feature in gdbstub

GDB expects the TLS registers to be exposed via org.gnu.gdb.aarch64.tls,
which will contain either just "tpidr", or else "tpidr" and "tpidr2".

This will be important for SME in future, because the lazy state
restoration scheme requires GDB to use the TPIDR2 information.
GDB doesn't currently implement that, but we should provide the
register via the XML so that we are ready when future GDB versions
support it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20251017153027.969016-3-peter.maydell@linaro.org
pull/307/head
Peter Maydell 6 months ago
parent
commit
7fd82461dd
  1. 1
      target/arm/cpu.h
  2. 6
      target/arm/gdbstub.c
  3. 63
      target/arm/gdbstub64.c
  4. 3
      target/arm/internals.h

1
target/arm/cpu.h

@ -943,6 +943,7 @@ struct ArchCPU {
DynamicGDBFeatureInfo dyn_smereg_feature;
DynamicGDBFeatureInfo dyn_m_systemreg_feature;
DynamicGDBFeatureInfo dyn_m_secextreg_feature;
DynamicGDBFeatureInfo dyn_tls_feature;
/* Timers used by the generic (architected) timer */
QEMUTimer *gt_timer[NUM_GTIMERS];

6
target/arm/gdbstub.c

@ -583,6 +583,12 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
0);
}
#endif
/* All AArch64 CPUs have at least TPIDR */
gdb_register_coprocessor(cs, aarch64_gdb_get_tls_reg,
aarch64_gdb_set_tls_reg,
arm_gen_dynamic_tls_feature(cs, cs->gdb_num_regs),
0);
#endif
} else {
if (arm_feature(env, ARM_FEATURE_NEON)) {

63
target/arm/gdbstub64.c

@ -387,6 +387,44 @@ int aarch64_gdb_set_sme2_reg(CPUState *cs, uint8_t *buf, int reg)
return 0;
}
int aarch64_gdb_get_tls_reg(CPUState *cs, GByteArray *buf, int reg)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
switch (reg) {
case 0: /* TPIDR_EL0 */
return gdb_get_reg64(buf, env->cp15.tpidr_el[0]);
case 1: /* TPIDR2_EL0 */
return gdb_get_reg64(buf, env->cp15.tpidr2_el0);
default:
/* gdbstub asked for something out of range */
break;
}
return 0;
}
int aarch64_gdb_set_tls_reg(CPUState *cs, uint8_t *buf, int reg)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
switch (reg) {
case 0: /* TPIDR_EL0 */
env->cp15.tpidr_el[0] = ldq_p(buf);
return 8;
case 1: /* TPIDR2_EL0 */
env->cp15.tpidr2_el0 = ldq_p(buf);
return 8;
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);
@ -586,6 +624,31 @@ GDBFeature *arm_gen_dynamic_smereg_feature(CPUState *cs, int base_reg)
return &cpu->dyn_smereg_feature.desc;
}
GDBFeature *arm_gen_dynamic_tls_feature(CPUState *cs, int base_reg)
{
ARMCPU *cpu = ARM_CPU(cs);
GDBFeatureBuilder builder;
int reg = 0;
gdb_feature_builder_init(&builder, &cpu->dyn_tls_feature.desc,
"org.gnu.gdb.aarch64.tls", "tls-registers.xml",
base_reg);
/*
* This feature must always have "tpidr", and may also have "tpidr2"
* if the CPU has that register.
*/
gdb_feature_builder_append_reg(&builder, "tpidr", 64,
reg++, "data_ptr", NULL);
if (cpu_isar_feature(aa64_sme, cpu)) {
gdb_feature_builder_append_reg(&builder, "tpidr2", 64,
reg++, "data_ptr", NULL);
}
gdb_feature_builder_end(&builder);
return &cpu->dyn_tls_feature.desc;
}
#ifdef CONFIG_USER_ONLY
int aarch64_gdb_get_tag_ctl_reg(CPUState *cs, GByteArray *buf, int reg)
{

3
target/arm/internals.h

@ -1716,6 +1716,7 @@ 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_tls_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);
@ -1728,6 +1729,8 @@ int aarch64_gdb_get_pauth_reg(CPUState *cs, GByteArray *buf, int reg);
int aarch64_gdb_set_pauth_reg(CPUState *cs, uint8_t *buf, int reg);
int aarch64_gdb_get_tag_ctl_reg(CPUState *cs, GByteArray *buf, int reg);
int aarch64_gdb_set_tag_ctl_reg(CPUState *cs, uint8_t *buf, int reg);
int aarch64_gdb_get_tls_reg(CPUState *cs, GByteArray *buf, int reg);
int aarch64_gdb_set_tls_reg(CPUState *cs, uint8_t *buf, int reg);
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp);
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);

Loading…
Cancel
Save