12d5973cbSMichal Simek /*
22d5973cbSMichal Simek * Microblaze KGDB support
32d5973cbSMichal Simek *
42d5973cbSMichal Simek * This file is subject to the terms and conditions of the GNU General Public
52d5973cbSMichal Simek * License. See the file "COPYING" in the main directory of this archive
62d5973cbSMichal Simek * for more details.
72d5973cbSMichal Simek */
82d5973cbSMichal Simek
92d5973cbSMichal Simek #include <linux/kgdb.h>
102d5973cbSMichal Simek #include <linux/kdebug.h>
112d5973cbSMichal Simek #include <linux/irq.h>
122d5973cbSMichal Simek #include <linux/io.h>
132d5973cbSMichal Simek #include <asm/cacheflush.h>
142d5973cbSMichal Simek #include <asm/asm-offsets.h>
15f396a4d2SMichal Simek #include <asm/kgdb.h>
162d5973cbSMichal Simek #include <asm/pvr.h>
172d5973cbSMichal Simek
182d5973cbSMichal Simek #define GDB_REG 0
192d5973cbSMichal Simek #define GDB_PC 32
202d5973cbSMichal Simek #define GDB_MSR 33
212d5973cbSMichal Simek #define GDB_EAR 34
222d5973cbSMichal Simek #define GDB_ESR 35
232d5973cbSMichal Simek #define GDB_FSR 36
242d5973cbSMichal Simek #define GDB_BTR 37
252d5973cbSMichal Simek #define GDB_PVR 38
262d5973cbSMichal Simek #define GDB_REDR 50
272d5973cbSMichal Simek #define GDB_RPID 51
282d5973cbSMichal Simek #define GDB_RZPR 52
292d5973cbSMichal Simek #define GDB_RTLBX 53
302d5973cbSMichal Simek #define GDB_RTLBSX 54 /* mfs can't read it */
312d5973cbSMichal Simek #define GDB_RTLBLO 55
322d5973cbSMichal Simek #define GDB_RTLBHI 56
332d5973cbSMichal Simek
34*78b5f52aSJulia Lawall /* keep pvr separately because it is unchangeable */
3555ae2f3bSMichal Simek static struct pvr_s pvr;
362d5973cbSMichal Simek
pt_regs_to_gdb_regs(unsigned long * gdb_regs,struct pt_regs * regs)372d5973cbSMichal Simek void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
382d5973cbSMichal Simek {
39e76fdb32SMichal Simek unsigned int i;
402d5973cbSMichal Simek unsigned long *pt_regb = (unsigned long *)regs;
412d5973cbSMichal Simek int temp;
42e76fdb32SMichal Simek
432d5973cbSMichal Simek /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */
442d5973cbSMichal Simek for (i = 0; i < (sizeof(struct pt_regs) / 4) - 1; i++)
452d5973cbSMichal Simek gdb_regs[i] = pt_regb[i];
462d5973cbSMichal Simek
472d5973cbSMichal Simek /* Branch target register can't be changed */
482d5973cbSMichal Simek __asm__ __volatile__ ("mfs %0, rbtr;" : "=r"(temp) : );
492d5973cbSMichal Simek gdb_regs[GDB_BTR] = temp;
502d5973cbSMichal Simek
512d5973cbSMichal Simek /* pvr part - we have 11 pvr regs */
522d5973cbSMichal Simek for (i = 0; i < sizeof(struct pvr_s)/4; i++)
532d5973cbSMichal Simek gdb_regs[GDB_PVR + i] = pvr.pvr[i];
542d5973cbSMichal Simek
552d5973cbSMichal Simek /* read special registers - can't be changed */
562d5973cbSMichal Simek __asm__ __volatile__ ("mfs %0, redr;" : "=r"(temp) : );
572d5973cbSMichal Simek gdb_regs[GDB_REDR] = temp;
582d5973cbSMichal Simek __asm__ __volatile__ ("mfs %0, rpid;" : "=r"(temp) : );
592d5973cbSMichal Simek gdb_regs[GDB_RPID] = temp;
602d5973cbSMichal Simek __asm__ __volatile__ ("mfs %0, rzpr;" : "=r"(temp) : );
612d5973cbSMichal Simek gdb_regs[GDB_RZPR] = temp;
622d5973cbSMichal Simek __asm__ __volatile__ ("mfs %0, rtlbx;" : "=r"(temp) : );
632d5973cbSMichal Simek gdb_regs[GDB_RTLBX] = temp;
642d5973cbSMichal Simek __asm__ __volatile__ ("mfs %0, rtlblo;" : "=r"(temp) : );
652d5973cbSMichal Simek gdb_regs[GDB_RTLBLO] = temp;
662d5973cbSMichal Simek __asm__ __volatile__ ("mfs %0, rtlbhi;" : "=r"(temp) : );
672d5973cbSMichal Simek gdb_regs[GDB_RTLBHI] = temp;
682d5973cbSMichal Simek }
692d5973cbSMichal Simek
gdb_regs_to_pt_regs(unsigned long * gdb_regs,struct pt_regs * regs)702d5973cbSMichal Simek void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
712d5973cbSMichal Simek {
72e76fdb32SMichal Simek unsigned int i;
732d5973cbSMichal Simek unsigned long *pt_regb = (unsigned long *)regs;
742d5973cbSMichal Simek
752d5973cbSMichal Simek /* pt_regs and gdb_regs have the same 37 values.
762d5973cbSMichal Simek * The rest of gdb_regs are unused and can't be changed.
772d5973cbSMichal Simek * r0 register value can't be changed too. */
782d5973cbSMichal Simek for (i = 1; i < (sizeof(struct pt_regs) / 4) - 1; i++)
792d5973cbSMichal Simek pt_regb[i] = gdb_regs[i];
802d5973cbSMichal Simek }
812d5973cbSMichal Simek
microblaze_kgdb_break(struct pt_regs * regs)82f396a4d2SMichal Simek asmlinkage void microblaze_kgdb_break(struct pt_regs *regs)
832d5973cbSMichal Simek {
842d5973cbSMichal Simek if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0)
85f859f0a2SMichal Simek return;
862d5973cbSMichal Simek
872d5973cbSMichal Simek /* Jump over the first arch_kgdb_breakpoint which is barrier to
882d5973cbSMichal Simek * get kgdb work. The same solution is used for powerpc */
892d5973cbSMichal Simek if (*(u32 *) (regs->pc) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
902d5973cbSMichal Simek regs->pc += BREAK_INSTR_SIZE;
912d5973cbSMichal Simek }
922d5973cbSMichal Simek
932d5973cbSMichal Simek /* untested */
sleeping_thread_to_gdb_regs(unsigned long * gdb_regs,struct task_struct * p)942d5973cbSMichal Simek void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
952d5973cbSMichal Simek {
96e76fdb32SMichal Simek unsigned int i;
972d5973cbSMichal Simek unsigned long *pt_regb = (unsigned long *)(p->thread.regs);
982d5973cbSMichal Simek
992d5973cbSMichal Simek /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */
1002d5973cbSMichal Simek for (i = 0; i < (sizeof(struct pt_regs) / 4) - 1; i++)
1012d5973cbSMichal Simek gdb_regs[i] = pt_regb[i];
1022d5973cbSMichal Simek
1032d5973cbSMichal Simek /* pvr part - we have 11 pvr regs */
1042d5973cbSMichal Simek for (i = 0; i < sizeof(struct pvr_s)/4; i++)
1052d5973cbSMichal Simek gdb_regs[GDB_PVR + i] = pvr.pvr[i];
1062d5973cbSMichal Simek }
1072d5973cbSMichal Simek
kgdb_arch_set_pc(struct pt_regs * regs,unsigned long ip)1082d5973cbSMichal Simek void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
1092d5973cbSMichal Simek {
1102d5973cbSMichal Simek regs->pc = ip;
1112d5973cbSMichal Simek }
1122d5973cbSMichal Simek
kgdb_arch_handle_exception(int vector,int signo,int err_code,char * remcom_in_buffer,char * remcom_out_buffer,struct pt_regs * regs)1132d5973cbSMichal Simek int kgdb_arch_handle_exception(int vector, int signo, int err_code,
1142d5973cbSMichal Simek char *remcom_in_buffer, char *remcom_out_buffer,
1152d5973cbSMichal Simek struct pt_regs *regs)
1162d5973cbSMichal Simek {
1172d5973cbSMichal Simek char *ptr;
1182d5973cbSMichal Simek unsigned long address;
1192d5973cbSMichal Simek
1202d5973cbSMichal Simek switch (remcom_in_buffer[0]) {
1212d5973cbSMichal Simek case 'c':
1222d5973cbSMichal Simek /* handle the optional parameter */
1232d5973cbSMichal Simek ptr = &remcom_in_buffer[1];
1242d5973cbSMichal Simek if (kgdb_hex2long(&ptr, &address))
1252d5973cbSMichal Simek regs->pc = address;
1262d5973cbSMichal Simek
1272d5973cbSMichal Simek return 0;
1282d5973cbSMichal Simek }
1292d5973cbSMichal Simek return -1; /* this means that we do not want to exit from the handler */
1302d5973cbSMichal Simek }
1312d5973cbSMichal Simek
kgdb_arch_init(void)1322d5973cbSMichal Simek int kgdb_arch_init(void)
1332d5973cbSMichal Simek {
1342d5973cbSMichal Simek get_pvr(&pvr); /* Fill PVR structure */
1352d5973cbSMichal Simek return 0;
1362d5973cbSMichal Simek }
1372d5973cbSMichal Simek
kgdb_arch_exit(void)1382d5973cbSMichal Simek void kgdb_arch_exit(void)
1392d5973cbSMichal Simek {
1402d5973cbSMichal Simek /* Nothing to do */
1412d5973cbSMichal Simek }
1422d5973cbSMichal Simek
1432d5973cbSMichal Simek /*
1442d5973cbSMichal Simek * Global data
1452d5973cbSMichal Simek */
146cc028297SChristophe Leroy const struct kgdb_arch arch_kgdb_ops = {
147e4f29092SMichal Simek #ifdef __MICROBLAZEEL__
148e4f29092SMichal Simek .gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */
149e4f29092SMichal Simek #else
1502d5973cbSMichal Simek .gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */
151e4f29092SMichal Simek #endif
1522d5973cbSMichal Simek };
153