aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/debug/debug_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/debug/debug_core.c')
-rw-r--r--kernel/debug/debug_core.c87
1 files changed, 57 insertions, 30 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 0d7c08784efb..0557f24c6bca 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -41,6 +41,7 @@
41#include <linux/delay.h> 41#include <linux/delay.h>
42#include <linux/sched.h> 42#include <linux/sched.h>
43#include <linux/sysrq.h> 43#include <linux/sysrq.h>
44#include <linux/reboot.h>
44#include <linux/init.h> 45#include <linux/init.h>
45#include <linux/kgdb.h> 46#include <linux/kgdb.h>
46#include <linux/kdb.h> 47#include <linux/kdb.h>
@@ -52,7 +53,6 @@
52#include <asm/cacheflush.h> 53#include <asm/cacheflush.h>
53#include <asm/byteorder.h> 54#include <asm/byteorder.h>
54#include <linux/atomic.h> 55#include <linux/atomic.h>
55#include <asm/system.h>
56 56
57#include "debug_core.h" 57#include "debug_core.h"
58 58
@@ -75,6 +75,8 @@ static int exception_level;
75struct kgdb_io *dbg_io_ops; 75struct kgdb_io *dbg_io_ops;
76static DEFINE_SPINLOCK(kgdb_registration_lock); 76static DEFINE_SPINLOCK(kgdb_registration_lock);
77 77
78/* Action for the reboot notifiter, a global allow kdb to change it */
79static int kgdbreboot;
78/* kgdb console driver is loaded */ 80/* kgdb console driver is loaded */
79static int kgdb_con_registered; 81static int kgdb_con_registered;
80/* determine if kgdb console output should be used */ 82/* determine if kgdb console output should be used */
@@ -96,6 +98,7 @@ static int __init opt_kgdb_con(char *str)
96early_param("kgdbcon", opt_kgdb_con); 98early_param("kgdbcon", opt_kgdb_con);
97 99
98module_param(kgdb_use_con, int, 0644); 100module_param(kgdb_use_con, int, 0644);
101module_param(kgdbreboot, int, 0644);
99 102
100/* 103/*
101 * Holds information about breakpoints in a kernel. These breakpoints are 104 * Holds information about breakpoints in a kernel. These breakpoints are
@@ -157,37 +160,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup);
157 * Weak aliases for breakpoint management, 160 * Weak aliases for breakpoint management,
158 * can be overriden by architectures when needed: 161 * can be overriden by architectures when needed:
159 */ 162 */
160int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) 163int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
161{ 164{
162 int err; 165 int err;
163 166
164 err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE); 167 err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
168 BREAK_INSTR_SIZE);
165 if (err) 169 if (err)
166 return err; 170 return err;
167 171 err = probe_kernel_write((char *)bpt->bpt_addr,
168 return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, 172 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
169 BREAK_INSTR_SIZE); 173 return err;
170} 174}
171 175
172int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) 176int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
173{ 177{
174 return probe_kernel_write((char *)addr, 178 return probe_kernel_write((char *)bpt->bpt_addr,
175 (char *)bundle, BREAK_INSTR_SIZE); 179 (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
176} 180}
177 181
178int __weak kgdb_validate_break_address(unsigned long addr) 182int __weak kgdb_validate_break_address(unsigned long addr)
179{ 183{
180 char tmp_variable[BREAK_INSTR_SIZE]; 184 struct kgdb_bkpt tmp;
181 int err; 185 int err;
182 /* Validate setting the breakpoint and then removing it. In the 186 /* Validate setting the breakpoint and then removing it. If the
183 * remove fails, the kernel needs to emit a bad message because we 187 * remove fails, the kernel needs to emit a bad message because we
184 * are deep trouble not being able to put things back the way we 188 * are deep trouble not being able to put things back the way we
185 * found them. 189 * found them.
186 */ 190 */
187 err = kgdb_arch_set_breakpoint(addr, tmp_variable); 191 tmp.bpt_addr = addr;
192 err = kgdb_arch_set_breakpoint(&tmp);
188 if (err) 193 if (err)
189 return err; 194 return err;
190 err = kgdb_arch_remove_breakpoint(addr, tmp_variable); 195 err = kgdb_arch_remove_breakpoint(&tmp);
191 if (err) 196 if (err)
192 printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " 197 printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
193 "memory destroyed at: %lx", addr); 198 "memory destroyed at: %lx", addr);
@@ -231,7 +236,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
231 */ 236 */
232int dbg_activate_sw_breakpoints(void) 237int dbg_activate_sw_breakpoints(void)
233{ 238{
234 unsigned long addr;
235 int error; 239 int error;
236 int ret = 0; 240 int ret = 0;
237 int i; 241 int i;
@@ -240,16 +244,15 @@ int dbg_activate_sw_breakpoints(void)
240 if (kgdb_break[i].state != BP_SET) 244 if (kgdb_break[i].state != BP_SET)
241 continue; 245 continue;
242 246
243 addr = kgdb_break[i].bpt_addr; 247 error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
244 error = kgdb_arch_set_breakpoint(addr,
245 kgdb_break[i].saved_instr);
246 if (error) { 248 if (error) {
247 ret = error; 249 ret = error;
248 printk(KERN_INFO "KGDB: BP install failed: %lx", addr); 250 printk(KERN_INFO "KGDB: BP install failed: %lx",
251 kgdb_break[i].bpt_addr);
249 continue; 252 continue;
250 } 253 }
251 254
252 kgdb_flush_swbreak_addr(addr); 255 kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
253 kgdb_break[i].state = BP_ACTIVE; 256 kgdb_break[i].state = BP_ACTIVE;
254 } 257 }
255 return ret; 258 return ret;
@@ -298,7 +301,6 @@ int dbg_set_sw_break(unsigned long addr)
298 301
299int dbg_deactivate_sw_breakpoints(void) 302int dbg_deactivate_sw_breakpoints(void)
300{ 303{
301 unsigned long addr;
302 int error; 304 int error;
303 int ret = 0; 305 int ret = 0;
304 int i; 306 int i;
@@ -306,15 +308,14 @@ int dbg_deactivate_sw_breakpoints(void)
306 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { 308 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
307 if (kgdb_break[i].state != BP_ACTIVE) 309 if (kgdb_break[i].state != BP_ACTIVE)
308 continue; 310 continue;
309 addr = kgdb_break[i].bpt_addr; 311 error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
310 error = kgdb_arch_remove_breakpoint(addr,
311 kgdb_break[i].saved_instr);
312 if (error) { 312 if (error) {
313 printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); 313 printk(KERN_INFO "KGDB: BP remove failed: %lx\n",
314 kgdb_break[i].bpt_addr);
314 ret = error; 315 ret = error;
315 } 316 }
316 317
317 kgdb_flush_swbreak_addr(addr); 318 kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
318 kgdb_break[i].state = BP_SET; 319 kgdb_break[i].state = BP_SET;
319 } 320 }
320 return ret; 321 return ret;
@@ -348,7 +349,6 @@ int kgdb_isremovedbreak(unsigned long addr)
348 349
349int dbg_remove_all_break(void) 350int dbg_remove_all_break(void)
350{ 351{
351 unsigned long addr;
352 int error; 352 int error;
353 int i; 353 int i;
354 354
@@ -356,12 +356,10 @@ int dbg_remove_all_break(void)
356 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { 356 for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
357 if (kgdb_break[i].state != BP_ACTIVE) 357 if (kgdb_break[i].state != BP_ACTIVE)
358 goto setundefined; 358 goto setundefined;
359 addr = kgdb_break[i].bpt_addr; 359 error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
360 error = kgdb_arch_remove_breakpoint(addr,
361 kgdb_break[i].saved_instr);
362 if (error) 360 if (error)
363 printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", 361 printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
364 addr); 362 kgdb_break[i].bpt_addr);
365setundefined: 363setundefined:
366 kgdb_break[i].state = BP_UNDEFINED; 364 kgdb_break[i].state = BP_UNDEFINED;
367 } 365 }
@@ -784,6 +782,33 @@ void __init dbg_late_init(void)
784 kdb_init(KDB_INIT_FULL); 782 kdb_init(KDB_INIT_FULL);
785} 783}
786 784
785static int
786dbg_notify_reboot(struct notifier_block *this, unsigned long code, void *x)
787{
788 /*
789 * Take the following action on reboot notify depending on value:
790 * 1 == Enter debugger
791 * 0 == [the default] detatch debug client
792 * -1 == Do nothing... and use this until the board resets
793 */
794 switch (kgdbreboot) {
795 case 1:
796 kgdb_breakpoint();
797 case -1:
798 goto done;
799 }
800 if (!dbg_kdb_mode)
801 gdbstub_exit(code);
802done:
803 return NOTIFY_DONE;
804}
805
806static struct notifier_block dbg_reboot_notifier = {
807 .notifier_call = dbg_notify_reboot,
808 .next = NULL,
809 .priority = INT_MAX,
810};
811
787static void kgdb_register_callbacks(void) 812static void kgdb_register_callbacks(void)
788{ 813{
789 if (!kgdb_io_module_registered) { 814 if (!kgdb_io_module_registered) {
@@ -791,6 +816,7 @@ static void kgdb_register_callbacks(void)
791 kgdb_arch_init(); 816 kgdb_arch_init();
792 if (!dbg_is_early) 817 if (!dbg_is_early)
793 kgdb_arch_late(); 818 kgdb_arch_late();
819 register_reboot_notifier(&dbg_reboot_notifier);
794 atomic_notifier_chain_register(&panic_notifier_list, 820 atomic_notifier_chain_register(&panic_notifier_list,
795 &kgdb_panic_event_nb); 821 &kgdb_panic_event_nb);
796#ifdef CONFIG_MAGIC_SYSRQ 822#ifdef CONFIG_MAGIC_SYSRQ
@@ -812,6 +838,7 @@ static void kgdb_unregister_callbacks(void)
812 */ 838 */
813 if (kgdb_io_module_registered) { 839 if (kgdb_io_module_registered) {
814 kgdb_io_module_registered = 0; 840 kgdb_io_module_registered = 0;
841 unregister_reboot_notifier(&dbg_reboot_notifier);
815 atomic_notifier_chain_unregister(&panic_notifier_list, 842 atomic_notifier_chain_unregister(&panic_notifier_list,
816 &kgdb_panic_event_nb); 843 &kgdb_panic_event_nb);
817 kgdb_arch_exit(); 844 kgdb_arch_exit();