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