aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/kgdb.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/x86/kernel/kgdb.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'arch/x86/kernel/kgdb.c')
-rw-r--r--arch/x86/kernel/kgdb.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 852b81967a37..5f9ecff328b5 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -48,6 +48,7 @@
48#include <asm/apicdef.h> 48#include <asm/apicdef.h>
49#include <asm/system.h> 49#include <asm/system.h>
50#include <asm/apic.h> 50#include <asm/apic.h>
51#include <asm/nmi.h>
51 52
52struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = 53struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
53{ 54{
@@ -120,8 +121,8 @@ char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
120 memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, 121 memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
121 dbg_reg_def[regno].size); 122 dbg_reg_def[regno].size);
122 123
123 switch (regno) {
124#ifdef CONFIG_X86_32 124#ifdef CONFIG_X86_32
125 switch (regno) {
125 case GDB_SS: 126 case GDB_SS:
126 if (!user_mode_vm(regs)) 127 if (!user_mode_vm(regs))
127 *(unsigned long *)mem = __KERNEL_DS; 128 *(unsigned long *)mem = __KERNEL_DS;
@@ -134,8 +135,8 @@ char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
134 case GDB_FS: 135 case GDB_FS:
135 *(unsigned long *)mem = 0xFFFF; 136 *(unsigned long *)mem = 0xFFFF;
136 break; 137 break;
137#endif
138 } 138 }
139#endif
139 return dbg_reg_def[regno].name; 140 return dbg_reg_def[regno].name;
140} 141}
141 142
@@ -277,7 +278,7 @@ static int hw_break_release_slot(int breakno)
277 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); 278 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
278 if (dbg_release_bp_slot(*pevent)) 279 if (dbg_release_bp_slot(*pevent))
279 /* 280 /*
280 * The debugger is responisble for handing the retry on 281 * The debugger is responsible for handing the retry on
281 * remove failure. 282 * remove failure.
282 */ 283 */
283 return -1; 284 return -1;
@@ -315,14 +316,18 @@ static void kgdb_remove_all_hw_break(void)
315 if (!breakinfo[i].enabled) 316 if (!breakinfo[i].enabled)
316 continue; 317 continue;
317 bp = *per_cpu_ptr(breakinfo[i].pev, cpu); 318 bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
318 if (bp->attr.disabled == 1) 319 if (!bp->attr.disabled) {
320 arch_uninstall_hw_breakpoint(bp);
321 bp->attr.disabled = 1;
319 continue; 322 continue;
323 }
320 if (dbg_is_early) 324 if (dbg_is_early)
321 early_dr7 &= ~encode_dr7(i, breakinfo[i].len, 325 early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
322 breakinfo[i].type); 326 breakinfo[i].type);
323 else 327 else if (hw_break_release_slot(i))
324 arch_uninstall_hw_breakpoint(bp); 328 printk(KERN_ERR "KGDB: hw bpt remove failed %lx\n",
325 bp->attr.disabled = 1; 329 breakinfo[i].addr);
330 breakinfo[i].enabled = 0;
326 } 331 }
327} 332}
328 333
@@ -387,7 +392,7 @@ kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
387 * disable hardware debugging while it is processing gdb packets or 392 * disable hardware debugging while it is processing gdb packets or
388 * handling exception. 393 * handling exception.
389 */ 394 */
390void kgdb_disable_hw_debug(struct pt_regs *regs) 395static void kgdb_disable_hw_debug(struct pt_regs *regs)
391{ 396{
392 int i; 397 int i;
393 int cpu = raw_smp_processor_id(); 398 int cpu = raw_smp_processor_id();
@@ -477,8 +482,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
477 raw_smp_processor_id()); 482 raw_smp_processor_id());
478 } 483 }
479 484
480 kgdb_correct_hw_break();
481
482 return 0; 485 return 0;
483 } 486 }
484 487
@@ -523,10 +526,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
523 } 526 }
524 return NOTIFY_DONE; 527 return NOTIFY_DONE;
525 528
526 case DIE_NMI_IPI:
527 /* Just ignore, we will handle the roundup on DIE_NMI. */
528 return NOTIFY_DONE;
529
530 case DIE_NMIUNKNOWN: 529 case DIE_NMIUNKNOWN:
531 if (was_in_debug_nmi[raw_smp_processor_id()]) { 530 if (was_in_debug_nmi[raw_smp_processor_id()]) {
532 was_in_debug_nmi[raw_smp_processor_id()] = 0; 531 was_in_debug_nmi[raw_smp_processor_id()] = 0;
@@ -534,15 +533,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
534 } 533 }
535 return NOTIFY_DONE; 534 return NOTIFY_DONE;
536 535
537 case DIE_NMIWATCHDOG:
538 if (atomic_read(&kgdb_active) != -1) {
539 /* KGDB CPU roundup: */
540 kgdb_nmicallback(raw_smp_processor_id(), regs);
541 return NOTIFY_STOP;
542 }
543 /* Enter debugger: */
544 break;
545
546 case DIE_DEBUG: 536 case DIE_DEBUG:
547 if (atomic_read(&kgdb_cpu_doing_single_step) != -1) { 537 if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
548 if (user_mode(regs)) 538 if (user_mode(regs))
@@ -604,7 +594,7 @@ static struct notifier_block kgdb_notifier = {
604 /* 594 /*
605 * Lowest-prio notifier priority, we want to be notified last: 595 * Lowest-prio notifier priority, we want to be notified last:
606 */ 596 */
607 .priority = -INT_MAX, 597 .priority = NMI_LOCAL_LOW_PRIOR,
608}; 598};
609 599
610/** 600/**
@@ -621,7 +611,12 @@ int kgdb_arch_init(void)
621static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi, 611static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
622 struct perf_sample_data *data, struct pt_regs *regs) 612 struct perf_sample_data *data, struct pt_regs *regs)
623{ 613{
624 kgdb_ll_trap(DIE_DEBUG, "debug", regs, 0, 0, SIGTRAP); 614 struct task_struct *tsk = current;
615 int i;
616
617 for (i = 0; i < 4; i++)
618 if (breakinfo[i].enabled)
619 tsk->thread.debugreg6 |= (DR_TRAP0 << i);
625} 620}
626 621
627void kgdb_arch_late(void) 622void kgdb_arch_late(void)
@@ -644,7 +639,7 @@ void kgdb_arch_late(void)
644 if (breakinfo[i].pev) 639 if (breakinfo[i].pev)
645 continue; 640 continue;
646 breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL); 641 breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
647 if (IS_ERR(breakinfo[i].pev)) { 642 if (IS_ERR((void * __force)breakinfo[i].pev)) {
648 printk(KERN_ERR "kgdb: Could not allocate hw" 643 printk(KERN_ERR "kgdb: Could not allocate hw"
649 "breakpoints\nDisabling the kernel debugger\n"); 644 "breakpoints\nDisabling the kernel debugger\n");
650 breakinfo[i].pev = NULL; 645 breakinfo[i].pev = NULL;
@@ -721,6 +716,7 @@ struct kgdb_arch arch_kgdb_ops = {
721 .flags = KGDB_HW_BREAKPOINT, 716 .flags = KGDB_HW_BREAKPOINT,
722 .set_hw_breakpoint = kgdb_set_hw_break, 717 .set_hw_breakpoint = kgdb_set_hw_break,
723 .remove_hw_breakpoint = kgdb_remove_hw_break, 718 .remove_hw_breakpoint = kgdb_remove_hw_break,
719 .disable_hw_break = kgdb_disable_hw_debug,
724 .remove_all_hw_break = kgdb_remove_all_hw_break, 720 .remove_all_hw_break = kgdb_remove_all_hw_break,
725 .correct_hw_break = kgdb_correct_hw_break, 721 .correct_hw_break = kgdb_correct_hw_break,
726}; 722};