]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - arch/h8300/kernel/kgdb.c
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue
[mirror_ubuntu-hirsute-kernel.git] / arch / h8300 / kernel / kgdb.c
CommitLineData
96ff2d70
YS
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
16struct 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
35char *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
59int 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
79asmlinkage 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
89void 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
96void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
97{
98 regs->pc = pc;
99}
100
101int 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
122int kgdb_arch_init(void)
123{
124 return 0;
125}
126
127void kgdb_arch_exit(void)
128{
129 /* Nothing to do */
130}
131
cc028297 132const struct kgdb_arch arch_kgdb_ops = {
96ff2d70
YS
133 /* Breakpoint instruction: trapa #2 */
134 .gdb_bpt_instr = { 0x57, 0x20 },
135};