Merge tag 'livepatching-for-5.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel...
[linux/fpc-iii.git] / arch / h8300 / kernel / kgdb.c
blob602e478afbd5800eab9ba03277bf7d4db36336f0
1 /*
2 * H8/300 KGDB support
4 * Copyright (C) 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
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 */
11 #include <linux/ptrace.h>
12 #include <linux/kgdb.h>
13 #include <linux/kdebug.h>
14 #include <linux/io.h>
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 },
35 char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
37 if (regno >= DBG_MAX_REG_NUM || regno < 0)
38 return NULL;
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;
56 return dbg_reg_def[regno].name;
59 int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
61 if (regno >= DBG_MAX_REG_NUM || regno < 0)
62 return -EINVAL;
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);
76 return 0;
79 asmlinkage void h8300_kgdb_trap(struct pt_regs *regs)
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;
89 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
91 memset((char *)gdb_regs, 0, NUMREGBYTES);
92 gdb_regs[GDB_SP] = p->thread.ksp;
93 gdb_regs[GDB_PC] = KSTK_EIP(p);
96 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
98 regs->pc = pc;
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)
105 char *ptr;
106 unsigned long addr;
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;
116 return 0;
119 return -1; /* this means that we do not want to exit from the handler */
122 int kgdb_arch_init(void)
124 return 0;
127 void kgdb_arch_exit(void)
129 /* Nothing to do */
132 const struct kgdb_arch arch_kgdb_ops = {
133 /* Breakpoint instruction: trapa #2 */
134 .gdb_bpt_instr = { 0x57, 0x20 },