Skip to content

Commit

Permalink
Merge branch 'dbg-early-merge' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Linus Torvalds committed May 21, 2010
2 parents 90b9a32 + 4fe1da4 commit ac3ee84
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 36 deletions.
17 changes: 17 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,12 @@ and is between 256 and 4096 characters. It is defined in the file
The VGA output is eventually overwritten by the real
console.

ekgdboc= [X86,KGDB] Allow early kernel console debugging
ekgdboc=kbd

This is desgined to be used in conjunction with
the boot argument: earlyprintk=vga

eata= [HW,SCSI]

edd= [EDD]
Expand Down Expand Up @@ -1121,6 +1127,17 @@ and is between 256 and 4096 characters. It is defined in the file
use the HighMem zone if it exists, and the Normal
zone if it does not.

kgdbdbgp= [KGDB,HW] kgdb over EHCI usb debug port.
Format: <Controller#>[,poll interval]
The controller # is the number of the ehci usb debug
port as it is probed via PCI. The poll interval is
optional and is the number seconds in between
each poll cycle to the debug port in case you need
the functionality for interrupting the kernel with
gdb or control-c on the dbgp connection. When
not using this parameter you use sysrq-g to break into
the kernel debugger.

kgdboc= [KGDB,HW] kgdb over consoles.
Requires a tty driver that supports console polling,
or a supported polling keyboard driver (non-usb).
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,8 @@ static inline void wbinvd_halt(void)
extern void enable_sep_cpu(void);
extern int sysenter_setup(void);

extern void early_trap_init(void);

/* Defined in head.S */
extern struct desc_ptr early_gdt_descr;

Expand Down
29 changes: 17 additions & 12 deletions arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,20 @@ static void clear_all_debug_regs(void)
}
}

#ifdef CONFIG_KGDB
/*
* Restore debug regs if using kgdbwait and you have a kernel debugger
* connection established.
*/
static void dbg_restore_debug_regs(void)
{
if (unlikely(kgdb_connected && arch_kgdb_ops.correct_hw_break))
arch_kgdb_ops.correct_hw_break();
}
#else /* ! CONFIG_KGDB */
#define dbg_restore_debug_regs()
#endif /* ! CONFIG_KGDB */

/*
* cpu_init() initializes state that is per-CPU. Some data is already
* initialized (naturally) in the bootstrap process, such as the GDT
Expand Down Expand Up @@ -1174,18 +1188,8 @@ void __cpuinit cpu_init(void)
load_TR_desc();
load_LDT(&init_mm.context);

#ifdef CONFIG_KGDB
/*
* If the kgdb is connected no debug regs should be altered. This
* is only applicable when KGDB and a KGDB I/O module are built
* into the kernel and you are using early debugging with
* kgdbwait. KGDB will control the kernel HW breakpoint registers.
*/
if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
arch_kgdb_ops.correct_hw_break();
else
#endif
clear_all_debug_regs();
clear_all_debug_regs();
dbg_restore_debug_regs();

fpu_init();

Expand Down Expand Up @@ -1239,6 +1243,7 @@ void __cpuinit cpu_init(void)
#endif

clear_all_debug_regs();
dbg_restore_debug_regs();

/*
* Force FPU initialization:
Expand Down
8 changes: 8 additions & 0 deletions arch/x86/kernel/early_printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ static void early_vga_write(struct console *con, const char *str, unsigned n)
writew(0x720, VGABASE + 2*(max_xpos*j + i));
current_ypos = max_ypos-1;
}
#ifdef CONFIG_KGDB_KDB
if (c == '\b') {
if (current_xpos > 0)
current_xpos--;
} else if (c == '\r') {
current_xpos = 0;
} else
#endif
if (c == '\n') {
current_xpos = 0;
current_ypos++;
Expand Down
47 changes: 38 additions & 9 deletions arch/x86/kernel/kgdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ static struct hw_breakpoint {
struct perf_event **pev;
} breakinfo[4];

static unsigned long early_dr7;

static void kgdb_correct_hw_break(void)
{
int breakno;
Expand All @@ -210,6 +212,14 @@ static void kgdb_correct_hw_break(void)
int cpu = raw_smp_processor_id();
if (!breakinfo[breakno].enabled)
continue;
if (dbg_is_early) {
set_debugreg(breakinfo[breakno].addr, breakno);
early_dr7 |= encode_dr7(breakno,
breakinfo[breakno].len,
breakinfo[breakno].type);
set_debugreg(early_dr7, 7);
continue;
}
bp = *per_cpu_ptr(breakinfo[breakno].pev, cpu);
info = counter_arch_bp(bp);
if (bp->attr.disabled != 1)
Expand All @@ -224,7 +234,8 @@ static void kgdb_correct_hw_break(void)
if (!val)
bp->attr.disabled = 0;
}
hw_breakpoint_restore();
if (!dbg_is_early)
hw_breakpoint_restore();
}

static int hw_break_reserve_slot(int breakno)
Expand All @@ -233,6 +244,9 @@ static int hw_break_reserve_slot(int breakno)
int cnt = 0;
struct perf_event **pevent;

if (dbg_is_early)
return 0;

for_each_online_cpu(cpu) {
cnt++;
pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
Expand All @@ -258,6 +272,9 @@ static int hw_break_release_slot(int breakno)
struct perf_event **pevent;
int cpu;

if (dbg_is_early)
return 0;

for_each_online_cpu(cpu) {
pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
if (dbg_release_bp_slot(*pevent))
Expand Down Expand Up @@ -302,7 +319,11 @@ static void kgdb_remove_all_hw_break(void)
bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
if (bp->attr.disabled == 1)
continue;
arch_uninstall_hw_breakpoint(bp);
if (dbg_is_early)
early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
breakinfo[i].type);
else
arch_uninstall_hw_breakpoint(bp);
bp->attr.disabled = 1;
}
}
Expand Down Expand Up @@ -379,6 +400,11 @@ void kgdb_disable_hw_debug(struct pt_regs *regs)
for (i = 0; i < 4; i++) {
if (!breakinfo[i].enabled)
continue;
if (dbg_is_early) {
early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
breakinfo[i].type);
continue;
}
bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
if (bp->attr.disabled == 1)
continue;
Expand Down Expand Up @@ -595,15 +621,16 @@ static struct notifier_block kgdb_notifier = {
* specific callbacks.
*/
int kgdb_arch_init(void)
{
return register_die_notifier(&kgdb_notifier);
}

void kgdb_arch_late(void)
{
int i, cpu;
int ret;
struct perf_event_attr attr;
struct perf_event **pevent;

ret = register_die_notifier(&kgdb_notifier);
if (ret != 0)
return ret;
/*
* Pre-allocate the hw breakpoint structions in the non-atomic
* portion of kgdb because this operation requires mutexs to
Expand All @@ -615,12 +642,15 @@ int kgdb_arch_init(void)
attr.bp_type = HW_BREAKPOINT_W;
attr.disabled = 1;
for (i = 0; i < 4; i++) {
if (breakinfo[i].pev)
continue;
breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
if (IS_ERR(breakinfo[i].pev)) {
printk(KERN_ERR "kgdb: Could not allocate hw breakpoints\n");
printk(KERN_ERR "kgdb: Could not allocate hw"
"breakpoints\nDisabling the kernel debugger\n");
breakinfo[i].pev = NULL;
kgdb_arch_exit();
return -1;
return;
}
for_each_online_cpu(cpu) {
pevent = per_cpu_ptr(breakinfo[i].pev, cpu);
Expand All @@ -631,7 +661,6 @@ int kgdb_arch_init(void)
}
}
}
return ret;
}

/**
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@ void __init setup_arch(char **cmdline_p)
/* VMI may relocate the fixmap; do this before touching ioremap area */
vmi_init();

early_trap_init();
early_cpu_init();
early_ioremap_init();

Expand Down
14 changes: 10 additions & 4 deletions arch/x86/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,16 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
}
#endif

/* Set of traps needed for early debugging. */
void __init early_trap_init(void)
{
set_intr_gate_ist(1, &debug, DEBUG_STACK);
/* int3 can be called from all */
set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
set_intr_gate(14, &page_fault);
load_idt(&idt_descr);
}

void __init trap_init(void)
{
int i;
Expand All @@ -821,10 +831,7 @@ void __init trap_init(void)
#endif

set_intr_gate(0, &divide_error);
set_intr_gate_ist(1, &debug, DEBUG_STACK);
set_intr_gate_ist(2, &nmi, NMI_STACK);
/* int3 can be called from all */
set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
/* int4 can be called from all */
set_system_intr_gate(4, &overflow);
set_intr_gate(5, &bounds);
Expand All @@ -840,7 +847,6 @@ void __init trap_init(void)
set_intr_gate(11, &segment_not_present);
set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK);
set_intr_gate(13, &general_protection);
set_intr_gate(14, &page_fault);
set_intr_gate(15, &spurious_interrupt_bug);
set_intr_gate(16, &coprocessor_error);
set_intr_gate(17, &alignment_check);
Expand Down
19 changes: 19 additions & 0 deletions drivers/serial/kgdboc.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,25 @@ static struct kgdb_io kgdboc_io_ops = {
.post_exception = kgdboc_post_exp_handler,
};

#ifdef CONFIG_KGDB_SERIAL_CONSOLE
/* This is only available if kgdboc is a built in for early debugging */
int __init kgdboc_early_init(char *opt)
{
/* save the first character of the config string because the
* init routine can destroy it.
*/
char save_ch;

kgdboc_option_setup(opt);
save_ch = config[0];
init_kgdboc();
config[0] = save_ch;
return 0;
}

early_param("ekgdboc", kgdboc_early_init);
#endif /* CONFIG_KGDB_SERIAL_CONSOLE */

module_init(init_kgdboc);
module_exit(cleanup_kgdboc);
module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
Expand Down
Loading

0 comments on commit ac3ee84

Please sign in to comment.