qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC] qemu-system-arm: cortex-m gdb registers


From: Christopher Friedt
Subject: [Qemu-devel] [RFC] qemu-system-arm: cortex-m gdb registers
Date: Mon, 14 Dec 2015 01:36:10 -0500

* allow overriding the default xml descriptor with gdb_xml_descriptor()
* read cortex-m registers using arm_cortexm_gdb_read_register()
* write cortex-m registers using arm_cortexm_gdb_write_register()
* correct the number of cortex-m core regs to 23

Signed-off-by: Christopher Friedt <address@hidden>
---
 gdbstub.c            |  29 ++++---
 include/qom/cpu.h    |   1 +
 target-arm/cpu-qom.h |   4 +
 target-arm/cpu.c     |   5 +-
 target-arm/gdbstub.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 241 insertions(+), 13 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 9c29aa0..4684a4b 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -540,19 +540,24 @@ static const char *get_feature_xml(const char *p, const 
char **newp,
             GDBRegisterState *r;
             CPUState *cpu = first_cpu;
 
-            snprintf(target_xml, sizeof(target_xml),
-                     "<?xml version=\"1.0\"?>"
-                     "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
-                     "<target>"
-                     "<xi:include href=\"%s\"/>",
-                     cc->gdb_core_xml_file);
-
-            for (r = cpu->gdb_regs; r; r = r->next) {
-                pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
-                pstrcat(target_xml, sizeof(target_xml), r->xml);
-                pstrcat(target_xml, sizeof(target_xml), "\"/>");
+            if (cc->gdb_xml_descriptor) {
+                cc->gdb_xml_descriptor(cpu, target_xml, sizeof(target_xml));
+            } else {
+                snprintf(target_xml, sizeof(target_xml),
+                         "<?xml version=\"1.0\"?>"
+                         "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
+                         "<target>"
+                         "<xi:include href=\"%s\"/>",
+                         cc->gdb_core_xml_file);
+
+                for (r = cpu->gdb_regs; r; r = r->next) {
+                    pstrcat(target_xml, sizeof(target_xml),
+                        "<xi:include href=\"");
+                    pstrcat(target_xml, sizeof(target_xml), r->xml);
+                    pstrcat(target_xml, sizeof(target_xml), "\"/>");
+                }
+                pstrcat(target_xml, sizeof(target_xml), "</target>");
             }
-            pstrcat(target_xml, sizeof(target_xml), "</target>");
         }
         return target_xml;
     }
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 51a1323..7b8d875 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -152,6 +152,7 @@ typedef struct CPUClass {
     int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int rw,
                             int mmu_index);
     hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
+    int (*gdb_xml_descriptor)(CPUState *cpu, char *buf, size_t len);
     int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg);
     int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
     void (*debug_excp_handler)(CPUState *cpu);
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 25fb1ce..eafae6b 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -221,6 +221,10 @@ hwaddr arm_cpu_get_phys_page_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);
 
+int arm_cortexm_gdb_xml_descriptor(CPUState *cpu, char *buf, size_t len);
+int arm_cortexm_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int arm_cortexm_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
 /* Callback functions for the generic timer's timers. */
 void arm_gt_ptimer_cb(void *opaque);
 void arm_gt_vtimer_cb(void *opaque);
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 30739fc..e56b77a 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -553,7 +553,6 @@ static void arm_cpu_post_init(Object *obj)
                                      &error_abort);
         }
     }
-
 }
 
 static void arm_cpu_finalizefn(Object *obj)
@@ -910,6 +909,10 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
 #endif
 
     cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
+    cc->gdb_num_core_regs = 23;
+    cc->gdb_xml_descriptor = arm_cortexm_gdb_xml_descriptor;
+    cc->gdb_read_register = arm_cortexm_gdb_read_register;
+    cc->gdb_write_register = arm_cortexm_gdb_write_register;
 }
 
 static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
diff --git a/target-arm/gdbstub.c b/target-arm/gdbstub.c
index 1c34396..eb39757 100644
--- a/target-arm/gdbstub.c
+++ b/target-arm/gdbstub.c
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2003-2005 Fabrice Bellard
  * Copyright (c) 2013 SUSE LINUX Products GmbH
+ * Copyright (c) 2015 Christopher Friedt
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -100,3 +101,217 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
     /* Unknown register.  */
     return 0;
 }
