^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* kgdb.c: KGDB support for 64-bit sparc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kgdb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kdebug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/ftrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/context_tracking.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/kdebug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct reg_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) gdb_regs[GDB_G0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) for (i = 0; i < 15; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) gdb_regs[GDB_L0 + i] = win->locals[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) gdb_regs[GDB_I0 + i] = win->ins[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) for (i = GDB_F0; i <= GDB_F62; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) gdb_regs[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) gdb_regs[GDB_PC] = regs->tpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) gdb_regs[GDB_NPC] = regs->tnpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) gdb_regs[GDB_STATE] = regs->tstate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) gdb_regs[GDB_FSR] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) gdb_regs[GDB_FPRS] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) gdb_regs[GDB_Y] = regs->y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct thread_info *t = task_thread_info(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) extern unsigned int switch_to_pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) extern unsigned int ret_from_fork;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct reg_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned long pc, cwp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) for (i = GDB_G0; i < GDB_G6; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) gdb_regs[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) gdb_regs[GDB_G6] = (unsigned long) t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) gdb_regs[GDB_G7] = (unsigned long) p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) for (i = GDB_O0; i < GDB_SP; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) gdb_regs[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) gdb_regs[GDB_SP] = t->ksp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) gdb_regs[GDB_O7] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) win = (struct reg_window *) (t->ksp + STACK_BIAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) gdb_regs[GDB_L0 + i] = win->locals[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) gdb_regs[GDB_I0 + i] = win->ins[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) for (i = GDB_F0; i <= GDB_F62; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) gdb_regs[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (t->new_child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pc = (unsigned long) &ret_from_fork;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pc = (unsigned long) &switch_to_pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) gdb_regs[GDB_PC] = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) gdb_regs[GDB_NPC] = pc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) cwp = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) gdb_regs[GDB_STATE] = (TSTATE_PRIV | TSTATE_IE | cwp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) gdb_regs[GDB_FSR] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) gdb_regs[GDB_FPRS] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) gdb_regs[GDB_Y] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct reg_window *win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) for (i = 0; i < 15; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* If the TSTATE register is changing, we have to preserve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * the CWP field, otherwise window save/restore explodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (regs->tstate != gdb_regs[GDB_STATE]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned long cwp = regs->tstate & TSTATE_CWP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) regs->tstate = (gdb_regs[GDB_STATE] & ~TSTATE_CWP) | cwp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) regs->tpc = gdb_regs[GDB_PC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) regs->tnpc = gdb_regs[GDB_NPC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) regs->y = gdb_regs[GDB_Y];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) win->locals[i] = gdb_regs[GDB_L0 + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) win->ins[i] = gdb_regs[GDB_I0 + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) __asm__ __volatile__("rdpr %%pstate, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) "wrpr %0, %1, %%pstate"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) : "=r" (flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) : "i" (PSTATE_IE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) flushw_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (atomic_read(&kgdb_active) != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) kgdb_nmicallback(raw_smp_processor_id(), regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) __asm__ __volatile__("wrpr %0, 0, %%pstate"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) : : "r" (flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) char *remcomInBuffer, char *remcomOutBuffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct pt_regs *linux_regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) switch (remcomInBuffer[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* try to read optional parameter, pc unchanged if no parm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ptr = &remcomInBuffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (kgdb_hex2long(&ptr, &addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) linux_regs->tpc = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) linux_regs->tnpc = addr + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case 'D':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case 'k':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (linux_regs->tpc == (unsigned long) arch_kgdb_breakpoint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) linux_regs->tpc = linux_regs->tnpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) linux_regs->tnpc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) enum ctx_state prev_state = exception_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (user_mode(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) bad_trap(regs, trap_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) flushw_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) exception_exit(prev_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int kgdb_arch_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) void kgdb_arch_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) regs->tpc = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) regs->tnpc = regs->tpc + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) const struct kgdb_arch arch_kgdb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* Breakpoint instruction: ta 0x72 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) };