aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Vorontsov <anton.vorontsov@linaro.org>2012-09-24 17:27:50 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-26 16:42:25 -0400
commit5a14fead07bcf4e0acc877a8d9e1d1f40a441153 (patch)
tree7fd90cf9cdd0b734f013df6bb86f34fdd80c5732
parentc5dd553b9fd069892c9e2de734f4f604e280fa7a (diff)
kernel/debug: Mask KGDB NMI upon entry
The new arch callback should manage NMIs that usually cause KGDB to enter. That is, not all NMIs should be enabled/disabled, but only those that issue kgdb_handle_exception(). We must mask it as serial-line interrupt can be used as an NMI, so if the original KGDB-entry cause was say a breakpoint, then every input to KDB console will cause KGDB to reenter, which we don't want. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Acked-by: Jason Wessel <jason.wessel@windriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/linux/kgdb.h3
-rw-r--r--kernel/debug/debug_core.c14
2 files changed, 14 insertions, 3 deletions
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index c4d2fc194ede..7800cce284db 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -240,6 +240,7 @@ extern void kgdb_arch_late(void);
240 * hardware breakpoints. 240 * hardware breakpoints.
241 * @correct_hw_break: Allow an architecture to specify how to correct the 241 * @correct_hw_break: Allow an architecture to specify how to correct the
242 * hardware debug registers. 242 * hardware debug registers.
243 * @enable_nmi: Manage NMI-triggered entry to KGDB
243 */ 244 */
244struct kgdb_arch { 245struct kgdb_arch {
245 unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE]; 246 unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE];
@@ -252,6 +253,8 @@ struct kgdb_arch {
252 void (*disable_hw_break)(struct pt_regs *regs); 253 void (*disable_hw_break)(struct pt_regs *regs);
253 void (*remove_all_hw_break)(void); 254 void (*remove_all_hw_break)(void);
254 void (*correct_hw_break)(void); 255 void (*correct_hw_break)(void);
256
257 void (*enable_nmi)(bool on);
255}; 258};
256 259
257/** 260/**
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 0557f24c6bca..17e073c309e6 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -672,6 +672,10 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
672{ 672{
673 struct kgdb_state kgdb_var; 673 struct kgdb_state kgdb_var;
674 struct kgdb_state *ks = &kgdb_var; 674 struct kgdb_state *ks = &kgdb_var;
675 int ret = 0;
676
677 if (arch_kgdb_ops.enable_nmi)
678 arch_kgdb_ops.enable_nmi(0);
675 679
676 ks->cpu = raw_smp_processor_id(); 680 ks->cpu = raw_smp_processor_id();
677 ks->ex_vector = evector; 681 ks->ex_vector = evector;
@@ -681,11 +685,15 @@ kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
681 ks->linux_regs = regs; 685 ks->linux_regs = regs;
682 686
683 if (kgdb_reenter_check(ks)) 687 if (kgdb_reenter_check(ks))
684 return 0; /* Ouch, double exception ! */ 688 goto out; /* Ouch, double exception ! */
685 if (kgdb_info[ks->cpu].enter_kgdb != 0) 689 if (kgdb_info[ks->cpu].enter_kgdb != 0)
686 return 0; 690 goto out;
687 691
688 return kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER); 692 ret = kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER);
693out:
694 if (arch_kgdb_ops.enable_nmi)
695 arch_kgdb_ops.enable_nmi(1);
696 return ret;
689} 697}
690 698
691int kgdb_nmicallback(int cpu, void *regs) 699int kgdb_nmicallback(int cpu, void *regs)