1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * SuperH KGDB support |
4 | * |
5 | * Copyright (C) 2008 - 2012 Paul Mundt |
6 | * |
7 | * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. |
8 | */ |
9 | #include <linux/kgdb.h> |
10 | #include <linux/kdebug.h> |
11 | #include <linux/irq.h> |
12 | #include <linux/io.h> |
13 | #include <linux/sched.h> |
14 | #include <linux/sched/task_stack.h> |
15 | |
16 | #include <asm/cacheflush.h> |
17 | #include <asm/traps.h> |
18 | |
19 | /* Macros for single step instruction identification */ |
20 | #define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) |
21 | #define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00) |
22 | #define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \ |
23 | (((op) & 0x7f ) << 1)) |
24 | #define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00) |
25 | #define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00) |
26 | #define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000) |
27 | #define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ |
28 | (((op) & 0x7ff) << 1)) |
29 | #define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023) |
30 | #define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8) |
31 | #define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000) |
32 | #define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ |
33 | (((op) & 0x7ff) << 1)) |
34 | #define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003) |
35 | #define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf) |
36 | #define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b) |
37 | #define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf) |
38 | #define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b) |
39 | #define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf) |
40 | #define OPCODE_RTS(op) ((op) == 0xb) |
41 | #define OPCODE_RTE(op) ((op) == 0x2b) |
42 | |
43 | #define SR_T_BIT_MASK 0x1 |
44 | #define STEP_OPCODE 0xc33d |
45 | |
46 | /* Calculate the new address for after a step */ |
47 | static short *get_step_address(struct pt_regs *linux_regs) |
48 | { |
49 | insn_size_t op = __raw_readw(addr: linux_regs->pc); |
50 | long addr; |
51 | |
52 | /* BT */ |
53 | if (OPCODE_BT(op)) { |
54 | if (linux_regs->sr & SR_T_BIT_MASK) |
55 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); |
56 | else |
57 | addr = linux_regs->pc + 2; |
58 | } |
59 | |
60 | /* BTS */ |
61 | else if (OPCODE_BTS(op)) { |
62 | if (linux_regs->sr & SR_T_BIT_MASK) |
63 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); |
64 | else |
65 | addr = linux_regs->pc + 4; /* Not in delay slot */ |
66 | } |
67 | |
68 | /* BF */ |
69 | else if (OPCODE_BF(op)) { |
70 | if (!(linux_regs->sr & SR_T_BIT_MASK)) |
71 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); |
72 | else |
73 | addr = linux_regs->pc + 2; |
74 | } |
75 | |
76 | /* BFS */ |
77 | else if (OPCODE_BFS(op)) { |
78 | if (!(linux_regs->sr & SR_T_BIT_MASK)) |
79 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); |
80 | else |
81 | addr = linux_regs->pc + 4; /* Not in delay slot */ |
82 | } |
83 | |
84 | /* BRA */ |
85 | else if (OPCODE_BRA(op)) |
86 | addr = linux_regs->pc + 4 + OPCODE_BRA_DISP(op); |
87 | |
88 | /* BRAF */ |
89 | else if (OPCODE_BRAF(op)) |
90 | addr = linux_regs->pc + 4 |
91 | + linux_regs->regs[OPCODE_BRAF_REG(op)]; |
92 | |
93 | /* BSR */ |
94 | else if (OPCODE_BSR(op)) |
95 | addr = linux_regs->pc + 4 + OPCODE_BSR_DISP(op); |
96 | |
97 | /* BSRF */ |
98 | else if (OPCODE_BSRF(op)) |
99 | addr = linux_regs->pc + 4 |
100 | + linux_regs->regs[OPCODE_BSRF_REG(op)]; |
101 | |
102 | /* JMP */ |
103 | else if (OPCODE_JMP(op)) |
104 | addr = linux_regs->regs[OPCODE_JMP_REG(op)]; |
105 | |
106 | /* JSR */ |
107 | else if (OPCODE_JSR(op)) |
108 | addr = linux_regs->regs[OPCODE_JSR_REG(op)]; |
109 | |
110 | /* RTS */ |
111 | else if (OPCODE_RTS(op)) |
112 | addr = linux_regs->pr; |
113 | |
114 | /* RTE */ |
115 | else if (OPCODE_RTE(op)) |
116 | addr = linux_regs->regs[15]; |
117 | |
118 | /* Other */ |
119 | else |
120 | addr = linux_regs->pc + instruction_size(op); |
121 | |
122 | flush_icache_range(start: addr, end: addr + instruction_size(op)); |
123 | return (short *)addr; |
124 | } |
125 | |
126 | /* |
127 | * Replace the instruction immediately after the current instruction |
128 | * (i.e. next in the expected flow of control) with a trap instruction, |
129 | * so that returning will cause only a single instruction to be executed. |
130 | * Note that this model is slightly broken for instructions with delay |
131 | * slots (e.g. B[TF]S, BSR, BRA etc), where both the branch and the |
132 | * instruction in the delay slot will be executed. |
133 | */ |
134 | |
135 | static unsigned long stepped_address; |
136 | static insn_size_t stepped_opcode; |
137 | |
138 | static void do_single_step(struct pt_regs *linux_regs) |
139 | { |
140 | /* Determine where the target instruction will send us to */ |
141 | unsigned short *addr = get_step_address(linux_regs); |
142 | |
143 | stepped_address = (int)addr; |
144 | |
145 | /* Replace it */ |
146 | stepped_opcode = __raw_readw(addr: (long)addr); |
147 | *addr = STEP_OPCODE; |
148 | |
149 | /* Flush and return */ |
150 | flush_icache_range(start: (long)addr, end: (long)addr + |
151 | instruction_size(stepped_opcode)); |
152 | } |
153 | |
154 | /* Undo a single step */ |
155 | static void undo_single_step(struct pt_regs *linux_regs) |
156 | { |
157 | /* If we have stepped, put back the old instruction */ |
158 | /* Use stepped_address in case we stopped elsewhere */ |
159 | if (stepped_opcode != 0) { |
160 | __raw_writew(val: stepped_opcode, addr: stepped_address); |
161 | flush_icache_range(start: stepped_address, end: stepped_address + 2); |
162 | } |
163 | |
164 | stepped_opcode = 0; |
165 | } |
166 | |
167 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { |
168 | { "r0" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[0]) }, |
169 | { "r1" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[1]) }, |
170 | { "r2" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[2]) }, |
171 | { "r3" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[3]) }, |
172 | { "r4" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[4]) }, |
173 | { "r5" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[5]) }, |
174 | { "r6" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[6]) }, |
175 | { "r7" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[7]) }, |
176 | { "r8" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[8]) }, |
177 | { "r9" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[9]) }, |
178 | { "r10" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[10]) }, |
179 | { "r11" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[11]) }, |
180 | { "r12" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[12]) }, |
181 | { "r13" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[13]) }, |
182 | { "r14" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[14]) }, |
183 | { "r15" , GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[15]) }, |
184 | { "pc" , GDB_SIZEOF_REG, offsetof(struct pt_regs, pc) }, |
185 | { "pr" , GDB_SIZEOF_REG, offsetof(struct pt_regs, pr) }, |
186 | { "sr" , GDB_SIZEOF_REG, offsetof(struct pt_regs, sr) }, |
187 | { "gbr" , GDB_SIZEOF_REG, offsetof(struct pt_regs, gbr) }, |
188 | { "mach" , GDB_SIZEOF_REG, offsetof(struct pt_regs, mach) }, |
189 | { "macl" , GDB_SIZEOF_REG, offsetof(struct pt_regs, macl) }, |
190 | { "vbr" , GDB_SIZEOF_REG, -1 }, |
191 | }; |
192 | |
193 | int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) |
194 | { |
195 | if (regno < 0 || regno >= DBG_MAX_REG_NUM) |
196 | return -EINVAL; |
197 | |
198 | if (dbg_reg_def[regno].offset != -1) |
199 | memcpy((void *)regs + dbg_reg_def[regno].offset, mem, |
200 | dbg_reg_def[regno].size); |
201 | |
202 | return 0; |
203 | } |
204 | |
205 | char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) |
206 | { |
207 | if (regno >= DBG_MAX_REG_NUM || regno < 0) |
208 | return NULL; |
209 | |
210 | if (dbg_reg_def[regno].size != -1) |
211 | memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, |
212 | dbg_reg_def[regno].size); |
213 | |
214 | switch (regno) { |
215 | case GDB_VBR: |
216 | __asm__ __volatile__ ("stc vbr, %0" : "=r" (mem)); |
217 | break; |
218 | } |
219 | |
220 | return dbg_reg_def[regno].name; |
221 | } |
222 | |
223 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) |
224 | { |
225 | struct pt_regs *thread_regs = task_pt_regs(p); |
226 | int reg; |
227 | |
228 | /* Initialize to zero */ |
229 | for (reg = 0; reg < DBG_MAX_REG_NUM; reg++) |
230 | gdb_regs[reg] = 0; |
231 | |
232 | /* |
233 | * Copy out GP regs 8 to 14. |
234 | * |
235 | * switch_to() relies on SR.RB toggling, so regs 0->7 are banked |
236 | * and need privileged instructions to get to. The r15 value we |
237 | * fetch from the thread info directly. |
238 | */ |
239 | for (reg = GDB_R8; reg < GDB_R15; reg++) |
240 | gdb_regs[reg] = thread_regs->regs[reg]; |
241 | |
242 | gdb_regs[GDB_R15] = p->thread.sp; |
243 | gdb_regs[GDB_PC] = p->thread.pc; |
244 | |
245 | /* |
246 | * Additional registers we have context for |
247 | */ |
248 | gdb_regs[GDB_PR] = thread_regs->pr; |
249 | gdb_regs[GDB_GBR] = thread_regs->gbr; |
250 | } |
251 | |
252 | int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, |
253 | char *remcomInBuffer, char *remcomOutBuffer, |
254 | struct pt_regs *linux_regs) |
255 | { |
256 | unsigned long addr; |
257 | char *ptr; |
258 | |
259 | /* Undo any stepping we may have done */ |
260 | undo_single_step(linux_regs); |
261 | |
262 | switch (remcomInBuffer[0]) { |
263 | case 'c': |
264 | case 's': |
265 | /* try to read optional parameter, pc unchanged if no parm */ |
266 | ptr = &remcomInBuffer[1]; |
267 | if (kgdb_hex2long(ptr: &ptr, long_val: &addr)) |
268 | linux_regs->pc = addr; |
269 | fallthrough; |
270 | case 'D': |
271 | case 'k': |
272 | atomic_set(v: &kgdb_cpu_doing_single_step, i: -1); |
273 | |
274 | if (remcomInBuffer[0] == 's') { |
275 | do_single_step(linux_regs); |
276 | kgdb_single_step = 1; |
277 | |
278 | atomic_set(v: &kgdb_cpu_doing_single_step, |
279 | raw_smp_processor_id()); |
280 | } |
281 | |
282 | return 0; |
283 | } |
284 | |
285 | /* this means that we do not want to exit from the handler: */ |
286 | return -1; |
287 | } |
288 | |
289 | unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs) |
290 | { |
291 | if (exception == 60) |
292 | return instruction_pointer(regs) - 2; |
293 | return instruction_pointer(regs); |
294 | } |
295 | |
296 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) |
297 | { |
298 | regs->pc = ip; |
299 | } |
300 | |
301 | /* |
302 | * The primary entry points for the kgdb debug trap table entries. |
303 | */ |
304 | BUILD_TRAP_HANDLER(singlestep) |
305 | { |
306 | unsigned long flags; |
307 | TRAP_HANDLER_DECL; |
308 | |
309 | local_irq_save(flags); |
310 | regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); |
311 | kgdb_handle_exception(0, SIGTRAP, 0, regs); |
312 | local_irq_restore(flags); |
313 | } |
314 | |
315 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) |
316 | { |
317 | int ret; |
318 | |
319 | switch (cmd) { |
320 | case DIE_BREAKPOINT: |
321 | /* |
322 | * This means a user thread is single stepping |
323 | * a system call which should be ignored |
324 | */ |
325 | if (test_thread_flag(TIF_SINGLESTEP)) |
326 | return NOTIFY_DONE; |
327 | |
328 | ret = kgdb_handle_exception(ex_vector: args->trapnr & 0xff, signo: args->signr, |
329 | err_code: args->err, regs: args->regs); |
330 | if (ret) |
331 | return NOTIFY_DONE; |
332 | |
333 | break; |
334 | } |
335 | |
336 | return NOTIFY_STOP; |
337 | } |
338 | |
339 | static int |
340 | kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) |
341 | { |
342 | unsigned long flags; |
343 | int ret; |
344 | |
345 | local_irq_save(flags); |
346 | ret = __kgdb_notify(args: ptr, cmd); |
347 | local_irq_restore(flags); |
348 | |
349 | return ret; |
350 | } |
351 | |
352 | static struct notifier_block kgdb_notifier = { |
353 | .notifier_call = kgdb_notify, |
354 | |
355 | /* |
356 | * Lowest-prio notifier priority, we want to be notified last: |
357 | */ |
358 | .priority = -INT_MAX, |
359 | }; |
360 | |
361 | int kgdb_arch_init(void) |
362 | { |
363 | return register_die_notifier(nb: &kgdb_notifier); |
364 | } |
365 | |
366 | void kgdb_arch_exit(void) |
367 | { |
368 | unregister_die_notifier(nb: &kgdb_notifier); |
369 | } |
370 | |
371 | const struct kgdb_arch arch_kgdb_ops = { |
372 | /* Breakpoint instruction: trapa #0x3c */ |
373 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
374 | .gdb_bpt_instr = { 0x3c, 0xc3 }, |
375 | #else |
376 | .gdb_bpt_instr = { 0xc3, 0x3c }, |
377 | #endif |
378 | }; |
379 | |