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