0001
0002
0003
0004
0005
0006
0007 #include <linux/kgdb.h>
0008 #include <linux/kdebug.h>
0009 #include <linux/sched.h>
0010
0011 #include <asm/kdebug.h>
0012 #include <asm/ptrace.h>
0013 #include <asm/irq.h>
0014 #include <asm/cacheflush.h>
0015
0016 #include "kernel.h"
0017 #include "entry.h"
0018
0019 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
0020 {
0021 struct reg_window32 *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_window32 *) regs->u_regs[UREG_FP];
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_F31; i++)
0035 gdb_regs[i] = 0;
0036
0037 gdb_regs[GDB_Y] = regs->y;
0038 gdb_regs[GDB_PSR] = regs->psr;
0039 gdb_regs[GDB_WIM] = 0;
0040 gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
0041 gdb_regs[GDB_PC] = regs->pc;
0042 gdb_regs[GDB_NPC] = regs->npc;
0043 gdb_regs[GDB_FSR] = 0;
0044 gdb_regs[GDB_CSR] = 0;
0045 }
0046
0047 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
0048 {
0049 struct thread_info *t = task_thread_info(p);
0050 struct reg_window32 *win;
0051 int i;
0052
0053 for (i = GDB_G0; i < GDB_G6; i++)
0054 gdb_regs[i] = 0;
0055 gdb_regs[GDB_G6] = (unsigned long) t;
0056 gdb_regs[GDB_G7] = 0;
0057 for (i = GDB_O0; i < GDB_SP; i++)
0058 gdb_regs[i] = 0;
0059 gdb_regs[GDB_SP] = t->ksp;
0060 gdb_regs[GDB_O7] = 0;
0061
0062 win = (struct reg_window32 *) t->ksp;
0063 for (i = 0; i < 8; i++)
0064 gdb_regs[GDB_L0 + i] = win->locals[i];
0065 for (i = 0; i < 8; i++)
0066 gdb_regs[GDB_I0 + i] = win->ins[i];
0067
0068 for (i = GDB_F0; i <= GDB_F31; i++)
0069 gdb_regs[i] = 0;
0070
0071 gdb_regs[GDB_Y] = 0;
0072
0073 gdb_regs[GDB_PSR] = t->kpsr;
0074 gdb_regs[GDB_WIM] = t->kwim;
0075 gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
0076 gdb_regs[GDB_PC] = t->kpc;
0077 gdb_regs[GDB_NPC] = t->kpc + 4;
0078 gdb_regs[GDB_FSR] = 0;
0079 gdb_regs[GDB_CSR] = 0;
0080 }
0081
0082 void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
0083 {
0084 struct reg_window32 *win;
0085 int i;
0086
0087 for (i = 0; i < 15; i++)
0088 regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
0089
0090
0091
0092
0093 if (regs->psr != gdb_regs[GDB_PSR]) {
0094 unsigned long cwp = regs->psr & PSR_CWP;
0095
0096 regs->psr = (gdb_regs[GDB_PSR] & ~PSR_CWP) | cwp;
0097 }
0098
0099 regs->pc = gdb_regs[GDB_PC];
0100 regs->npc = gdb_regs[GDB_NPC];
0101 regs->y = gdb_regs[GDB_Y];
0102
0103 win = (struct reg_window32 *) regs->u_regs[UREG_FP];
0104 for (i = 0; i < 8; i++)
0105 win->locals[i] = gdb_regs[GDB_L0 + i];
0106 for (i = 0; i < 8; i++)
0107 win->ins[i] = gdb_regs[GDB_I0 + i];
0108 }
0109
0110 int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
0111 char *remcomInBuffer, char *remcomOutBuffer,
0112 struct pt_regs *linux_regs)
0113 {
0114 unsigned long addr;
0115 char *ptr;
0116
0117 switch (remcomInBuffer[0]) {
0118 case 'c':
0119
0120 ptr = &remcomInBuffer[1];
0121 if (kgdb_hex2long(&ptr, &addr)) {
0122 linux_regs->pc = addr;
0123 linux_regs->npc = addr + 4;
0124 }
0125 fallthrough;
0126
0127 case 'D':
0128 case 'k':
0129 if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) {
0130 linux_regs->pc = linux_regs->npc;
0131 linux_regs->npc += 4;
0132 }
0133 return 0;
0134 }
0135 return -1;
0136 }
0137
0138 asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
0139 {
0140 unsigned long flags;
0141
0142 if (user_mode(regs)) {
0143 do_hw_interrupt(regs, trap_level);
0144 return;
0145 }
0146
0147 flushw_all();
0148
0149 local_irq_save(flags);
0150 kgdb_handle_exception(trap_level, SIGTRAP, 0, regs);
0151 local_irq_restore(flags);
0152 }
0153
0154 int kgdb_arch_init(void)
0155 {
0156 return 0;
0157 }
0158
0159 void kgdb_arch_exit(void)
0160 {
0161 }
0162
0163 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
0164 {
0165 regs->pc = ip;
0166 regs->npc = regs->pc + 4;
0167 }
0168
0169 const struct kgdb_arch arch_kgdb_ops = {
0170
0171 .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
0172 };