0001
0002
0003
0004
0005
0006
0007 #include <linux/kgdb.h>
0008 #include <linux/kdebug.h>
0009 #include <linux/ftrace.h>
0010 #include <linux/context_tracking.h>
0011
0012 #include <asm/cacheflush.h>
0013 #include <asm/kdebug.h>
0014 #include <asm/ptrace.h>
0015 #include <asm/irq.h>
0016
0017 #include "kernel.h"
0018
0019 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
0020 {
0021 struct reg_window *win;
0022 int i;
0023
0024 gdb_regs[GDB_G0] = 0;
0025 for (i = 0; i < 15; i++)
0026 gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
0027
0028 win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
0029 for (i = 0; i < 8; i++)
0030 gdb_regs[GDB_L0 + i] = win->locals[i];
0031 for (i = 0; i < 8; i++)
0032 gdb_regs[GDB_I0 + i] = win->ins[i];
0033
0034 for (i = GDB_F0; i <= GDB_F62; i++)
0035 gdb_regs[i] = 0;
0036
0037 gdb_regs[GDB_PC] = regs->tpc;
0038 gdb_regs[GDB_NPC] = regs->tnpc;
0039 gdb_regs[GDB_STATE] = regs->tstate;
0040 gdb_regs[GDB_FSR] = 0;
0041 gdb_regs[GDB_FPRS] = 0;
0042 gdb_regs[GDB_Y] = regs->y;
0043 }
0044
0045 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
0046 {
0047 struct thread_info *t = task_thread_info(p);
0048 extern unsigned int switch_to_pc;
0049 extern unsigned int ret_from_fork;
0050 struct reg_window *win;
0051 unsigned long pc, cwp;
0052 int i;
0053
0054 for (i = GDB_G0; i < GDB_G6; i++)
0055 gdb_regs[i] = 0;
0056 gdb_regs[GDB_G6] = (unsigned long) t;
0057 gdb_regs[GDB_G7] = (unsigned long) p;
0058 for (i = GDB_O0; i < GDB_SP; i++)
0059 gdb_regs[i] = 0;
0060 gdb_regs[GDB_SP] = t->ksp;
0061 gdb_regs[GDB_O7] = 0;
0062
0063 win = (struct reg_window *) (t->ksp + STACK_BIAS);
0064 for (i = 0; i < 8; i++)
0065 gdb_regs[GDB_L0 + i] = win->locals[i];
0066 for (i = 0; i < 8; i++)
0067 gdb_regs[GDB_I0 + i] = win->ins[i];
0068
0069 for (i = GDB_F0; i <= GDB_F62; i++)
0070 gdb_regs[i] = 0;
0071
0072 if (t->new_child)
0073 pc = (unsigned long) &ret_from_fork;
0074 else
0075 pc = (unsigned long) &switch_to_pc;
0076
0077 gdb_regs[GDB_PC] = pc;
0078 gdb_regs[GDB_NPC] = pc + 4;
0079
0080 cwp = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP];
0081
0082 gdb_regs[GDB_STATE] = (TSTATE_PRIV | TSTATE_IE | cwp);
0083 gdb_regs[GDB_FSR] = 0;
0084 gdb_regs[GDB_FPRS] = 0;
0085 gdb_regs[GDB_Y] = 0;
0086 }
0087
0088 void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
0089 {
0090 struct reg_window *win;
0091 int i;
0092
0093 for (i = 0; i < 15; i++)
0094 regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
0095
0096
0097
0098
0099 if (regs->tstate != gdb_regs[GDB_STATE]) {
0100 unsigned long cwp = regs->tstate & TSTATE_CWP;
0101
0102 regs->tstate = (gdb_regs[GDB_STATE] & ~TSTATE_CWP) | cwp;
0103 }
0104
0105 regs->tpc = gdb_regs[GDB_PC];
0106 regs->tnpc = gdb_regs[GDB_NPC];
0107 regs->y = gdb_regs[GDB_Y];
0108
0109 win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
0110 for (i = 0; i < 8; i++)
0111 win->locals[i] = gdb_regs[GDB_L0 + i];
0112 for (i = 0; i < 8; i++)
0113 win->ins[i] = gdb_regs[GDB_I0 + i];
0114 }
0115
0116 #ifdef CONFIG_SMP
0117 void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs)
0118 {
0119 unsigned long flags;
0120
0121 __asm__ __volatile__("rdpr %%pstate, %0\n\t"
0122 "wrpr %0, %1, %%pstate"
0123 : "=r" (flags)
0124 : "i" (PSTATE_IE));
0125
0126 flushw_all();
0127
0128 if (atomic_read(&kgdb_active) != -1)
0129 kgdb_nmicallback(raw_smp_processor_id(), regs);
0130
0131 __asm__ __volatile__("wrpr %0, 0, %%pstate"
0132 : : "r" (flags));
0133 }
0134 #endif
0135
0136 int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
0137 char *remcomInBuffer, char *remcomOutBuffer,
0138 struct pt_regs *linux_regs)
0139 {
0140 unsigned long addr;
0141 char *ptr;
0142
0143 switch (remcomInBuffer[0]) {
0144 case 'c':
0145
0146 ptr = &remcomInBuffer[1];
0147 if (kgdb_hex2long(&ptr, &addr)) {
0148 linux_regs->tpc = addr;
0149 linux_regs->tnpc = addr + 4;
0150 }
0151 fallthrough;
0152
0153 case 'D':
0154 case 'k':
0155 if (linux_regs->tpc == (unsigned long) arch_kgdb_breakpoint) {
0156 linux_regs->tpc = linux_regs->tnpc;
0157 linux_regs->tnpc += 4;
0158 }
0159 return 0;
0160 }
0161 return -1;
0162 }
0163
0164 asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
0165 {
0166 enum ctx_state prev_state = exception_enter();
0167 unsigned long flags;
0168
0169 if (user_mode(regs)) {
0170 bad_trap(regs, trap_level);
0171 goto out;
0172 }
0173
0174 flushw_all();
0175
0176 local_irq_save(flags);
0177 kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
0178 local_irq_restore(flags);
0179 out:
0180 exception_exit(prev_state);
0181 }
0182
0183 int kgdb_arch_init(void)
0184 {
0185 return 0;
0186 }
0187
0188 void kgdb_arch_exit(void)
0189 {
0190 }
0191
0192 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
0193 {
0194 regs->tpc = ip;
0195 regs->tnpc = regs->tpc + 4;
0196 }
0197
0198 const struct kgdb_arch arch_kgdb_ops = {
0199
0200 .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
0201 };