Commit e14dd076 authored by Qing Zhang's avatar Qing Zhang Committed by Huacai Chen
Browse files

LoongArch: Add basic KGDB & KDB support



KGDB is intended to be used as a source level debugger for the Linux
kernel. It is used along with gdb to debug a Linux kernel. GDB can be
used to "break in" to the kernel to inspect memory, variables and regs
similar to the way an application developer would use GDB to debug an
application. KDB is a frontend of KGDB which is similar to GDB.

By now, in addition to the generic KGDB features, the LoongArch KGDB
implements the following features:
- Hardware breakpoints/watchpoints;
- Software single-step support for KDB.

Signed-off-by: Qing Zhang <zhangqing@loongson.cn>   # Framework & CoreFeature
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> # BreakPoint & SingleStep
Signed-off-by: Hui Li <lihui@loongson.cn>           # Some Minor Improvements
Signed-off-by: Randy Dunlap <rdunlap@infradead.org> # Some Build Error Fixes
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent bd3c5798
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@
    |        csky: | TODO |
    |     hexagon: |  ok  |
    |        ia64: | TODO |
    |   loongarch: | TODO |
    |   loongarch: |  ok  |
    |        m68k: | TODO |
    |  microblaze: |  ok  |
    |        mips: |  ok  |
+1 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ config LOONGARCH
	select HAVE_ARCH_AUDITSYSCALL
	select HAVE_ARCH_JUMP_LABEL
	select HAVE_ARCH_JUMP_LABEL_RELATIVE
	select HAVE_ARCH_KGDB if PERF_EVENTS
	select HAVE_ARCH_MMAP_RND_BITS if MMU
	select HAVE_ARCH_SECCOMP_FILTER
	select HAVE_ARCH_TRACEHOOK
+97 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2023 Loongson Technology Corporation Limited
 */

#ifndef _ASM_LOONGARCH_KGDB_H
#define _ASM_LOONGARCH_KGDB_H

#define GDB_SIZEOF_REG		sizeof(u64)

/* gdb remote procotol expects the following register layout. */

/*
 * General purpose registers:
 *     r0-r31: 64 bit
 *     orig_a0: 64 bit
 *     pc : 64 bit
 *     csr_badvaddr: 64 bit
 */
#define DBG_PT_REGS_BASE	0
#define DBG_PT_REGS_NUM		35
#define DBG_PT_REGS_END		(DBG_PT_REGS_BASE + DBG_PT_REGS_NUM - 1)

/*
 * Floating point registers:
 *     f0-f31: 64 bit
 */
#define DBG_FPR_BASE		(DBG_PT_REGS_END + 1)
#define DBG_FPR_NUM		32
#define DBG_FPR_END		(DBG_FPR_BASE + DBG_FPR_NUM - 1)

/*
 * Condition Flag registers:
 *     fcc0-fcc8: 8 bit
 */
#define DBG_FCC_BASE		(DBG_FPR_END + 1)
#define DBG_FCC_NUM		8
#define DBG_FCC_END		(DBG_FCC_BASE + DBG_FCC_NUM - 1)

/*
 * Floating-point Control and Status registers:
 *     fcsr: 32 bit
 */
#define DBG_FCSR_NUM		1
#define DBG_FCSR		(DBG_FCC_END + 1)

#define DBG_MAX_REG_NUM		(DBG_FCSR + 1)

/*
 * Size of I/O buffer for gdb packet.
 * considering to hold all register contents, size is set
 */
#define BUFMAX			2048

/*
 * Number of bytes required for gdb_regs buffer.
 * PT_REGS and FPR: 8 bytes; FCSR: 4 bytes; FCC: 1 bytes.
 * GDB fails to connect for size beyond this with error
 * "'g' packet reply is too long"
 */
#define NUMREGBYTES		((DBG_PT_REGS_NUM + DBG_FPR_NUM) * GDB_SIZEOF_REG + DBG_FCC_NUM * 1 + DBG_FCSR_NUM * 4)

#define BREAK_INSTR_SIZE	4
#define CACHE_FLUSH_IS_SAFE	0

/* Register numbers of various important registers. */
enum dbg_loongarch_regnum {
	DBG_LOONGARCH_ZERO = 0,
	DBG_LOONGARCH_RA,
	DBG_LOONGARCH_TP,
	DBG_LOONGARCH_SP,
	DBG_LOONGARCH_A0,
	DBG_LOONGARCH_FP = 22,
	DBG_LOONGARCH_S0,
	DBG_LOONGARCH_S1,
	DBG_LOONGARCH_S2,
	DBG_LOONGARCH_S3,
	DBG_LOONGARCH_S4,
	DBG_LOONGARCH_S5,
	DBG_LOONGARCH_S6,
	DBG_LOONGARCH_S7,
	DBG_LOONGARCH_S8,
	DBG_LOONGARCH_ORIG_A0,
	DBG_LOONGARCH_PC,
	DBG_LOONGARCH_BADV
};

void kgdb_breakinst(void);
void arch_kgdb_breakpoint(void);

#ifdef CONFIG_KGDB
bool kgdb_breakpoint_handler(struct pt_regs *regs);
#else /* !CONFIG_KGDB */
static inline bool kgdb_breakpoint_handler(struct pt_regs *regs) { return false; }
#endif /* CONFIG_KGDB */

#endif /* __ASM_KGDB_H_ */
+4 −0
Original line number Diff line number Diff line
@@ -158,6 +158,10 @@
	cfi_st  u0, PT_R21, \docfi
	csrrd	u0, PERCPU_BASE_KS
9:
#ifdef CONFIG_KGDB
	li.w	t0, CSR_CRMD_WE
	csrxchg	t0, t0, LOONGARCH_CSR_CRMD
#endif
	.endm

	.macro	SAVE_ALL docfi=0
+1 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ obj-$(CONFIG_UNWINDER_PROLOGUE) += unwind_prologue.o
obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_regs.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o

obj-$(CONFIG_KGDB)		+= kgdb.o
obj-$(CONFIG_KPROBES)		+= kprobes.o
obj-$(CONFIG_RETHOOK)		+= rethook.o rethook_trampoline.o
obj-$(CONFIG_UPROBES)		+= uprobes.o
Loading