2 * Originally written by Glenn Engel, Lake Stevens Instrument Division
4 * Contributed by HP Systems
6 * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
7 * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
9 * Copyright (C) 1995 Andreas Busse
11 * Copyright (C) 2003 MontaVista Software Inc.
12 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
14 * Copyright (C) 2004-2005 MontaVista Software Inc.
15 * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
17 * Copyright (C) 2007-2008 Wind River Systems, Inc.
18 * Author/Maintainer: Jason Wessel, jason.wessel@windriver.com
20 * This file is licensed under the terms of the GNU General Public License
21 * version 2. This program is licensed "as is" without any warranty of any
22 * kind, whether express or implied.
25 #include <linux/ptrace.h> /* for linux pt_regs struct */
26 #include <linux/kgdb.h>
27 #include <linux/kdebug.h>
28 #include <linux/sched.h>
29 #include <linux/smp.h>
32 #include <asm/cacheflush.h>
33 #include <asm/processor.h>
34 #include <asm/sigcontext.h>
36 static struct hard_trap_info
{
37 unsigned char tt
; /* Trap type code for MIPS R3xxx and R4xxx */
38 unsigned char signo
; /* Signal that we map this trap into */
39 } hard_trap_info
[] = {
40 { 6, SIGBUS
}, /* instruction bus error */
41 { 7, SIGBUS
}, /* data bus error */
42 { 9, SIGTRAP
}, /* break */
43 /* { 11, SIGILL }, */ /* CPU unusable */
44 { 12, SIGFPE
}, /* overflow */
45 { 13, SIGTRAP
}, /* trap */
46 { 14, SIGSEGV
}, /* virtual instruction cache coherency */
47 { 15, SIGFPE
}, /* floating point exception */
48 { 23, SIGSEGV
}, /* watch */
49 { 31, SIGSEGV
}, /* virtual data cache coherency */
50 { 0, 0} /* Must be last */
53 void arch_kgdb_breakpoint(void)
56 ".globl breakinst\n\t"
59 "breakinst:\tbreak\n\t"
64 static void kgdb_call_nmi_hook(void *ignored
)
66 kgdb_nmicallback(raw_smp_processor_id(), NULL
);
69 void kgdb_roundup_cpus(unsigned long flags
)
72 smp_call_function(kgdb_call_nmi_hook
, NULL
, 0);
76 static int compute_signal(int tt
)
78 struct hard_trap_info
*ht
;
80 for (ht
= hard_trap_info
; ht
->tt
&& ht
->signo
; ht
++)
84 return SIGHUP
; /* default for things we don't know about */
87 void pt_regs_to_gdb_regs(unsigned long *gdb_regs
, struct pt_regs
*regs
)
91 #if (KGDB_GDB_REG_SIZE == 32)
92 u32
*ptr
= (u32
*)gdb_regs
;
94 u64
*ptr
= (u64
*)gdb_regs
;
97 for (reg
= 0; reg
< 32; reg
++)
98 *(ptr
++) = regs
->regs
[reg
];
100 *(ptr
++) = regs
->cp0_status
;
103 *(ptr
++) = regs
->cp0_badvaddr
;
104 *(ptr
++) = regs
->cp0_cause
;
105 *(ptr
++) = regs
->cp0_epc
;
108 if (!(current
&& (regs
->cp0_status
& ST0_CU1
)))
112 for (reg
= 0; reg
< 32; reg
++)
113 *(ptr
++) = current
->thread
.fpu
.fpr
[reg
];
116 void gdb_regs_to_pt_regs(unsigned long *gdb_regs
, struct pt_regs
*regs
)
120 #if (KGDB_GDB_REG_SIZE == 32)
121 const u32
*ptr
= (u32
*)gdb_regs
;
123 const u64
*ptr
= (u64
*)gdb_regs
;
126 for (reg
= 0; reg
< 32; reg
++)
127 regs
->regs
[reg
] = *(ptr
++);
129 regs
->cp0_status
= *(ptr
++);
132 regs
->cp0_badvaddr
= *(ptr
++);
133 regs
->cp0_cause
= *(ptr
++);
134 regs
->cp0_epc
= *(ptr
++);
136 /* FP REGS from current */
137 if (!(current
&& (regs
->cp0_status
& ST0_CU1
)))
140 for (reg
= 0; reg
< 32; reg
++)
141 current
->thread
.fpu
.fpr
[reg
] = *(ptr
++);
146 * Similar to regs_to_gdb_regs() except that process is sleeping and so
147 * we may not be able to get all the info.
149 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs
, struct task_struct
*p
)
152 struct thread_info
*ti
= task_thread_info(p
);
153 unsigned long ksp
= (unsigned long)ti
+ THREAD_SIZE
- 32;
154 struct pt_regs
*regs
= (struct pt_regs
*)ksp
- 1;
155 #if (KGDB_GDB_REG_SIZE == 32)
156 u32
*ptr
= (u32
*)gdb_regs
;
158 u64
*ptr
= (u64
*)gdb_regs
;
161 for (reg
= 0; reg
< 16; reg
++)
162 *(ptr
++) = regs
->regs
[reg
];
165 for (reg
= 16; reg
< 24; reg
++)
166 *(ptr
++) = regs
->regs
[reg
];
168 for (reg
= 24; reg
< 28; reg
++)
172 for (reg
= 28; reg
< 32; reg
++)
173 *(ptr
++) = regs
->regs
[reg
];
175 *(ptr
++) = regs
->cp0_status
;
178 *(ptr
++) = regs
->cp0_badvaddr
;
179 *(ptr
++) = regs
->cp0_cause
;
180 *(ptr
++) = regs
->cp0_epc
;
184 * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
185 * then try to fall into the debugger
187 static int kgdb_mips_notify(struct notifier_block
*self
, unsigned long cmd
,
190 struct die_args
*args
= (struct die_args
*)ptr
;
191 struct pt_regs
*regs
= args
->regs
;
192 int trap
= (regs
->cp0_cause
& 0x7c) >> 2;
194 /* Userpace events, ignore. */
198 if (atomic_read(&kgdb_active
) != -1)
199 kgdb_nmicallback(smp_processor_id(), regs
);
201 if (kgdb_handle_exception(trap
, compute_signal(trap
), 0, regs
))
204 if (atomic_read(&kgdb_setting_breakpoint
))
205 if ((trap
== 9) && (regs
->cp0_epc
== (unsigned long)breakinst
))
208 /* In SMP mode, __flush_cache_all does IPI */
215 static struct notifier_block kgdb_notifier
= {
216 .notifier_call
= kgdb_mips_notify
,
220 * Handle the 's' and 'c' commands
222 int kgdb_arch_handle_exception(int vector
, int signo
, int err_code
,
223 char *remcom_in_buffer
, char *remcom_out_buffer
,
224 struct pt_regs
*regs
)
227 unsigned long address
;
228 int cpu
= smp_processor_id();
230 switch (remcom_in_buffer
[0]) {
233 /* handle the optional parameter */
234 ptr
= &remcom_in_buffer
[1];
235 if (kgdb_hex2long(&ptr
, &address
))
236 regs
->cp0_epc
= address
;
238 atomic_set(&kgdb_cpu_doing_single_step
, -1);
239 if (remcom_in_buffer
[0] == 's')
240 atomic_set(&kgdb_cpu_doing_single_step
, cpu
);
248 struct kgdb_arch arch_kgdb_ops
;
251 * We use kgdb_early_setup so that functions we need to call now don't
252 * cause trouble when called again later.
254 int kgdb_arch_init(void)
256 union mips_instruction insn
= {
262 memcpy(arch_kgdb_ops
.gdb_bpt_instr
, insn
.byte
, BREAK_INSTR_SIZE
);
264 register_die_notifier(&kgdb_notifier
);
270 * kgdb_arch_exit - Perform any architecture specific uninitalization.
272 * This function will handle the uninitalization of any architecture
273 * specific callbacks, for dynamic registration and unregistration.
275 void kgdb_arch_exit(void)
277 unregister_die_notifier(&kgdb_notifier
);