diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/x86/kernel/kgdb.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 48 |
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 | ||
52 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | 53 | struct 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 | */ |
390 | void kgdb_disable_hw_debug(struct pt_regs *regs) | 395 | static 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) | |||
621 | static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi, | 611 | static 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 | ||
627 | void kgdb_arch_late(void) | 622 | void 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 | }; |