Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * arch/arm/kernel/kgdb.c
4 : : *
5 : : * ARM KGDB support
6 : : *
7 : : * Copyright (c) 2002-2004 MontaVista Software, Inc
8 : : * Copyright (c) 2008 Wind River Systems, Inc.
9 : : *
10 : : * Authors: George Davis <davis_g@mvista.com>
11 : : * Deepak Saxena <dsaxena@plexity.net>
12 : : */
13 : : #include <linux/irq.h>
14 : : #include <linux/kdebug.h>
15 : : #include <linux/kgdb.h>
16 : : #include <linux/uaccess.h>
17 : :
18 : : #include <asm/patch.h>
19 : : #include <asm/traps.h>
20 : :
21 : : struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
22 : : {
23 : : { "r0", 4, offsetof(struct pt_regs, ARM_r0)},
24 : : { "r1", 4, offsetof(struct pt_regs, ARM_r1)},
25 : : { "r2", 4, offsetof(struct pt_regs, ARM_r2)},
26 : : { "r3", 4, offsetof(struct pt_regs, ARM_r3)},
27 : : { "r4", 4, offsetof(struct pt_regs, ARM_r4)},
28 : : { "r5", 4, offsetof(struct pt_regs, ARM_r5)},
29 : : { "r6", 4, offsetof(struct pt_regs, ARM_r6)},
30 : : { "r7", 4, offsetof(struct pt_regs, ARM_r7)},
31 : : { "r8", 4, offsetof(struct pt_regs, ARM_r8)},
32 : : { "r9", 4, offsetof(struct pt_regs, ARM_r9)},
33 : : { "r10", 4, offsetof(struct pt_regs, ARM_r10)},
34 : : { "fp", 4, offsetof(struct pt_regs, ARM_fp)},
35 : : { "ip", 4, offsetof(struct pt_regs, ARM_ip)},
36 : : { "sp", 4, offsetof(struct pt_regs, ARM_sp)},
37 : : { "lr", 4, offsetof(struct pt_regs, ARM_lr)},
38 : : { "pc", 4, offsetof(struct pt_regs, ARM_pc)},
39 : : { "f0", 12, -1 },
40 : : { "f1", 12, -1 },
41 : : { "f2", 12, -1 },
42 : : { "f3", 12, -1 },
43 : : { "f4", 12, -1 },
44 : : { "f5", 12, -1 },
45 : : { "f6", 12, -1 },
46 : : { "f7", 12, -1 },
47 : : { "fps", 4, -1 },
48 : : { "cpsr", 4, offsetof(struct pt_regs, ARM_cpsr)},
49 : : };
50 : :
51 : 0 : char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
52 : : {
53 [ # # ]: 0 : if (regno >= DBG_MAX_REG_NUM || regno < 0)
54 : : return NULL;
55 : :
56 [ # # ]: 0 : if (dbg_reg_def[regno].offset != -1)
57 : 0 : memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
58 : 0 : dbg_reg_def[regno].size);
59 : : else
60 : 0 : memset(mem, 0, dbg_reg_def[regno].size);
61 : 0 : return dbg_reg_def[regno].name;
62 : : }
63 : :
64 : 0 : int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
65 : : {
66 [ # # ]: 0 : if (regno >= DBG_MAX_REG_NUM || regno < 0)
67 : : return -EINVAL;
68 : :
69 [ # # ]: 0 : if (dbg_reg_def[regno].offset != -1)
70 : 0 : memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
71 : 0 : dbg_reg_def[regno].size);
72 : : return 0;
73 : : }
74 : :
75 : : void
76 : 0 : sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
77 : : {
78 : : struct thread_info *ti;
79 : : int regno;
80 : :
81 : : /* Just making sure... */
82 [ # # ]: 0 : if (task == NULL)
83 : 0 : return;
84 : :
85 : : /* Initialize to zero */
86 [ # # ]: 0 : for (regno = 0; regno < GDB_MAX_REGS; regno++)
87 : 0 : gdb_regs[regno] = 0;
88 : :
89 : : /* Otherwise, we have only some registers from switch_to() */
90 : 0 : ti = task_thread_info(task);
91 : 0 : gdb_regs[_R4] = ti->cpu_context.r4;
92 : 0 : gdb_regs[_R5] = ti->cpu_context.r5;
93 : 0 : gdb_regs[_R6] = ti->cpu_context.r6;
94 : 0 : gdb_regs[_R7] = ti->cpu_context.r7;
95 : 0 : gdb_regs[_R8] = ti->cpu_context.r8;
96 : 0 : gdb_regs[_R9] = ti->cpu_context.r9;
97 : 0 : gdb_regs[_R10] = ti->cpu_context.sl;
98 : 0 : gdb_regs[_FP] = ti->cpu_context.fp;
99 : 0 : gdb_regs[_SPT] = ti->cpu_context.sp;
100 : 0 : gdb_regs[_PC] = ti->cpu_context.pc;
101 : : }
102 : :
103 : 0 : void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
104 : : {
105 : 0 : regs->ARM_pc = pc;
106 : 0 : }
107 : :
108 : : static int compiled_break;
109 : :
110 : 0 : int kgdb_arch_handle_exception(int exception_vector, int signo,
111 : : int err_code, char *remcom_in_buffer,
112 : : char *remcom_out_buffer,
113 : : struct pt_regs *linux_regs)
114 : : {
115 : : unsigned long addr;
116 : : char *ptr;
117 : :
118 [ # # ]: 0 : switch (remcom_in_buffer[0]) {
119 : : case 'D':
120 : : case 'k':
121 : : case 'c':
122 : : /*
123 : : * Try to read optional parameter, pc unchanged if no parm.
124 : : * If this was a compiled breakpoint, we need to move
125 : : * to the next instruction or we will just breakpoint
126 : : * over and over again.
127 : : */
128 : 0 : ptr = &remcom_in_buffer[1];
129 [ # # ]: 0 : if (kgdb_hex2long(&ptr, &addr))
130 : 0 : linux_regs->ARM_pc = addr;
131 [ # # ]: 0 : else if (compiled_break == 1)
132 : 0 : linux_regs->ARM_pc += 4;
133 : :
134 : 0 : compiled_break = 0;
135 : :
136 : 0 : return 0;
137 : : }
138 : :
139 : : return -1;
140 : : }
141 : :
142 : 0 : static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
143 : : {
144 : 0 : kgdb_handle_exception(1, SIGTRAP, 0, regs);
145 : :
146 : 0 : return 0;
147 : : }
148 : :
149 : 0 : static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
150 : : {
151 : 0 : compiled_break = 1;
152 : 0 : kgdb_handle_exception(1, SIGTRAP, 0, regs);
153 : :
154 : 0 : return 0;
155 : : }
156 : :
157 : : static struct undef_hook kgdb_brkpt_hook = {
158 : : .instr_mask = 0xffffffff,
159 : : .instr_val = KGDB_BREAKINST,
160 : : .cpsr_mask = MODE_MASK,
161 : : .cpsr_val = SVC_MODE,
162 : : .fn = kgdb_brk_fn
163 : : };
164 : :
165 : : static struct undef_hook kgdb_compiled_brkpt_hook = {
166 : : .instr_mask = 0xffffffff,
167 : : .instr_val = KGDB_COMPILED_BREAK,
168 : : .cpsr_mask = MODE_MASK,
169 : : .cpsr_val = SVC_MODE,
170 : : .fn = kgdb_compiled_brk_fn
171 : : };
172 : :
173 : : static int __kgdb_notify(struct die_args *args, unsigned long cmd)
174 : : {
175 : 0 : struct pt_regs *regs = args->regs;
176 : :
177 [ # # ]: 0 : if (kgdb_handle_exception(1, args->signr, cmd, regs))
178 : : return NOTIFY_DONE;
179 : : return NOTIFY_STOP;
180 : : }
181 : : static int
182 : 0 : kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
183 : : {
184 : : unsigned long flags;
185 : : int ret;
186 : :
187 : 0 : local_irq_save(flags);
188 : : ret = __kgdb_notify(ptr, cmd);
189 [ # # ]: 0 : local_irq_restore(flags);
190 : :
191 : 0 : return ret;
192 : : }
193 : :
194 : : static struct notifier_block kgdb_notifier = {
195 : : .notifier_call = kgdb_notify,
196 : : .priority = -INT_MAX,
197 : : };
198 : :
199 : :
200 : : /**
201 : : * kgdb_arch_init - Perform any architecture specific initalization.
202 : : *
203 : : * This function will handle the initalization of any architecture
204 : : * specific callbacks.
205 : : */
206 : 0 : int kgdb_arch_init(void)
207 : : {
208 : 0 : int ret = register_die_notifier(&kgdb_notifier);
209 : :
210 [ # # ]: 0 : if (ret != 0)
211 : : return ret;
212 : :
213 : 0 : register_undef_hook(&kgdb_brkpt_hook);
214 : 0 : register_undef_hook(&kgdb_compiled_brkpt_hook);
215 : :
216 : 0 : return 0;
217 : : }
218 : :
219 : : /**
220 : : * kgdb_arch_exit - Perform any architecture specific uninitalization.
221 : : *
222 : : * This function will handle the uninitalization of any architecture
223 : : * specific callbacks, for dynamic registration and unregistration.
224 : : */
225 : 0 : void kgdb_arch_exit(void)
226 : : {
227 : 0 : unregister_undef_hook(&kgdb_brkpt_hook);
228 : 0 : unregister_undef_hook(&kgdb_compiled_brkpt_hook);
229 : 0 : unregister_die_notifier(&kgdb_notifier);
230 : 0 : }
231 : :
232 : 0 : int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
233 : : {
234 : : int err;
235 : :
236 : : /* patch_text() only supports int-sized breakpoints */
237 : : BUILD_BUG_ON(sizeof(int) != BREAK_INSTR_SIZE);
238 : :
239 : 0 : err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
240 : : BREAK_INSTR_SIZE);
241 [ # # ]: 0 : if (err)
242 : : return err;
243 : :
244 : : /* Machine is already stopped, so we can use __patch_text() directly */
245 : 0 : __patch_text((void *)bpt->bpt_addr,
246 : : *(unsigned int *)arch_kgdb_ops.gdb_bpt_instr);
247 : :
248 : 0 : return err;
249 : : }
250 : :
251 : 0 : int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
252 : : {
253 : : /* Machine is already stopped, so we can use __patch_text() directly */
254 : 0 : __patch_text((void *)bpt->bpt_addr, *(unsigned int *)bpt->saved_instr);
255 : :
256 : 0 : return 0;
257 : : }
258 : :
259 : : /*
260 : : * Register our undef instruction hooks with ARM undef core.
261 : : * We register a hook specifically looking for the KGB break inst
262 : : * and we handle the normal undef case within the do_undefinstr
263 : : * handler.
264 : : */
265 : : const struct kgdb_arch arch_kgdb_ops = {
266 : : #ifndef __ARMEB__
267 : : .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
268 : : #else /* ! __ARMEB__ */
269 : : .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
270 : : #endif
271 : : };
|