From: Christopher Friedt <chrisfriedt@gmail.com>
To: qemu-devel@nongnu.org
Cc: Christopher Friedt <chrisfriedt@gmail.com>
Subject: [Qemu-devel] [RFC] qemu-system-arm: cortex-m gdb registers
Date: Mon, 14 Dec 2015 01:36:10 -0500 [thread overview]
Message-ID: <1450074970-28562-2-git-send-email-chrisfriedt@gmail.com> (raw)
In-Reply-To: <1450074970-28562-1-git-send-email-chrisfriedt@gmail.com>
* 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 <chrisfriedt@gmail.com>
---
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)
next prev parent reply other threads:[~2015-12-14 6:36 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-14 6:36 [Qemu-devel] [RFC] qemu-system-arm: cortex-m gdb registers Christopher Friedt
2015-12-14 6:36 ` Christopher Friedt [this message]
2015-12-14 8:31 ` Peter Maydell
2015-12-14 13:07 ` Christopher Friedt
2015-12-14 13:14 ` Peter Maydell
2015-12-14 13:16 ` Christopher Friedt
2015-12-14 14:22 ` Christopher Friedt
2015-12-14 15:11 ` Peter Maydell
2015-12-14 15:56 ` Alex Bennée
2015-12-14 16:18 ` Christopher Friedt
2015-12-16 0:16 ` Christopher Friedt
2015-12-16 11:16 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1450074970-28562-2-git-send-email-chrisfriedt@gmail.com \
--to=chrisfriedt@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.