^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Nios2 KGDB support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015 Altera Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Based on the code posted by Kazuyasu on the Altera Forum at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kgdb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kdebug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static int wait_for_remote_debugger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) { "zero", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) { "at", GDB_SIZEOF_REG, offsetof(struct pt_regs, r1) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) { "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r2) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) { "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r3) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) { "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r4) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) { "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r5) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) { "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r6) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) { "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r7) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) { "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r8) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) { "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r9) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) { "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) { "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) { "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) { "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) { "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) { "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) { "r16", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) { "r17", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { "r18", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) { "r19", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { "r20", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { "r21", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { "r22", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) { "r23", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) { "et", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { "bt", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { "gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { "fp", GDB_SIZEOF_REG, offsetof(struct pt_regs, fp) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { "ea", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { "ba", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { "ra", GDB_SIZEOF_REG, offsetof(struct pt_regs, ra) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, ea) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { "status", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { "estatus", GDB_SIZEOF_REG, offsetof(struct pt_regs, estatus) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { "bstatus", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { "ienable", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { "ipending", GDB_SIZEOF_REG, -1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { "cpuid", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { "ctl6", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { "exception", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { "pteaddr", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { "tlbacc", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { "tlbmisc", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { "eccinj", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { "badaddr", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { "config", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { "mpubase", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { "mpuacc", GDB_SIZEOF_REG, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (regno >= DBG_MAX_REG_NUM || regno < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (dbg_reg_def[regno].offset != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) dbg_reg_def[regno].size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) memset(mem, 0, dbg_reg_def[regno].size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return dbg_reg_def[regno].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (regno >= DBG_MAX_REG_NUM || regno < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (dbg_reg_def[regno].offset != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dbg_reg_def[regno].size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) memset((char *)gdb_regs, 0, NUMREGBYTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) gdb_regs[GDB_SP] = p->thread.kregs->sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) gdb_regs[GDB_PC] = p->thread.kregs->ea;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) regs->ea = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int kgdb_arch_handle_exception(int vector, int signo, int err_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) char *remcom_in_buffer, char *remcom_out_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) switch (remcom_in_buffer[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* handle the optional parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ptr = &remcom_in_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (kgdb_hex2long(&ptr, &addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) regs->ea = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return -1; /* this means that we do not want to exit from the handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) asmlinkage void kgdb_breakpoint_c(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * The breakpoint entry code has moved the PC on by 4 bytes, so we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * move it back. This could be done on the host but we do it here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!wait_for_remote_debugger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) regs->ea -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) else /* pass the first trap 30 code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) wait_for_remote_debugger = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) kgdb_handle_exception(30, SIGTRAP, 0, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int kgdb_arch_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) wait_for_remote_debugger = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) void kgdb_arch_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* Nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) const struct kgdb_arch arch_kgdb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* Breakpoint instruction: trap 30 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .gdb_bpt_instr = { 0xba, 0x6f, 0x3b, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };