aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 14:10:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 14:10:41 -0400
commitac3ee84c604502240122c47b52f0542ec8774f15 (patch)
treefa74b50e310af6cef3298a052514b2d42b260d6b /arch
parent90b9a32d8f441369b2f97a765d2d957b531eb653 (diff)
parent4fe1da4ebc18c4c42fa56c228447f68033fce5f0 (diff)
Merge branch 'dbg-early-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'dbg-early-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb: echi-dbgp: Add kernel debugger support for the usb debug port earlyprintk,vga,kdb: Fix \b and \r for earlyprintk=vga with kdb kgdboc: Add ekgdboc for early use of the kernel debugger x86,early dr regs,kgdb: Allow kernel debugger early dr register access x86,kgdb: Implement early hardware breakpoint debugging x86, kgdb, init: Add early and late debug states x86, kgdb: early trap init for early debug
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/processor.h2
-rw-r--r--arch/x86/kernel/cpu/common.c29
-rw-r--r--arch/x86/kernel/early_printk.c8
-rw-r--r--arch/x86/kernel/kgdb.c47
-rw-r--r--arch/x86/kernel/setup.c1
-rw-r--r--arch/x86/kernel/traps.c14
6 files changed, 76 insertions, 25 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 5a51379dcbe4..7e5c6a60b8ee 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -789,6 +789,8 @@ static inline void wbinvd_halt(void)
789extern void enable_sep_cpu(void); 789extern void enable_sep_cpu(void);
790extern int sysenter_setup(void); 790extern int sysenter_setup(void);
791 791
792extern void early_trap_init(void);
793
792/* Defined in head.S */ 794/* Defined in head.S */
793extern struct desc_ptr early_gdt_descr; 795extern struct desc_ptr early_gdt_descr;
794 796
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index c1c00d0b1692..cc83a002786e 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1084,6 +1084,20 @@ static void clear_all_debug_regs(void)
1084 } 1084 }
1085} 1085}
1086 1086
1087#ifdef CONFIG_KGDB
1088/*
1089 * Restore debug regs if using kgdbwait and you have a kernel debugger
1090 * connection established.
1091 */
1092static void dbg_restore_debug_regs(void)
1093{
1094 if (unlikely(kgdb_connected && arch_kgdb_ops.correct_hw_break))
1095 arch_kgdb_ops.correct_hw_break();
1096}
1097#else /* ! CONFIG_KGDB */
1098#define dbg_restore_debug_regs()
1099#endif /* ! CONFIG_KGDB */
1100
1087/* 1101/*
1088 * cpu_init() initializes state that is per-CPU. Some data is already 1102 * cpu_init() initializes state that is per-CPU. Some data is already
1089 * initialized (naturally) in the bootstrap process, such as the GDT 1103 * initialized (naturally) in the bootstrap process, such as the GDT
@@ -1174,18 +1188,8 @@ void __cpuinit cpu_init(void)
1174 load_TR_desc(); 1188 load_TR_desc();
1175 load_LDT(&init_mm.context); 1189 load_LDT(&init_mm.context);
1176 1190
1177#ifdef CONFIG_KGDB 1191 clear_all_debug_regs();
1178 /* 1192 dbg_restore_debug_regs();
1179 * If the kgdb is connected no debug regs should be altered. This
1180 * is only applicable when KGDB and a KGDB I/O module are built
1181 * into the kernel and you are using early debugging with
1182 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
1183 */
1184 if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
1185 arch_kgdb_ops.correct_hw_break();
1186 else
1187#endif
1188 clear_all_debug_regs();
1189 1193
1190 fpu_init(); 1194 fpu_init();
1191 1195
@@ -1239,6 +1243,7 @@ void __cpuinit cpu_init(void)
1239#endif 1243#endif
1240 1244
1241 clear_all_debug_regs(); 1245 clear_all_debug_regs();
1246 dbg_restore_debug_regs();
1242 1247
1243 /* 1248 /*
1244 * Force FPU initialization: 1249 * Force FPU initialization:
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index b9c830c12b4a..fa99bae75ace 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -41,6 +41,14 @@ static void early_vga_write(struct console *con, const char *str, unsigned n)
41 writew(0x720, VGABASE + 2*(max_xpos*j + i)); 41 writew(0x720, VGABASE + 2*(max_xpos*j + i));
42 current_ypos = max_ypos-1; 42 current_ypos = max_ypos-1;
43 } 43 }
44#ifdef CONFIG_KGDB_KDB
45 if (c == '\b') {
46 if (current_xpos > 0)
47 current_xpos--;
48 } else if (c == '\r') {
49 current_xpos = 0;
50 } else
51#endif
44 if (c == '\n') { 52 if (c == '\n') {
45 current_xpos = 0; 53 current_xpos = 0;
46 current_ypos++; 54 current_ypos++;
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 95b89d4cb8f1..4f4af75b9482 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -199,6 +199,8 @@ static struct hw_breakpoint {
199 struct perf_event **pev; 199 struct perf_event **pev;
200} breakinfo[4]; 200} breakinfo[4];
201 201
202static unsigned long early_dr7;
203
202static void kgdb_correct_hw_break(void) 204static void kgdb_correct_hw_break(void)
203{ 205{
204 int breakno; 206 int breakno;
@@ -210,6 +212,14 @@ static void kgdb_correct_hw_break(void)
210 int cpu = raw_smp_processor_id(); 212 int cpu = raw_smp_processor_id();
211 if (!breakinfo[breakno].enabled) 213 if (!breakinfo[breakno].enabled)
212 continue; 214 continue;
215 if (dbg_is_early) {
216 set_debugreg(breakinfo[breakno].addr, breakno);
217 early_dr7 |= encode_dr7(breakno,
218 breakinfo[breakno].len,
219 breakinfo[breakno].type);
220 set_debugreg(early_dr7, 7);
221 continue;
222 }
213 bp = *per_cpu_ptr(breakinfo[breakno].pev, cpu); 223 bp = *per_cpu_ptr(breakinfo[breakno].pev, cpu);
214 info = counter_arch_bp(bp); 224 info = counter_arch_bp(bp);
215 if (bp->attr.disabled != 1) 225 if (bp->attr.disabled != 1)
@@ -224,7 +234,8 @@ static void kgdb_correct_hw_break(void)
224 if (!val) 234 if (!val)
225 bp->attr.disabled = 0; 235 bp->attr.disabled = 0;
226 } 236 }
227 hw_breakpoint_restore(); 237 if (!dbg_is_early)
238 hw_breakpoint_restore();
228} 239}
229 240
230static int hw_break_reserve_slot(int breakno) 241static int hw_break_reserve_slot(int breakno)
@@ -233,6 +244,9 @@ static int hw_break_reserve_slot(int breakno)
233 int cnt = 0; 244 int cnt = 0;
234 struct perf_event **pevent; 245 struct perf_event **pevent;
235 246
247 if (dbg_is_early)
248 return 0;
249
236 for_each_online_cpu(cpu) { 250 for_each_online_cpu(cpu) {
237 cnt++; 251 cnt++;
238 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); 252 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
@@ -258,6 +272,9 @@ static int hw_break_release_slot(int breakno)
258 struct perf_event **pevent; 272 struct perf_event **pevent;
259 int cpu; 273 int cpu;
260 274
275 if (dbg_is_early)
276 return 0;
277
261 for_each_online_cpu(cpu) { 278 for_each_online_cpu(cpu) {
262 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu); 279 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
263 if (dbg_release_bp_slot(*pevent)) 280 if (dbg_release_bp_slot(*pevent))
@@ -302,7 +319,11 @@ static void kgdb_remove_all_hw_break(void)
302 bp = *per_cpu_ptr(breakinfo[i].pev, cpu); 319 bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
303 if (bp->attr.disabled == 1) 320 if (bp->attr.disabled == 1)
304 continue; 321 continue;
305 arch_uninstall_hw_breakpoint(bp); 322 if (dbg_is_early)
323 early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
324 breakinfo[i].type);
325 else
326 arch_uninstall_hw_breakpoint(bp);
306 bp->attr.disabled = 1; 327 bp->attr.disabled = 1;
307 } 328 }
308} 329}
@@ -379,6 +400,11 @@ void kgdb_disable_hw_debug(struct pt_regs *regs)
379 for (i = 0; i < 4; i++) { 400 for (i = 0; i < 4; i++) {
380 if (!breakinfo[i].enabled) 401 if (!breakinfo[i].enabled)
381 continue; 402 continue;
403 if (dbg_is_early) {
404 early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
405 breakinfo[i].type);
406 continue;
407 }
382 bp = *per_cpu_ptr(breakinfo[i].pev, cpu); 408 bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
383 if (bp->attr.disabled == 1) 409 if (bp->attr.disabled == 1)
384 continue; 410 continue;
@@ -596,14 +622,15 @@ static struct notifier_block kgdb_notifier = {
596 */ 622 */
597int kgdb_arch_init(void) 623int kgdb_arch_init(void)
598{ 624{
625 return register_die_notifier(&kgdb_notifier);
626}
627
628void kgdb_arch_late(void)
629{
599 int i, cpu; 630 int i, cpu;
600 int ret;
601 struct perf_event_attr attr; 631 struct perf_event_attr attr;
602 struct perf_event **pevent; 632 struct perf_event **pevent;
603 633
604 ret = register_die_notifier(&kgdb_notifier);
605 if (ret != 0)
606 return ret;
607 /* 634 /*
608 * Pre-allocate the hw breakpoint structions in the non-atomic 635 * Pre-allocate the hw breakpoint structions in the non-atomic
609 * portion of kgdb because this operation requires mutexs to 636 * portion of kgdb because this operation requires mutexs to
@@ -615,12 +642,15 @@ int kgdb_arch_init(void)
615 attr.bp_type = HW_BREAKPOINT_W; 642 attr.bp_type = HW_BREAKPOINT_W;
616 attr.disabled = 1; 643 attr.disabled = 1;
617 for (i = 0; i < 4; i++) { 644 for (i = 0; i < 4; i++) {
645 if (breakinfo[i].pev)
646 continue;
618 breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL); 647 breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
619 if (IS_ERR(breakinfo[i].pev)) { 648 if (IS_ERR(breakinfo[i].pev)) {
620 printk(KERN_ERR "kgdb: Could not allocate hw breakpoints\n"); 649 printk(KERN_ERR "kgdb: Could not allocate hw"
650 "breakpoints\nDisabling the kernel debugger\n");
621 breakinfo[i].pev = NULL; 651 breakinfo[i].pev = NULL;
622 kgdb_arch_exit(); 652 kgdb_arch_exit();
623 return -1; 653 return;
624 } 654 }
625 for_each_online_cpu(cpu) { 655 for_each_online_cpu(cpu) {
626 pevent = per_cpu_ptr(breakinfo[i].pev, cpu); 656 pevent = per_cpu_ptr(breakinfo[i].pev, cpu);
@@ -631,7 +661,6 @@ int kgdb_arch_init(void)
631 } 661 }
632 } 662 }
633 } 663 }
634 return ret;
635} 664}
636 665
637/** 666/**
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c4851eff57b3..e8029896309a 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -725,6 +725,7 @@ void __init setup_arch(char **cmdline_p)
725 /* VMI may relocate the fixmap; do this before touching ioremap area */ 725 /* VMI may relocate the fixmap; do this before touching ioremap area */
726 vmi_init(); 726 vmi_init();
727 727
728 early_trap_init();
728 early_cpu_init(); 729 early_cpu_init();
729 early_ioremap_init(); 730 early_ioremap_init();
730 731
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 7eaad4c5110a..142d70c74b02 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -808,6 +808,16 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
808} 808}
809#endif 809#endif
810 810
811/* Set of traps needed for early debugging. */
812void __init early_trap_init(void)
813{
814 set_intr_gate_ist(1, &debug, DEBUG_STACK);
815 /* int3 can be called from all */
816 set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
817 set_intr_gate(14, &page_fault);
818 load_idt(&idt_descr);
819}
820
811void __init trap_init(void) 821void __init trap_init(void)
812{ 822{
813 int i; 823 int i;
@@ -821,10 +831,7 @@ void __init trap_init(void)
821#endif 831#endif
822 832
823 set_intr_gate(0, &divide_error); 833 set_intr_gate(0, &divide_error);
824 set_intr_gate_ist(1, &debug, DEBUG_STACK);
825 set_intr_gate_ist(2, &nmi, NMI_STACK); 834 set_intr_gate_ist(2, &nmi, NMI_STACK);
826 /* int3 can be called from all */
827 set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
828 /* int4 can be called from all */ 835 /* int4 can be called from all */
829 set_system_intr_gate(4, &overflow); 836 set_system_intr_gate(4, &overflow);
830 set_intr_gate(5, &bounds); 837 set_intr_gate(5, &bounds);
@@ -840,7 +847,6 @@ void __init trap_init(void)
840 set_intr_gate(11, &segment_not_present); 847 set_intr_gate(11, &segment_not_present);
841 set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK); 848 set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK);
842 set_intr_gate(13, &general_protection); 849 set_intr_gate(13, &general_protection);
843 set_intr_gate(14, &page_fault);
844 set_intr_gate(15, &spurious_interrupt_bug); 850 set_intr_gate(15, &spurious_interrupt_bug);
845 set_intr_gate(16, &coprocessor_error); 851 set_intr_gate(16, &coprocessor_error);
846 set_intr_gate(17, &alignment_check); 852 set_intr_gate(17, &alignment_check);