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