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)
 {
