diff mbox series

[4/5] riscv: Use the XML target descriptions to support system registers report

Message ID 1583225274-26292-1-git-send-email-vincent.chen@sifive.com (mailing list archive)
State New, archived
Headers show
Series riscv: Add KGDB and KDB support | expand

Commit Message

Vincent Chen March 3, 2020, 8:47 a.m. UTC
The sstatus, badaddr and scause registers belonged to the thread
context, and KGDB can obtain their contents from pt_regs in each trap.
However, the sequential number of these registers is far from the general
purpose registers. It causes riscv to report many trivial middle
registers in the reply packets. In order to solve this problem, the GDB
query mechanism was introduced to enable KGDB to customize the reported
register list through the XML target descriptions.

Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
---
 arch/riscv/include/asm/gdb_xml.h | 60 ++++++++++++++++++++++++++++++++++++++++
 arch/riscv/include/asm/kgdb.h    |  5 +++-
 arch/riscv/kernel/kgdb.c         | 27 ++++++++++++++++++
 3 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/include/asm/gdb_xml.h
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/gdb_xml.h b/arch/riscv/include/asm/gdb_xml.h
new file mode 100644
index 000000000000..42c31f11265c
--- /dev/null
+++ b/arch/riscv/include/asm/gdb_xml.h
@@ -0,0 +1,60 @@ 
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+static const char gdb_query_pkt[10] = "Supported:";
+
+static const char gdb_reply_feature[64] =
+			"PacketSize=2048;qXfer:features:read+;";
+
+static const char gdb_xfer_read_target[25] = "Xfer:features:read:target";
+
+static const char gdb_xfer_read_cpuxml[38] =
+			"Xfer:features:read:riscv-64bit-cpu.xml";
+
+static const char gdb_target_desc[256] =
+"l<?xml version=\"1.0\"?>"
+"<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
+"<target>"
+"<xi:include href=\"riscv-64bit-cpu.xml\"/>"
+"</target>";
+
+static const char gdb_cpuxml[2048] =
+"l<?xml version=\"1.0\"?>"
+"<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">"
+"<feature name=\"org.gnu.gdb.riscv.cpu\">"
+"<reg name=\""PT_REG_ZERO"\" bitsize=\"64\" type=\"int\" regnum=\"0\"/>"
+"<reg name=\""PT_REG_RA"\" bitsize=\"64\" type=\"code_ptr\"/>"
+"<reg name=\""PT_REG_SP"\" bitsize=\"64\" type=\"data_ptr\"/>"
+"<reg name=\""PT_REG_GP"\" bitsize=\"64\" type=\"data_ptr\"/>"
+"<reg name=\""PT_REG_TP"\" bitsize=\"64\" type=\"data_ptr\"/>"
+"<reg name=\""PT_REG_T0"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_T1"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_T2"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_FP"\" bitsize=\"64\" type=\"data_ptr\"/>"
+"<reg name=\""PT_REG_S1"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A0"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A1"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A2"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A3"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A4"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A5"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A6"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_A7"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S2"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S3"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S4"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S5"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S6"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S7"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S8"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S9"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S10"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_S11"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_T3"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_T4"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_T5"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_T6"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_SEPC"\" bitsize=\"64\" type=\"code_ptr\"/>"
+"<reg name=\""PT_REG_SSTATUS"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_STVAL"\" bitsize=\"64\" type=\"int\"/>"
+"<reg name=\""PT_REG_SCAUSE"\" bitsize=\"64\" type=\"int\"/>"
+"</feature>";
diff --git a/arch/riscv/include/asm/kgdb.h b/arch/riscv/include/asm/kgdb.h
index e3b455932506..67078aec867f 100644
--- a/arch/riscv/include/asm/kgdb.h
+++ b/arch/riscv/include/asm/kgdb.h
@@ -7,7 +7,7 @@ 
 
 #define GDB_SIZEOF_REG sizeof(unsigned long)
 
-#define DBG_MAX_REG_NUM (33)
+#define DBG_MAX_REG_NUM (36)
 #define NUMREGBYTES ((DBG_MAX_REG_NUM) * GDB_SIZEOF_REG)
 #define CACHE_FLUSH_IS_SAFE     1
 #define BUFMAX                  2048
@@ -66,6 +66,9 @@  static inline void arch_kgdb_breakpoint(void)
 #define PT_REG_T5 "t5"
 #define PT_REG_T6 "t6"
 #define PT_REG_SEPC "pc"
+#define PT_REG_SSTATUS "sstatus"
+#define PT_REG_STVAL "stval"
+#define PT_REG_SCAUSE "scause"
 
 #endif
 #endif
diff --git a/arch/riscv/kernel/kgdb.c b/arch/riscv/kernel/kgdb.c
index 0a3fe5d672f1..01af9fb43150 100644
--- a/arch/riscv/kernel/kgdb.c
+++ b/arch/riscv/kernel/kgdb.c
@@ -7,6 +7,7 @@ 
 #include <linux/irqflags.h>
 #include <linux/string.h>
 #include <asm/cacheflush.h>
+#include <asm/gdb_xml.h>
 
 enum {
 	NOT_KGDB_BREAK = 0,
@@ -48,6 +49,9 @@  struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
 	{PT_REG_T5, GDB_SIZEOF_REG, offsetof(struct pt_regs, t5)},
 	{PT_REG_T6, GDB_SIZEOF_REG, offsetof(struct pt_regs, t6)},
 	{PT_REG_SEPC, GDB_SIZEOF_REG, offsetof(struct pt_regs, epc)},
+	{PT_REG_SSTATUS, GDB_SIZEOF_REG, offsetof(struct pt_regs, status)},
+	{PT_REG_STVAL, GDB_SIZEOF_REG, offsetof(struct pt_regs, badaddr)},
+	{PT_REG_SCAUSE, GDB_SIZEOF_REG, offsetof(struct pt_regs, cause)},
 };
 
 char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
@@ -100,6 +104,29 @@  void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
 	regs->epc = pc;
 }
 
+void kgdb_arch_cmd_query(char *remcom_in_buffer, char *remcom_out_buffer)
+{
+	switch (remcom_in_buffer[1]) {
+	case 'S':
+		if (!strncmp(remcom_in_buffer + 1,
+			     gdb_query_pkt, sizeof(gdb_query_pkt)))
+			strcpy(remcom_out_buffer, gdb_reply_feature);
+		break;
+	case 'X':
+		if (!strncmp(remcom_in_buffer + 1,
+			     gdb_xfer_read_target,
+			     sizeof(gdb_xfer_read_target)))
+			strcpy(remcom_out_buffer, gdb_target_desc);
+		else if (!strncmp(remcom_in_buffer + 1,
+				  gdb_xfer_read_cpuxml,
+				  sizeof(gdb_xfer_read_cpuxml)))
+			strcpy(remcom_out_buffer, gdb_cpuxml);
+		break;
+	default:
+		break;
+	}
+}
+
 static inline void kgdb_arch_update_addr(struct pt_regs *regs,
 					 char *remcom_in_buffer)
 {