+
+enum cm_gdb_regnr {
+    R0, R1, R2, R3,
+    R4, R5, R6, R7,
+    R8, R9, R10, R11,
+    R12, SP, LR, PC,
+    XPSR, MSP, PSP, PRIMASK,
+    BASEPRI, FAULTMASK, CONTROL,
+};
+struct cm_gdb_regdesc {
+    const char *const name;
+    int bitsz;
+    int nr;
+    const char *const type;
+    const char *const grp;
+};
+static const struct cm_gdb_regdesc cm_gdb_regdesc[] = {
+    { "r0",        32,        R0, "int",      "general", },
+    { "r1",        32,        R1, "int",      "general", },
+    { "r2",        32,        R2, "int",      "general", },
+    { "r3",        32,        R3, "int",      "general", },
+    { "r4",        32,        R4, "int",      "general", },
+    { "r5",        32,        R5, "int",      "general", },
+    { "r6",        32,        R6, "int",      "general", },
+    { "r7",        32,        R7, "int",      "general", },
+    { "r8",        32,        R8, "int",      "general", },
+    { "r9",        32,        R9, "int",      "general", },
+    { "r10",       32,       R10, "int",      "general", },
+    { "r11",       32,       R11, "int",      "general", },
+    { "r12",       32,       R12, "int",      "general", },
+    { "sp",        32,        SP, "data_ptr", "general", },
+    { "lr",        32,        LR, "int",      "general", },
+    { "pc",        32,        PC, "code_ptr", "general", },
+    { "xpsr",      32,      XPSR, "int",      "general", },
+    { "msp",       32,       MSP, "data_ptr", "system",  },
+    { "psp",       32,       PSP, "data_ptr", "system",  },
+    { "primask",    1,   PRIMASK, "int8",     "system",  },
+    { "basepri",    8,   BASEPRI, "int8",     "system",  },
+    { "faultmask",  1, FAULTMASK, "int8",     "system",  },
+    { "control",    2,   CONTROL, "int8",     "system",  },
+};
+
+int arm_cortexm_gdb_xml_descriptor(CPUState *cs, char *buf, size_t len)
+{
+    int r;
+    int i;
+    ssize_t l;
+    char *d;
+    ARMCPU *cpu;
+    CPUARMState *env;
+
+    l = len;
+    d = buf;
+    cpu = ARM_CPU(cs);
+    env = &cpu->env;
+
+#define _update_buf_or_err() \
+    do { \
+        d += r; \
+        len -= r; \
+        if (r < 0 || l <= 0) { \
+            goto nospace; \
+        } \
+    } while (0);
+
+    r = snprintf(d, l,
+        "<?xml version=\"1.0\"?>"
+        "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
+        "<target version=\"1.0\">"
+        "<feature name=\"org.gnu.gdb.arm.m-profile\">"
+    );
+    _update_buf_or_err();
+
+    for (
+        i = 0;
+        i < sizeof(cm_gdb_regdesc) / sizeof(cm_gdb_regdesc[0]);
+        i++
+    ) {
+        r = snprintf(d, l,
+            "<reg name=\"%s\" bitsize=\"%d\" "
+            "regnum=\"%d\" type=\"%s\" group=\"%s\"/>",
+            cm_gdb_regdesc[i].name,
+            cm_gdb_regdesc[i].bitsz,
+            cm_gdb_regdesc[i].nr,
+            cm_gdb_regdesc[i].type,
+            cm_gdb_regdesc[i].grp
+        );
+        _update_buf_or_err();
+
+        if (XPSR == i) {
+            r = snprintf(d, l,
+                "</feature>"
+                "<feature name=\"org.gnu.gdb.arm.m-system\">"
+            );
+            _update_buf_or_err();
+        }
+    }
+
+    r = snprintf(d, l,
+        "</feature>"
+        "</target>"
+    );
+    _update_buf_or_err();
+
+    r = 0;
+    goto out;
+
+nospace:
+    buf[0] = '\0';
+    r = -1;
+out:
+    return r;
+
+#undef _update_buf_or_err
+}
+
+#ifndef PSTATE_F
+#define PSTATE_F (1U << 6)
+#endif
+#ifndef PSTATE_I
+#define PSTATE_I (1U << 7)
+#endif
+
+int arm_cortexm_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
+    if (n < XPSR) {
+        /* Core integer register.  */
+        return gdb_get_reg32(mem_buf, env->regs[n]);
+    }
+
+    switch (n) {
+    case XPSR:
+        return gdb_get_reg32(mem_buf, xpsr_read(env));
+    case MSP:
+        return gdb_get_reg32(mem_buf,
+            env->v7m.current_sp ? env->v7m.other_sp : env->regs[SP]);
+    case PSP:
+        return gdb_get_reg32(mem_buf,
+            env->v7m.current_sp ? env->regs[SP] : env->v7m.other_sp);
+    case PRIMASK:
+        return gdb_get_reg8(mem_buf, !!(env->daif & PSTATE_I));
+    case BASEPRI:
+        return gdb_get_reg8(mem_buf, env->v7m.basepri);
+    case FAULTMASK:
+        return gdb_get_reg8(mem_buf, !!(env->daif & PSTATE_F));
+    case CONTROL:
+        return gdb_get_reg8(mem_buf, env->v7m.control);
+    }
+    /* Unknown register.  */
+    return 0;
+}
+
+int arm_cortexm_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    uint32_t tmp;
+
+    tmp = ldl_p(mem_buf);
+
+    /* Mask out low bit of PC to workaround gdb bugs.  This will probably
+       cause problems if we ever implement the Jazelle DBX extensions.  */
+    if (n == 15) {
+        tmp &= ~1;
+    }
+
+    if (n < 16) {
+        /* Core integer register.  */
+        env->regs[n] = tmp;
+        return 4;
+    }
+    switch (n) {
+    case XPSR: return 4;
+    case MSP:
+        if (env->v7m.current_sp) {
+            env->v7m.other_sp = tmp;
+        } else {
+            env->regs[SP] = tmp;
+        }
+        return 4;
+    case PSP:
+        if (env->v7m.current_sp) {
+            env->regs[SP] = tmp;
+        } else {
+            env->v7m.other_sp = tmp;
+        }
+        return 4;
+    case PRIMASK:
+        if (tmp & 1) {
+            env->daif |= PSTATE_I;
+        } else {
+            env->daif &= ~PSTATE_I;
+        }
+        return 1;
+    case BASEPRI:
+        env->v7m.basepri = tmp & 0xff;
+        return 1;
+    case FAULTMASK:
+        if (tmp & 1) {
+            env->daif |= PSTATE_F;
+        } else {
+            env->daif &= ~PSTATE_F;
+        }
+        return 1;
+    case CONTROL:
+        env->v7m.control = tmp & 0x3;
+        return 1;
+    }
+    /* Unknown register.  */
+    return 0;
+}
-- 
2.5.4 (Apple Git-61)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]