1 /*
2  * H8/300 KGDB support
3  *
4  * Copyright (C) 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  */
10 
11 #include <linux/ptrace.h>
12 #include <linux/kgdb.h>
13 #include <linux/kdebug.h>
14 #include <linux/io.h>
15 
16 struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
17 	{ "er0", GDB_SIZEOF_REG, offsetof(struct pt_regs, er0) },
18 	{ "er1", GDB_SIZEOF_REG, offsetof(struct pt_regs, er1) },
19 	{ "er2", GDB_SIZEOF_REG, offsetof(struct pt_regs, er2) },
20 	{ "er3", GDB_SIZEOF_REG, offsetof(struct pt_regs, er3) },
21 	{ "er4", GDB_SIZEOF_REG, offsetof(struct pt_regs, er4) },
22 	{ "er5", GDB_SIZEOF_REG, offsetof(struct pt_regs, er5) },
23 	{ "er6", GDB_SIZEOF_REG, offsetof(struct pt_regs, er6) },
24 	{ "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) },
25 	{ "ccr", GDB_SIZEOF_REG, offsetof(struct pt_regs, ccr) },
26 	{ "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, pc) },
27 	{ "cycles", GDB_SIZEOF_REG, -1 },
28 #if defined(CONFIG_CPU_H8S)
29 	{ "exr", GDB_SIZEOF_REG, offsetof(struct pt_regs, exr) },
30 #endif
31 	{ "tick", GDB_SIZEOF_REG, -1 },
32 	{ "inst", GDB_SIZEOF_REG, -1 },
33 };
34 
dbg_get_reg(int regno,void * mem,struct pt_regs * regs)35 char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
36 {
37 	if (regno >= DBG_MAX_REG_NUM || regno < 0)
38 		return NULL;
39 
40 	switch (regno) {
41 	case GDB_CCR:
42 #if defined(CONFIG_CPU_H8S)
43 	case GDB_EXR:
44 #endif
45 		*(u32 *)mem = *(u16 *)((void *)regs +
46 				       dbg_reg_def[regno].offset);
47 		break;
48 	default:
49 		if (dbg_reg_def[regno].offset >= 0)
50 			memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
51 			       dbg_reg_def[regno].size);
52 		else
53 			memset(mem, 0, dbg_reg_def[regno].size);
54 		break;
55 	}
56 	return dbg_reg_def[regno].name;
57 }
58 
dbg_set_reg(int regno,void * mem,struct pt_regs * regs)59 int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
60 {
61 	if (regno >= DBG_MAX_REG_NUM || regno < 0)
62 		return -EINVAL;
63 
64 	switch (regno) {
65 	case GDB_CCR:
66 #if defined(CONFIG_CPU_H8S)
67 	case GDB_EXR:
68 #endif
69 		*(u16 *)((void *)regs +
70 			 dbg_reg_def[regno].offset) = *(u32 *)mem;
71 		break;
72 	default:
73 		memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
74 		       dbg_reg_def[regno].size);
75 	}
76 	return 0;
77 }
78 
h8300_kgdb_trap(struct pt_regs * regs)79 asmlinkage void h8300_kgdb_trap(struct pt_regs *regs)
80 {
81 	regs->pc &= 0x00ffffff;
82 	if (kgdb_handle_exception(10, SIGTRAP, 0, regs))
83 		return;
84 	if (*(u16 *)(regs->pc) == *(u16 *)&arch_kgdb_ops.gdb_bpt_instr)
85 		regs->pc += BREAK_INSTR_SIZE;
86 	regs->pc |= regs->ccr << 24;
87 }
88 
sleeping_thread_to_gdb_regs(unsigned long * gdb_regs,struct task_struct * p)89 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
90 {
91 	memset((char *)gdb_regs, 0, NUMREGBYTES);
92 	gdb_regs[GDB_SP] = p->thread.ksp;
93 	gdb_regs[GDB_PC] = KSTK_EIP(p);
94 }
95 
kgdb_arch_set_pc(struct pt_regs * regs,unsigned long pc)96 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
97 {
98 	regs->pc = pc;
99 }
100 
kgdb_arch_handle_exception(int vector,int signo,int err_code,char * remcom_in_buffer,char * remcom_out_buffer,struct pt_regs * regs)101 int kgdb_arch_handle_exception(int vector, int signo, int err_code,
102 				char *remcom_in_buffer, char *remcom_out_buffer,
103 				struct pt_regs *regs)
104 {
105 	char *ptr;
106 	unsigned long addr;
107 
108 	switch (remcom_in_buffer[0]) {
109 	case 's':
110 	case 'c':
111 		/* handle the optional parameters */
112 		ptr = &remcom_in_buffer[1];
113 		if (kgdb_hex2long(&ptr, &addr))
114 			regs->pc = addr;
115 
116 		return 0;
117 	}
118 
119 	return -1; /* this means that we do not want to exit from the handler */
120 }
121 
kgdb_arch_init(void)122 int kgdb_arch_init(void)
123 {
124 	return 0;
125 }
126 
kgdb_arch_exit(void)127 void kgdb_arch_exit(void)
128 {
129 	/* Nothing to do */
130 }
131 
132 const struct kgdb_arch arch_kgdb_ops = {
133 	/* Breakpoint instruction: trapa #2 */
134 	.gdb_bpt_instr = { 0x57, 0x20 },
135 };
136