|
From: | Abdallah Bouassida |
Subject: | [Qemu-arm] [PATCH RFC] target-arm:Add a dynamic XML-description of the cp-registers to GDB |
Date: | Tue, 16 Jan 2018 10:40:10 +0100 |
User-agent: | Mozilla/5.0 (Windows NT 6.3; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2 |
[PATCH RFC] target-arm:Add a dynamic XML-description of the
cp-registers to GDB This patch offers to GDB the ability to read/write all the coprocessor registers for ARM and ARM64 by generating dynamically an XML-description for these registers. - gdbstub.c : *Extend the get_feature_xml() to handle the dynamic XML generation for architectures that support this (gdb_coprocessor_dynnamic_xml == true) *Extend the gdb_write_register() and gdb_read_register() to handle the write and the read of these registers. - include/qom/cpu.h: *Add a new structure "XMLDynamicDescription". *Declare the new variables and function pointers. - target/arm/cpu.c: *Initialize the new variables and function pointers for ARM. - target/arm/cpu.h: *Declare the new read, write and XML dynamic generation functions. *Declare the write_raw_cp_reg() as I have changed it to non static. - target/arm/gdbstub.c: *Define the new functions for ARM: arm_generate_xml(): is called for each register of the hashtable cp_regs to generate the right XML "<reg />" line for it. arm_get_feature_xml_dynamically(): generate the XML dynamically. arm_cpu_gdb_read_cpregister(): To read the coprocessor registers. arm_cpu_gdb_write_cpregister(): To write the coprocessor registers. This patch is tagged as [RFC] because I need help to review the following points: *I only take the registers that (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) So, am I covering all the Coprocessor registers with that? *For the ARM64, should I differentiate the registers that have two views (32 and 64) Maybe by adding in the XML description a "32" tag for the registers name for the 32bit view and a "64" for the 64bit view. *How to properly handle the secure and the non secure views? Signed-off-by: Abdallah Bouassida <address@hidden> --- gdbstub.c | 18 +++++++++++ include/qom/cpu.h | 19 +++++++++++ target/arm/cpu.c | 5 +++ target/arm/cpu.h | 6 +++- target/arm/gdbstub.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ target/arm/helper.c | 3 +- 6 files changed, 138 insertions(+), 3 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index f1d5148..b0124c8 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -670,10 +670,20 @@ static const char *get_feature_xml(const char *p, const char **newp, pstrcat(target_xml, sizeof(target_xml), r->xml); pstrcat(target_xml, sizeof(target_xml), "\"/>"); } + if (cc->gdb_coprocessor_dynamic_xml) { + pstrcat(target_xml, sizeof(target_xml), "<xi:include href=""> + pstrcat(target_xml, sizeof(target_xml), \ + "coprocessor_dynamic.xml"); + pstrcat(target_xml, sizeof(target_xml), "\"/>"); + } pstrcat(target_xml, sizeof(target_xml), "</target>"); } return target_xml; } + if (strncmp(p, "coprocessor_dynamic.xml", len) == 0) { + CPUState *cpu = first_cpu; + return cc->get_feature_xml_dynamically(cpu); + } for (i = 0; ; i++) { name = xml_builtin[i][0]; if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len)) @@ -697,6 +707,10 @@ static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg) return r->get_reg(env, mem_buf, reg - r->base_reg); } } + + if (reg < cpu->gdb_num_regs + cc->gdb_num_cpregs) { + return cc->gdb_read_cpregister(cpu, mem_buf, reg - cpu->gdb_num_regs); + } return 0; } @@ -715,6 +729,10 @@ static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg) return r->set_reg(env, mem_buf, reg - r->base_reg); } } + + if (reg < cpu->gdb_num_regs + cc->gdb_num_cpregs) { + return cc->gdb_write_cpregister(cpu, mem_buf, reg - cpu->gdb_num_regs); + } return 0; } diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 93bd546..f40ee59 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -76,6 +76,19 @@ typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr, struct TranslationBlock; /** + * XMLDynamicDescription: + * @desc: Contains the XML descriptions. + * @num_cpregs: Number of the Coprocessor registers seen by GDB. + * @xml_cpregs_ordred_keys: Array that contains the corresponding Key of + * a given cpreg with the same order of the cpreg in the XML description. + */ +typedef struct XMLDynamicDescription { + char * desc; + int num_cpregs; + uint32_t *xml_cpregs_ordred_keys; +} XMLDynamicDescription; + +/** * CPUClass: * @class_by_name: Callback to map -cpu command line model name to an * instantiatable CPU type. @@ -196,6 +209,12 @@ typedef struct CPUClass { const struct VMStateDescription *vmsd; const char *gdb_core_xml_file; + bool gdb_coprocessor_dynamic_xml; + XMLDynamicDescription dyn_xml; + int gdb_num_cpregs; + char * (*get_feature_xml_dynamically)(CPUState *cpu); + int (*gdb_read_cpregister)(CPUState *cpu, uint8_t *buf, int reg); + int (*gdb_write_cpregister)(CPUState *cpu, uint8_t *buf, int reg); gchar * (*gdb_arch_name)(CPUState *cpu); void (*cpu_exec_enter)(CPUState *cpu); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index cc1856c..00efae4 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1751,6 +1751,11 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) #endif cc->gdb_num_core_regs = 26; cc->gdb_core_xml_file = "arm-core.xml"; + cc->gdb_coprocessor_dynamic_xml=true; + cc->gdb_num_cpregs = 0; + cc->get_feature_xml_dynamically = arm_get_feature_xml_dynamically; + cc->gdb_read_cpregister = arm_cpu_gdb_read_cpregister; + cc->gdb_write_cpregister = arm_cpu_gdb_write_cpregister; cc->gdb_arch_name = arm_gdb_arch_name; cc->gdb_stop_before_watchpoint = true; cc->debug_excp_handler = arm_debug_excp_handler; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 9631670..16f84e3 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -797,6 +797,9 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr, int arm_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +char *arm_get_feature_xml_dynamically(CPUState *cpu); +int arm_cpu_gdb_read_cpregister(CPUState *cpu, uint8_t *buf, int reg); +int arm_cpu_gdb_write_cpregister(CPUState *cpu, uint8_t *buf, int reg); int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); @@ -2005,7 +2008,8 @@ static inline bool cp_access_ok(int current_el, /* Raw read of a coprocessor register (as needed for migration, etc) */ uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri); - +void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t v); /** * write_list_to_cpustate * @cpu: ARMCPU diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index 04c1208..123da12 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -101,3 +101,93 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) /* Unknown register. */ return 0; } + +static void arm_generate_xml(gpointer key, gpointer value, gpointer cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUClass *cc = CPU_GET_CLASS(cpu); + XMLDynamicDescription *dyn_xml = &cc->dyn_xml; + ARMCPRegInfo *ri = value; + uint32_t ri_key= *(uint32_t *)key; + CPUARMState *env = &cpu->env; + char **target_xml=(char **)&(dyn_xml->desc); + char *tmp_xml=*target_xml; + + if (!(ri->type & (ARM_CP_NO_RAW|ARM_CP_ALIAS))) { + if (cpreg_field_is_64bit(ri)){ + if (arm_feature(env, ARM_FEATURE_AARCH64)) { + *target_xml=g_strconcat(*target_xml, "<reg name=\"", \ + ri->name, "\" bitsize=\"64\"/>", NULL); + } else { + return; + } + } else { + *target_xml=g_strconcat(*target_xml, "<reg name=\"", \ + ri->name, "\" bitsize=\"32\"/>", NULL); + } + g_free(tmp_xml); + dyn_xml->num_cpregs++; + dyn_xml->xml_cpregs_ordred_keys=g_renew(uint32_t, \ + dyn_xml->xml_cpregs_ordred_keys, dyn_xml->num_cpregs); + dyn_xml->xml_cpregs_ordred_keys[dyn_xml->num_cpregs - 1] = ri_key; + } +} + +char *arm_get_feature_xml_dynamically(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUClass *cc = CPU_GET_CLASS(cpu); + + cc->dyn_xml.num_cpregs=0; + cc->dyn_xml.desc=g_strconcat("<?xml version=\"1.0\"?>", \ + "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">", \ + "<feature name=\"org.gnu.gdb.dynamic.cp\">", NULL); + g_hash_table_foreach(cpu->cp_regs, arm_generate_xml, cs); + cc->dyn_xml.desc=g_strconcat( cc->dyn_xml.desc, "</feature>", NULL); + cc->gdb_num_cpregs=cc->dyn_xml.num_cpregs; + return cc->dyn_xml.desc; +} + +int arm_cpu_gdb_read_cpregister(CPUState *cs, uint8_t *mem_buf, int n) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUClass *cc = CPU_GET_CLASS(cpu); + ARMCPRegInfo *ri; + CPUARMState *env = &cpu->env; + uint32_t key; + + key = cc->dyn_xml.xml_cpregs_ordred_keys[n]; + ri=(ARMCPRegInfo *)get_arm_cp_reginfo(arm_env_get_cpu(env)->cp_regs, key); + if (ri) { + if(cpreg_field_is_64bit(ri)){ + return gdb_get_reg64(mem_buf, (uint64_t)read_raw_cp_reg(env,ri)); + } else { + return gdb_get_reg32(mem_buf, (uint32_t)read_raw_cp_reg(env,ri)); + } + } + return 0; +} + +int arm_cpu_gdb_write_cpregister(CPUState *cs, uint8_t *mem_buf, int n) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUClass *cc = CPU_GET_CLASS(cpu); + ARMCPRegInfo *ri; + CPUARMState *env = &cpu->env; + uint32_t tmp_buf,key; + + tmp_buf = ldl_p(mem_buf); + key = cc->dyn_xml.xml_cpregs_ordred_keys[n]; + ri=(ARMCPRegInfo *)get_arm_cp_reginfo(arm_env_get_cpu(env)->cp_regs, key); + if (ri) { + if (!(ri->type & ARM_CP_CONST)) { + write_raw_cp_reg(env, ri, tmp_buf); + if (cpreg_field_is_64bit(ri)) { + return 8; + } else { + return 4; + } + } + } + return 0; +} diff --git a/target/arm/helper.c b/target/arm/helper.c index d1395f9..fedc6bc 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -191,8 +191,7 @@ uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri) } } -static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t v) +void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v) { /* Raw write of a coprocessor register (as needed for migration, etc). * Note that constant registers are treated as write-ignored; the -- 1.9.1 |
[Prev in Thread] | Current Thread | [Next in Thread] |