1 /* 2 * Microblaze KGDB support 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file "COPYING" in the main directory of this archive 6 * for more details. 7 */ 8 9 #include <linux/kgdb.h> 10 #include <linux/kdebug.h> 11 #include <linux/irq.h> 12 #include <linux/io.h> 13 #include <asm/cacheflush.h> 14 #include <asm/asm-offsets.h> 15 #include <asm/pvr.h> 16 17 #define GDB_REG 0 18 #define GDB_PC 32 19 #define GDB_MSR 33 20 #define GDB_EAR 34 21 #define GDB_ESR 35 22 #define GDB_FSR 36 23 #define GDB_BTR 37 24 #define GDB_PVR 38 25 #define GDB_REDR 50 26 #define GDB_RPID 51 27 #define GDB_RZPR 52 28 #define GDB_RTLBX 53 29 #define GDB_RTLBSX 54 /* mfs can't read it */ 30 #define GDB_RTLBLO 55 31 #define GDB_RTLBHI 56 32 33 /* keep pvr separately because it is unchangeble */ 34 struct pvr_s pvr; 35 36 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) 37 { 38 int i; 39 unsigned long *pt_regb = (unsigned long *)regs; 40 int temp; 41 /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */ 42 for (i = 0; i < (sizeof(struct pt_regs) / 4) - 1; i++) 43 gdb_regs[i] = pt_regb[i]; 44 45 /* Branch target register can't be changed */ 46 __asm__ __volatile__ ("mfs %0, rbtr;" : "=r"(temp) : ); 47 gdb_regs[GDB_BTR] = temp; 48 49 /* pvr part - we have 11 pvr regs */ 50 for (i = 0; i < sizeof(struct pvr_s)/4; i++) 51 gdb_regs[GDB_PVR + i] = pvr.pvr[i]; 52 53 /* read special registers - can't be changed */ 54 __asm__ __volatile__ ("mfs %0, redr;" : "=r"(temp) : ); 55 gdb_regs[GDB_REDR] = temp; 56 __asm__ __volatile__ ("mfs %0, rpid;" : "=r"(temp) : ); 57 gdb_regs[GDB_RPID] = temp; 58 __asm__ __volatile__ ("mfs %0, rzpr;" : "=r"(temp) : ); 59 gdb_regs[GDB_RZPR] = temp; 60 __asm__ __volatile__ ("mfs %0, rtlbx;" : "=r"(temp) : ); 61 gdb_regs[GDB_RTLBX] = temp; 62 __asm__ __volatile__ ("mfs %0, rtlblo;" : "=r"(temp) : ); 63 gdb_regs[GDB_RTLBLO] = temp; 64 __asm__ __volatile__ ("mfs %0, rtlbhi;" : "=r"(temp) : ); 65 gdb_regs[GDB_RTLBHI] = temp; 66 } 67 68 void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) 69 { 70 int i; 71 unsigned long *pt_regb = (unsigned long *)regs; 72 73 /* pt_regs and gdb_regs have the same 37 values. 74 * The rest of gdb_regs are unused and can't be changed. 75 * r0 register value can't be changed too. */ 76 for (i = 1; i < (sizeof(struct pt_regs) / 4) - 1; i++) 77 pt_regb[i] = gdb_regs[i]; 78 } 79 80 void microblaze_kgdb_break(struct pt_regs *regs) 81 { 82 if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0) 83 return; 84 85 /* Jump over the first arch_kgdb_breakpoint which is barrier to 86 * get kgdb work. The same solution is used for powerpc */ 87 if (*(u32 *) (regs->pc) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) 88 regs->pc += BREAK_INSTR_SIZE; 89 } 90 91 /* untested */ 92 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) 93 { 94 int i; 95 unsigned long *pt_regb = (unsigned long *)(p->thread.regs); 96 97 /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */ 98 for (i = 0; i < (sizeof(struct pt_regs) / 4) - 1; i++) 99 gdb_regs[i] = pt_regb[i]; 100 101 /* pvr part - we have 11 pvr regs */ 102 for (i = 0; i < sizeof(struct pvr_s)/4; i++) 103 gdb_regs[GDB_PVR + i] = pvr.pvr[i]; 104 } 105 106 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) 107 { 108 regs->pc = ip; 109 } 110 111 int kgdb_arch_handle_exception(int vector, int signo, int err_code, 112 char *remcom_in_buffer, char *remcom_out_buffer, 113 struct pt_regs *regs) 114 { 115 char *ptr; 116 unsigned long address; 117 118 switch (remcom_in_buffer[0]) { 119 case 'c': 120 /* handle the optional parameter */ 121 ptr = &remcom_in_buffer[1]; 122 if (kgdb_hex2long(&ptr, &address)) 123 regs->pc = address; 124 125 return 0; 126 } 127 return -1; /* this means that we do not want to exit from the handler */ 128 } 129 130 int kgdb_arch_init(void) 131 { 132 get_pvr(&pvr); /* Fill PVR structure */ 133 return 0; 134 } 135 136 void kgdb_arch_exit(void) 137 { 138 /* Nothing to do */ 139 } 140 141 /* 142 * Global data 143 */ 144 struct kgdb_arch arch_kgdb_ops = { 145 #ifdef __MICROBLAZEEL__ 146 .gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */ 147 #else 148 .gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */ 149 #endif 150 }; 151