2008-04-17 22:05:37 +04:00
/*
2010-04-02 20:48:03 +04:00
* Kernel Debug Core
2008-04-17 22:05:37 +04:00
*
* Maintainer : Jason Wessel < jason . wessel @ windriver . com >
*
* Copyright ( C ) 2000 - 2001 VERITAS Software Corporation .
* Copyright ( C ) 2002 - 2004 Timesys Corporation
* Copyright ( C ) 2003 - 2004 Amit S . Kale < amitkale @ linsyssoft . com >
* Copyright ( C ) 2004 Pavel Machek < pavel @ suse . cz >
* Copyright ( C ) 2004 - 2006 Tom Rini < trini @ kernel . crashing . org >
* Copyright ( C ) 2004 - 2006 LinSysSoft Technologies Pvt . Ltd .
2010-04-02 20:48:03 +04:00
* Copyright ( C ) 2005 - 2009 Wind River Systems , Inc .
2008-04-17 22:05:37 +04:00
* Copyright ( C ) 2007 MontaVista Software , Inc .
* Copyright ( C ) 2008 Red Hat , Inc . , Ingo Molnar < mingo @ redhat . com >
*
* Contributors at various stages not listed above :
* Jason Wessel ( jason . wessel @ windriver . com )
* George Anzinger < george @ mvista . com >
* Anurekh Saxena ( anurekh . saxena @ timesys . com )
* Lake Stevens Instrument Division ( Glenn Engel )
* Jim Kingdon , Cygnus Support .
*
* Original KGDB stub : David Grothe < dave @ gcom . com > ,
* Tigran Aivazian < tigran @ sco . com >
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed " as is " without any warranty of any
* kind , whether express or implied .
*/
# include <linux/pid_namespace.h>
2008-02-15 23:55:54 +03:00
# include <linux/clocksource.h>
2008-04-17 22:05:37 +04:00
# include <linux/interrupt.h>
# include <linux/spinlock.h>
# include <linux/console.h>
# include <linux/threads.h>
# include <linux/uaccess.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/ptrace.h>
# include <linux/string.h>
# include <linux/delay.h>
# include <linux/sched.h>
# include <linux/sysrq.h>
# include <linux/init.h>
# include <linux/kgdb.h>
2010-05-21 06:04:21 +04:00
# include <linux/kdb.h>
2008-04-17 22:05:37 +04:00
# include <linux/pid.h>
# include <linux/smp.h>
# include <linux/mm.h>
# include <asm/cacheflush.h>
# include <asm/byteorder.h>
# include <asm/atomic.h>
# include <asm/system.h>
2010-04-02 20:48:03 +04:00
# include "debug_core.h"
2008-04-17 22:05:37 +04:00
2010-04-02 20:48:03 +04:00
static int kgdb_break_asap ;
2010-04-02 20:47:02 +04:00
2010-04-02 20:48:03 +04:00
struct debuggerinfo_struct kgdb_info [ NR_CPUS ] ;
2008-04-17 22:05:37 +04:00
/**
* kgdb_connected - Is a host GDB connected to us ?
*/
int kgdb_connected ;
EXPORT_SYMBOL_GPL ( kgdb_connected ) ;
/* All the KGDB handlers are installed */
static int kgdb_io_module_registered ;
/* Guard for recursive entry */
static int exception_level ;
2010-04-02 20:48:03 +04:00
struct kgdb_io * dbg_io_ops ;
2008-04-17 22:05:37 +04:00
static DEFINE_SPINLOCK ( kgdb_registration_lock ) ;
/* kgdb console driver is loaded */
static int kgdb_con_registered ;
/* determine if kgdb console output should be used */
static int kgdb_use_con ;
2010-05-21 06:04:21 +04:00
/* Next cpu to become the master debug core */
int dbg_switch_cpu ;
/* Use kdb or gdbserver mode */
static int dbg_kdb_mode = 1 ;
2008-04-17 22:05:37 +04:00
static int __init opt_kgdb_con ( char * str )
{
kgdb_use_con = 1 ;
return 0 ;
}
early_param ( " kgdbcon " , opt_kgdb_con ) ;
module_param ( kgdb_use_con , int , 0644 ) ;
/*
* Holds information about breakpoints in a kernel . These breakpoints are
* added and removed by gdb .
*/
static struct kgdb_bkpt kgdb_break [ KGDB_MAX_BREAKPOINTS ] = {
[ 0 . . . KGDB_MAX_BREAKPOINTS - 1 ] = { . state = BP_UNDEFINED }
} ;
/*
* The CPU # of the active CPU , or - 1 if none :
*/
atomic_t kgdb_active = ATOMIC_INIT ( - 1 ) ;
2010-05-21 06:04:21 +04:00
EXPORT_SYMBOL_GPL ( kgdb_active ) ;
2008-04-17 22:05:37 +04:00
/*
* We use NR_CPUs not PERCPU , in case kgdb is used to debug early
* bootup code ( which might not have percpu set up yet ) :
*/
static atomic_t passive_cpu_wait [ NR_CPUS ] ;
static atomic_t cpu_in_kgdb [ NR_CPUS ] ;
atomic_t kgdb_setting_breakpoint ;
struct task_struct * kgdb_usethread ;
struct task_struct * kgdb_contthread ;
int kgdb_single_step ;
2010-04-02 20:48:03 +04:00
static pid_t kgdb_sstep_pid ;
2008-04-17 22:05:37 +04:00
/* to keep track of the CPU which is doing the single stepping*/
atomic_t kgdb_cpu_doing_single_step = ATOMIC_INIT ( - 1 ) ;
/*
* If you are debugging a problem where roundup ( the collection of
* all other CPUs ) is a problem [ this should be extremely rare ] ,
* then use the nokgdbroundup option to avoid roundup . In that case
* the other CPUs might interfere with your debugging context , so
* use this with care :
*/
2008-04-25 01:57:23 +04:00
static int kgdb_do_roundup = 1 ;
2008-04-17 22:05:37 +04:00
static int __init opt_nokgdbroundup ( char * str )
{
kgdb_do_roundup = 0 ;
return 0 ;
}
early_param ( " nokgdbroundup " , opt_nokgdbroundup ) ;
/*
* Finally , some KGDB code : - )
*/
/*
* Weak aliases for breakpoint management ,
* can be overriden by architectures when needed :
*/
int __weak kgdb_arch_set_breakpoint ( unsigned long addr , char * saved_instr )
{
int err ;
err = probe_kernel_read ( saved_instr , ( char * ) addr , BREAK_INSTR_SIZE ) ;
if ( err )
return err ;
return probe_kernel_write ( ( char * ) addr , arch_kgdb_ops . gdb_bpt_instr ,
BREAK_INSTR_SIZE ) ;
}
int __weak kgdb_arch_remove_breakpoint ( unsigned long addr , char * bundle )
{
return probe_kernel_write ( ( char * ) addr ,
( char * ) bundle , BREAK_INSTR_SIZE ) ;
}
2008-08-01 17:39:34 +04:00
int __weak kgdb_validate_break_address ( unsigned long addr )
{
char tmp_variable [ BREAK_INSTR_SIZE ] ;
int err ;
/* Validate setting the breakpoint and then removing it. In the
* remove fails , the kernel needs to emit a bad message because we
* are deep trouble not being able to put things back the way we
* found them .
*/
err = kgdb_arch_set_breakpoint ( addr , tmp_variable ) ;
if ( err )
return err ;
err = kgdb_arch_remove_breakpoint ( addr , tmp_variable ) ;
if ( err )
printk ( KERN_ERR " KGDB: Critical breakpoint error, kernel "
" memory destroyed at: %lx " , addr ) ;
return err ;
}
2008-04-17 22:05:37 +04:00
unsigned long __weak kgdb_arch_pc ( int exception , struct pt_regs * regs )
{
return instruction_pointer ( regs ) ;
}
int __weak kgdb_arch_init ( void )
{
return 0 ;
}
2008-02-20 22:33:38 +03:00
int __weak kgdb_skipexception ( int exception , struct pt_regs * regs )
{
return 0 ;
}
void __weak
kgdb_post_primary_code ( struct pt_regs * regs , int e_vector , int err_code )
{
return ;
}
2008-04-17 22:05:37 +04:00
/**
* kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb .
* @ regs : Current & struct pt_regs .
*
* This function will be called if the particular architecture must
* disable hardware debugging while it is processing gdb packets or
* handling exception .
*/
void __weak kgdb_disable_hw_debug ( struct pt_regs * regs )
{
}
/*
* Some architectures need cache flushes when we set / clear a
* breakpoint :
*/
static void kgdb_flush_swbreak_addr ( unsigned long addr )
{
if ( ! CACHE_FLUSH_IS_SAFE )
return ;
2008-03-08 01:34:16 +03:00
if ( current - > mm & & current - > mm - > mmap_cache ) {
2008-04-17 22:05:37 +04:00
flush_cache_range ( current - > mm - > mmap_cache ,
addr , addr + BREAK_INSTR_SIZE ) ;
}
2008-04-02 01:55:28 +04:00
/* Force flush instruction cache if it was outside the mm */
flush_icache_range ( addr , addr + BREAK_INSTR_SIZE ) ;
2008-04-17 22:05:37 +04:00
}
/*
* SW breakpoint management :
*/
2010-04-02 20:48:03 +04:00
int dbg_activate_sw_breakpoints ( void )
2008-04-17 22:05:37 +04:00
{
unsigned long addr ;
2009-12-11 17:43:20 +03:00
int error ;
int ret = 0 ;
2008-04-17 22:05:37 +04:00
int i ;
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
if ( kgdb_break [ i ] . state ! = BP_SET )
continue ;
addr = kgdb_break [ i ] . bpt_addr ;
error = kgdb_arch_set_breakpoint ( addr ,
kgdb_break [ i ] . saved_instr ) ;
2009-12-11 17:43:20 +03:00
if ( error ) {
ret = error ;
printk ( KERN_INFO " KGDB: BP install failed: %lx " , addr ) ;
continue ;
}
2008-04-17 22:05:37 +04:00
kgdb_flush_swbreak_addr ( addr ) ;
kgdb_break [ i ] . state = BP_ACTIVE ;
}
2009-12-11 17:43:20 +03:00
return ret ;
2008-04-17 22:05:37 +04:00
}
2010-04-02 20:48:03 +04:00
int dbg_set_sw_break ( unsigned long addr )
2008-04-17 22:05:37 +04:00
{
int err = kgdb_validate_break_address ( addr ) ;
int breakno = - 1 ;
int i ;
if ( err )
return err ;
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
if ( ( kgdb_break [ i ] . state = = BP_SET ) & &
( kgdb_break [ i ] . bpt_addr = = addr ) )
return - EEXIST ;
}
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
if ( kgdb_break [ i ] . state = = BP_REMOVED & &
kgdb_break [ i ] . bpt_addr = = addr ) {
breakno = i ;
break ;
}
}
if ( breakno = = - 1 ) {
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
if ( kgdb_break [ i ] . state = = BP_UNDEFINED ) {
breakno = i ;
break ;
}
}
}
if ( breakno = = - 1 )
return - E2BIG ;
kgdb_break [ breakno ] . state = BP_SET ;
kgdb_break [ breakno ] . type = BP_BREAKPOINT ;
kgdb_break [ breakno ] . bpt_addr = addr ;
return 0 ;
}
2010-05-21 06:04:21 +04:00
int dbg_deactivate_sw_breakpoints ( void )
2008-04-17 22:05:37 +04:00
{
unsigned long addr ;
2009-12-11 17:43:20 +03:00
int error ;
int ret = 0 ;
2008-04-17 22:05:37 +04:00
int i ;
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
if ( kgdb_break [ i ] . state ! = BP_ACTIVE )
continue ;
addr = kgdb_break [ i ] . bpt_addr ;
error = kgdb_arch_remove_breakpoint ( addr ,
kgdb_break [ i ] . saved_instr ) ;
2009-12-11 17:43:20 +03:00
if ( error ) {
printk ( KERN_INFO " KGDB: BP remove failed: %lx \n " , addr ) ;
ret = error ;
}
2008-04-17 22:05:37 +04:00
kgdb_flush_swbreak_addr ( addr ) ;
kgdb_break [ i ] . state = BP_SET ;
}
2009-12-11 17:43:20 +03:00
return ret ;
2008-04-17 22:05:37 +04:00
}
2010-04-02 20:48:03 +04:00
int dbg_remove_sw_break ( unsigned long addr )
2008-04-17 22:05:37 +04:00
{
int i ;
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
if ( ( kgdb_break [ i ] . state = = BP_SET ) & &
( kgdb_break [ i ] . bpt_addr = = addr ) ) {
kgdb_break [ i ] . state = BP_REMOVED ;
return 0 ;
}
}
return - ENOENT ;
}
int kgdb_isremovedbreak ( unsigned long addr )
{
int i ;
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
if ( ( kgdb_break [ i ] . state = = BP_REMOVED ) & &
( kgdb_break [ i ] . bpt_addr = = addr ) )
return 1 ;
}
return 0 ;
}
2010-04-02 20:48:03 +04:00
int dbg_remove_all_break ( void )
2008-04-17 22:05:37 +04:00
{
unsigned long addr ;
int error ;
int i ;
/* Clear memory breakpoints. */
for ( i = 0 ; i < KGDB_MAX_BREAKPOINTS ; i + + ) {
2008-03-08 01:34:16 +03:00
if ( kgdb_break [ i ] . state ! = BP_ACTIVE )
goto setundefined ;
2008-04-17 22:05:37 +04:00
addr = kgdb_break [ i ] . bpt_addr ;
error = kgdb_arch_remove_breakpoint ( addr ,
kgdb_break [ i ] . saved_instr ) ;
if ( error )
2008-03-08 01:34:16 +03:00
printk ( KERN_ERR " KGDB: breakpoint remove failed: %lx \n " ,
addr ) ;
setundefined :
kgdb_break [ i ] . state = BP_UNDEFINED ;
2008-04-17 22:05:37 +04:00
}
/* Clear hardware breakpoints. */
if ( arch_kgdb_ops . remove_all_hw_break )
arch_kgdb_ops . remove_all_hw_break ( ) ;
return 0 ;
}
/*
* Return true if there is a valid kgdb I / O module . Also if no
* debugger is attached a message can be printed to the console about
* waiting for the debugger to attach .
*
* The print_wait argument is only to be true when called from inside
* the core kgdb_handle_exception , because it will wait for the
* debugger to attach .
*/
static int kgdb_io_ready ( int print_wait )
{
2010-04-02 20:48:03 +04:00
if ( ! dbg_io_ops )
2008-04-17 22:05:37 +04:00
return 0 ;
if ( kgdb_connected )
return 1 ;
if ( atomic_read ( & kgdb_setting_breakpoint ) )
return 1 ;
2010-05-21 06:04:21 +04:00
if ( print_wait ) {
# ifdef CONFIG_KGDB_KDB
if ( ! dbg_kdb_mode )
printk ( KERN_CRIT " KGDB: waiting... or $3#33 for KDB \n " ) ;
# else
2008-04-17 22:05:37 +04:00
printk ( KERN_CRIT " KGDB: Waiting for remote debugger \n " ) ;
2010-05-21 06:04:21 +04:00
# endif
}
2008-04-17 22:05:37 +04:00
return 1 ;
}
static int kgdb_reenter_check ( struct kgdb_state * ks )
{
unsigned long addr ;
if ( atomic_read ( & kgdb_active ) ! = raw_smp_processor_id ( ) )
return 0 ;
/* Panic on recursive debugger calls: */
exception_level + + ;
addr = kgdb_arch_pc ( ks - > ex_vector , ks - > linux_regs ) ;
2010-05-21 06:04:21 +04:00
dbg_deactivate_sw_breakpoints ( ) ;
2008-04-17 22:05:37 +04:00
/*
* If the break point removed ok at the place exception
* occurred , try to recover and print a warning to the end
* user because the user planted a breakpoint in a place that
* KGDB needs in order to function .
*/
2010-04-02 20:48:03 +04:00
if ( dbg_remove_sw_break ( addr ) = = 0 ) {
2008-04-17 22:05:37 +04:00
exception_level = 0 ;
kgdb_skipexception ( ks - > ex_vector , ks - > linux_regs ) ;
2010-04-02 20:48:03 +04:00
dbg_activate_sw_breakpoints ( ) ;
2008-02-15 23:55:55 +03:00
printk ( KERN_CRIT " KGDB: re-enter error: breakpoint removed %lx \n " ,
addr ) ;
2008-04-17 22:05:37 +04:00
WARN_ON_ONCE ( 1 ) ;
return 1 ;
}
2010-04-02 20:48:03 +04:00
dbg_remove_all_break ( ) ;
2008-04-17 22:05:37 +04:00
kgdb_skipexception ( ks - > ex_vector , ks - > linux_regs ) ;
if ( exception_level > 1 ) {
dump_stack ( ) ;
panic ( " Recursive entry to debugger " ) ;
}
printk ( KERN_CRIT " KGDB: re-enter exception: ALL breakpoints killed \n " ) ;
dump_stack ( ) ;
panic ( " Recursive entry to debugger " ) ;
return 1 ;
}
2010-05-21 06:04:21 +04:00
static void dbg_cpu_switch ( int cpu , int next_cpu )
{
/* Mark the cpu we are switching away from as a slave when it
* holds the kgdb_active token . This must be done so that the
* that all the cpus wait in for the debug core will not enter
* again as the master . */
if ( cpu = = atomic_read ( & kgdb_active ) ) {
kgdb_info [ cpu ] . exception_state | = DCPU_IS_SLAVE ;
kgdb_info [ cpu ] . exception_state & = ~ DCPU_WANT_MASTER ;
}
kgdb_info [ next_cpu ] . exception_state | = DCPU_NEXT_MASTER ;
}
2010-04-02 20:47:02 +04:00
static int kgdb_cpu_enter ( struct kgdb_state * ks , struct pt_regs * regs )
2008-04-17 22:05:37 +04:00
{
unsigned long flags ;
2009-12-11 17:43:17 +03:00
int sstep_tries = 100 ;
2010-05-21 06:04:21 +04:00
int error ;
2008-04-17 22:05:37 +04:00
int i , cpu ;
2010-04-02 20:57:18 +04:00
int trace_on = 0 ;
2008-04-17 22:05:37 +04:00
acquirelock :
/*
* Interrupts will be restored by the ' trap return ' code , except when
* single stepping .
*/
local_irq_save ( flags ) ;
2010-04-02 20:47:02 +04:00
cpu = ks - > cpu ;
kgdb_info [ cpu ] . debuggerinfo = regs ;
kgdb_info [ cpu ] . task = current ;
2010-05-21 06:04:21 +04:00
kgdb_info [ cpu ] . ret_state = 0 ;
kgdb_info [ cpu ] . irq_depth = hardirq_count ( ) > > HARDIRQ_SHIFT ;
2010-04-02 20:47:02 +04:00
/*
* Make sure the above info reaches the primary CPU before
* our cpu_in_kgdb [ ] flag setting does :
*/
2010-04-02 23:58:18 +04:00
atomic_inc ( & cpu_in_kgdb [ cpu ] ) ;
2008-04-17 22:05:37 +04:00
/*
2010-04-02 20:47:02 +04:00
* CPU will loop if it is a slave or request to become a kgdb
* master cpu and acquire the kgdb_active lock :
2008-04-17 22:05:37 +04:00
*/
2010-04-02 20:47:02 +04:00
while ( 1 ) {
2010-05-21 06:04:21 +04:00
cpu_loop :
if ( kgdb_info [ cpu ] . exception_state & DCPU_NEXT_MASTER ) {
kgdb_info [ cpu ] . exception_state & = ~ DCPU_NEXT_MASTER ;
goto cpu_master_loop ;
} else if ( kgdb_info [ cpu ] . exception_state & DCPU_WANT_MASTER ) {
2010-04-02 20:47:02 +04:00
if ( atomic_cmpxchg ( & kgdb_active , - 1 , cpu ) = = cpu )
break ;
} else if ( kgdb_info [ cpu ] . exception_state & DCPU_IS_SLAVE ) {
if ( ! atomic_read ( & passive_cpu_wait [ cpu ] ) )
goto return_normal ;
} else {
return_normal :
/* Return to normal operation by executing any
* hw breakpoint fixup .
*/
if ( arch_kgdb_ops . correct_hw_break )
arch_kgdb_ops . correct_hw_break ( ) ;
2010-04-02 20:57:18 +04:00
if ( trace_on )
tracing_on ( ) ;
2010-04-02 23:58:18 +04:00
atomic_dec ( & cpu_in_kgdb [ cpu ] ) ;
2010-04-02 20:47:02 +04:00
touch_softlockup_watchdog_sync ( ) ;
clocksource_touch_watchdog ( ) ;
local_irq_restore ( flags ) ;
return 0 ;
}
2008-04-17 22:05:37 +04:00
cpu_relax ( ) ;
2010-04-02 20:47:02 +04:00
}
2008-04-17 22:05:37 +04:00
/*
2009-12-11 17:43:17 +03:00
* For single stepping , try to only enter on the processor
* that was single stepping . To gaurd against a deadlock , the
* kernel will only try for the value of sstep_tries before
* giving up and continuing on .
2008-04-17 22:05:37 +04:00
*/
if ( atomic_read ( & kgdb_cpu_doing_single_step ) ! = - 1 & &
2009-12-11 17:43:17 +03:00
( kgdb_info [ cpu ] . task & &
kgdb_info [ cpu ] . task - > pid ! = kgdb_sstep_pid ) & & - - sstep_tries ) {
2008-04-17 22:05:37 +04:00
atomic_set ( & kgdb_active , - 1 ) ;
2010-01-28 01:25:22 +03:00
touch_softlockup_watchdog_sync ( ) ;
2008-02-15 23:55:54 +03:00
clocksource_touch_watchdog ( ) ;
2008-04-17 22:05:37 +04:00
local_irq_restore ( flags ) ;
goto acquirelock ;
}
if ( ! kgdb_io_ready ( 1 ) ) {
2010-05-21 06:04:21 +04:00
kgdb_info [ cpu ] . ret_state = 1 ;
2010-04-02 20:48:03 +04:00
goto kgdb_restore ; /* No I/O connection, resume the system */
2008-04-17 22:05:37 +04:00
}
/*
* Don ' t enter if we have hit a removed breakpoint .
*/
if ( kgdb_skipexception ( ks - > ex_vector , ks - > linux_regs ) )
goto kgdb_restore ;
/* Call the I/O driver's pre_exception routine */
2010-04-02 20:48:03 +04:00
if ( dbg_io_ops - > pre_exception )
dbg_io_ops - > pre_exception ( ) ;
2008-04-17 22:05:37 +04:00
kgdb_disable_hw_debug ( ks - > linux_regs ) ;
/*
* Get the passive CPU lock which will hold all the non - primary
* CPU in a spin state while the debugger is active
*/
kgdb, x86, arm, mips, powerpc: ignore user space single stepping
On the x86 arch, user space single step exceptions should be ignored
if they occur in the kernel space, such as ptrace stepping through a
system call.
First check if it is kgdb that is executing a single step, then ensure
it is not an accidental traversal into the user space, while in kgdb,
any other time the TIF_SINGLESTEP is set, kgdb should ignore the
exception.
On x86, arm, mips and powerpc, the kgdb_contthread usage was
inconsistent with the way single stepping is implemented in the kgdb
core. The arch specific stub should always set the
kgdb_cpu_doing_single_step correctly if it is single stepping. This
allows kgdb to correctly process an instruction steps if ptrace
happens to be requesting an instruction step over a system call.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2008-09-26 19:36:41 +04:00
if ( ! kgdb_single_step ) {
2008-04-17 22:05:37 +04:00
for ( i = 0 ; i < NR_CPUS ; i + + )
2010-04-02 23:58:18 +04:00
atomic_inc ( & passive_cpu_wait [ i ] ) ;
2008-04-17 22:05:37 +04:00
}
2008-04-02 01:55:27 +04:00
# ifdef CONFIG_SMP
/* Signal the other CPUs to enter kgdb_wait() */
kgdb, x86, arm, mips, powerpc: ignore user space single stepping
On the x86 arch, user space single step exceptions should be ignored
if they occur in the kernel space, such as ptrace stepping through a
system call.
First check if it is kgdb that is executing a single step, then ensure
it is not an accidental traversal into the user space, while in kgdb,
any other time the TIF_SINGLESTEP is set, kgdb should ignore the
exception.
On x86, arm, mips and powerpc, the kgdb_contthread usage was
inconsistent with the way single stepping is implemented in the kgdb
core. The arch specific stub should always set the
kgdb_cpu_doing_single_step correctly if it is single stepping. This
allows kgdb to correctly process an instruction steps if ptrace
happens to be requesting an instruction step over a system call.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2008-09-26 19:36:41 +04:00
if ( ( ! kgdb_single_step ) & & kgdb_do_roundup )
2008-04-02 01:55:27 +04:00
kgdb_roundup_cpus ( flags ) ;
# endif
2008-04-17 22:05:37 +04:00
/*
* Wait for the other CPUs to be notified and be waiting for us :
*/
for_each_online_cpu ( i ) {
2010-05-21 06:04:21 +04:00
while ( kgdb_do_roundup & & ! atomic_read ( & cpu_in_kgdb [ i ] ) )
2008-04-17 22:05:37 +04:00
cpu_relax ( ) ;
}
/*
* At this point the primary processor is completely
* in the debugger and all secondary CPUs are quiescent
*/
kgdb_post_primary_code ( ks - > linux_regs , ks - > ex_vector , ks - > err_code ) ;
2010-05-21 06:04:21 +04:00
dbg_deactivate_sw_breakpoints ( ) ;
2008-04-17 22:05:37 +04:00
kgdb_single_step = 0 ;
kgdb, x86, arm, mips, powerpc: ignore user space single stepping
On the x86 arch, user space single step exceptions should be ignored
if they occur in the kernel space, such as ptrace stepping through a
system call.
First check if it is kgdb that is executing a single step, then ensure
it is not an accidental traversal into the user space, while in kgdb,
any other time the TIF_SINGLESTEP is set, kgdb should ignore the
exception.
On x86, arm, mips and powerpc, the kgdb_contthread usage was
inconsistent with the way single stepping is implemented in the kgdb
core. The arch specific stub should always set the
kgdb_cpu_doing_single_step correctly if it is single stepping. This
allows kgdb to correctly process an instruction steps if ptrace
happens to be requesting an instruction step over a system call.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2008-09-26 19:36:41 +04:00
kgdb_contthread = current ;
2008-04-17 22:05:37 +04:00
exception_level = 0 ;
2010-04-02 20:57:18 +04:00
trace_on = tracing_is_on ( ) ;
if ( trace_on )
tracing_off ( ) ;
2008-04-17 22:05:37 +04:00
2010-05-21 06:04:21 +04:00
while ( 1 ) {
cpu_master_loop :
if ( dbg_kdb_mode ) {
kgdb_connected = 1 ;
error = kdb_stub ( ks ) ;
} else {
error = gdb_serial_stub ( ks ) ;
}
if ( error = = DBG_PASS_EVENT ) {
dbg_kdb_mode = ! dbg_kdb_mode ;
kgdb_connected = 0 ;
} else if ( error = = DBG_SWITCH_CPU_EVENT ) {
dbg_cpu_switch ( cpu , dbg_switch_cpu ) ;
goto cpu_loop ;
} else {
kgdb_info [ cpu ] . ret_state = error ;
break ;
}
}
2008-04-17 22:05:37 +04:00
/* Call the I/O driver's post_exception routine */
2010-04-02 20:48:03 +04:00
if ( dbg_io_ops - > post_exception )
dbg_io_ops - > post_exception ( ) ;
2008-04-17 22:05:37 +04:00
2010-04-02 23:58:18 +04:00
atomic_dec ( & cpu_in_kgdb [ ks - > cpu ] ) ;
2008-04-17 22:05:37 +04:00
kgdb, x86, arm, mips, powerpc: ignore user space single stepping
On the x86 arch, user space single step exceptions should be ignored
if they occur in the kernel space, such as ptrace stepping through a
system call.
First check if it is kgdb that is executing a single step, then ensure
it is not an accidental traversal into the user space, while in kgdb,
any other time the TIF_SINGLESTEP is set, kgdb should ignore the
exception.
On x86, arm, mips and powerpc, the kgdb_contthread usage was
inconsistent with the way single stepping is implemented in the kgdb
core. The arch specific stub should always set the
kgdb_cpu_doing_single_step correctly if it is single stepping. This
allows kgdb to correctly process an instruction steps if ptrace
happens to be requesting an instruction step over a system call.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2008-09-26 19:36:41 +04:00
if ( ! kgdb_single_step ) {
2008-04-17 22:05:37 +04:00
for ( i = NR_CPUS - 1 ; i > = 0 ; i - - )
2010-04-02 23:58:18 +04:00
atomic_dec ( & passive_cpu_wait [ i ] ) ;
2008-04-17 22:05:37 +04:00
/*
2010-05-21 06:04:21 +04:00
* Wait till all the CPUs have quit from the debugger ,
* but allow a CPU that hit an exception and is
* waiting to become the master to remain in the debug
* core .
2008-04-17 22:05:37 +04:00
*/
for_each_online_cpu ( i ) {
2010-05-21 06:04:21 +04:00
while ( kgdb_do_roundup & &
atomic_read ( & cpu_in_kgdb [ i ] ) & &
! ( kgdb_info [ i ] . exception_state &
DCPU_WANT_MASTER ) )
2008-04-17 22:05:37 +04:00
cpu_relax ( ) ;
}
}
kgdb_restore :
2009-12-11 17:43:17 +03:00
if ( atomic_read ( & kgdb_cpu_doing_single_step ) ! = - 1 ) {
int sstep_cpu = atomic_read ( & kgdb_cpu_doing_single_step ) ;
if ( kgdb_info [ sstep_cpu ] . task )
kgdb_sstep_pid = kgdb_info [ sstep_cpu ] . task - > pid ;
else
kgdb_sstep_pid = 0 ;
}
2010-04-02 20:57:18 +04:00
if ( trace_on )
tracing_on ( ) ;
2008-04-17 22:05:37 +04:00
/* Free kgdb_active */
atomic_set ( & kgdb_active , - 1 ) ;
2010-01-28 01:25:22 +03:00
touch_softlockup_watchdog_sync ( ) ;
2008-02-15 23:55:54 +03:00
clocksource_touch_watchdog ( ) ;
2008-04-17 22:05:37 +04:00
local_irq_restore ( flags ) ;
2010-05-21 06:04:21 +04:00
return kgdb_info [ cpu ] . ret_state ;
2008-04-17 22:05:37 +04:00
}
2010-04-02 20:47:02 +04:00
/*
* kgdb_handle_exception ( ) - main entry point from a kernel exception
*
* Locking hierarchy :
* interface locks , if any ( begin_session )
* kgdb lock ( kgdb_active )
*/
int
kgdb_handle_exception ( int evector , int signo , int ecode , struct pt_regs * regs )
{
struct kgdb_state kgdb_var ;
struct kgdb_state * ks = & kgdb_var ;
int ret ;
ks - > cpu = raw_smp_processor_id ( ) ;
ks - > ex_vector = evector ;
ks - > signo = signo ;
ks - > ex_vector = evector ;
ks - > err_code = ecode ;
ks - > kgdb_usethreadid = 0 ;
ks - > linux_regs = regs ;
if ( kgdb_reenter_check ( ks ) )
return 0 ; /* Ouch, double exception ! */
kgdb_info [ ks - > cpu ] . exception_state | = DCPU_WANT_MASTER ;
ret = kgdb_cpu_enter ( ks , regs ) ;
2010-05-21 06:04:21 +04:00
kgdb_info [ ks - > cpu ] . exception_state & = ~ ( DCPU_WANT_MASTER |
DCPU_IS_SLAVE ) ;
2010-04-02 20:47:02 +04:00
return ret ;
}
2008-04-17 22:05:37 +04:00
int kgdb_nmicallback ( int cpu , void * regs )
{
# ifdef CONFIG_SMP
2010-04-02 20:47:02 +04:00
struct kgdb_state kgdb_var ;
struct kgdb_state * ks = & kgdb_var ;
memset ( ks , 0 , sizeof ( struct kgdb_state ) ) ;
ks - > cpu = cpu ;
ks - > linux_regs = regs ;
2008-04-17 22:05:37 +04:00
if ( ! atomic_read ( & cpu_in_kgdb [ cpu ] ) & &
2010-04-02 20:47:02 +04:00
atomic_read ( & kgdb_active ) ! = - 1 & &
atomic_read ( & kgdb_active ) ! = cpu ) {
kgdb_info [ cpu ] . exception_state | = DCPU_IS_SLAVE ;
kgdb_cpu_enter ( ks , regs ) ;
kgdb_info [ cpu ] . exception_state & = ~ DCPU_IS_SLAVE ;
2008-04-17 22:05:37 +04:00
return 0 ;
}
# endif
return 1 ;
}
2008-06-24 19:52:55 +04:00
static void kgdb_console_write ( struct console * co , const char * s ,
unsigned count )
2008-04-17 22:05:37 +04:00
{
unsigned long flags ;
/* If we're debugging, or KGDB has not connected, don't try
* and print . */
2010-05-21 06:04:21 +04:00
if ( ! kgdb_connected | | atomic_read ( & kgdb_active ) ! = - 1 | | dbg_kdb_mode )
2008-04-17 22:05:37 +04:00
return ;
local_irq_save ( flags ) ;
2010-04-02 20:48:03 +04:00
gdbstub_msg_write ( s , count ) ;
2008-04-17 22:05:37 +04:00
local_irq_restore ( flags ) ;
}
static struct console kgdbcons = {
. name = " kgdb " ,
. write = kgdb_console_write ,
. flags = CON_PRINTBUFFER | CON_ENABLED ,
. index = - 1 ,
} ;
# ifdef CONFIG_MAGIC_SYSRQ
2010-04-02 20:48:03 +04:00
static void sysrq_handle_dbg ( int key , struct tty_struct * tty )
2008-04-17 22:05:37 +04:00
{
2010-04-02 20:48:03 +04:00
if ( ! dbg_io_ops ) {
2008-04-17 22:05:37 +04:00
printk ( KERN_CRIT " ERROR: No KGDB I/O module available \n " ) ;
return ;
}
2010-05-21 06:04:21 +04:00
if ( ! kgdb_connected ) {
# ifdef CONFIG_KGDB_KDB
if ( ! dbg_kdb_mode )
printk ( KERN_CRIT " KGDB or $3#33 for KDB \n " ) ;
# else
2008-04-17 22:05:37 +04:00
printk ( KERN_CRIT " Entering KGDB \n " ) ;
2010-05-21 06:04:21 +04:00
# endif
}
2008-04-17 22:05:37 +04:00
kgdb_breakpoint ( ) ;
}
2010-04-02 20:48:03 +04:00
static struct sysrq_key_op sysrq_dbg_op = {
. handler = sysrq_handle_dbg ,
2009-05-14 06:56:59 +04:00
. help_msg = " debug(G) " ,
. action_msg = " DEBUG " ,
2008-04-17 22:05:37 +04:00
} ;
# endif
static void kgdb_register_callbacks ( void )
{
if ( ! kgdb_io_module_registered ) {
kgdb_io_module_registered = 1 ;
kgdb_arch_init ( ) ;
# ifdef CONFIG_MAGIC_SYSRQ
2010-04-02 20:48:03 +04:00
register_sysrq_key ( ' g ' , & sysrq_dbg_op ) ;
2008-04-17 22:05:37 +04:00
# endif
if ( kgdb_use_con & & ! kgdb_con_registered ) {
register_console ( & kgdbcons ) ;
kgdb_con_registered = 1 ;
}
}
}
static void kgdb_unregister_callbacks ( void )
{
/*
* When this routine is called KGDB should unregister from the
* panic handler and clean up , making sure it is not handling any
* break exceptions at the time .
*/
if ( kgdb_io_module_registered ) {
kgdb_io_module_registered = 0 ;
kgdb_arch_exit ( ) ;
# ifdef CONFIG_MAGIC_SYSRQ
2010-04-02 20:48:03 +04:00
unregister_sysrq_key ( ' g ' , & sysrq_dbg_op ) ;
2008-04-17 22:05:37 +04:00
# endif
if ( kgdb_con_registered ) {
unregister_console ( & kgdbcons ) ;
kgdb_con_registered = 0 ;
}
}
}
static void kgdb_initial_breakpoint ( void )
{
kgdb_break_asap = 0 ;
printk ( KERN_CRIT " kgdb: Waiting for connection from remote gdb... \n " ) ;
kgdb_breakpoint ( ) ;
}
/**
2008-03-08 01:34:16 +03:00
* kgdb_register_io_module - register KGDB IO module
2010-04-02 20:48:03 +04:00
* @ new_dbg_io_ops : the io ops vector
2008-04-17 22:05:37 +04:00
*
* Register it with the KGDB core .
*/
2010-04-02 20:48:03 +04:00
int kgdb_register_io_module ( struct kgdb_io * new_dbg_io_ops )
2008-04-17 22:05:37 +04:00
{
int err ;
spin_lock ( & kgdb_registration_lock ) ;
2010-04-02 20:48:03 +04:00
if ( dbg_io_ops ) {
2008-04-17 22:05:37 +04:00
spin_unlock ( & kgdb_registration_lock ) ;
printk ( KERN_ERR " kgdb: Another I/O driver is already "
" registered with KGDB. \n " ) ;
return - EBUSY ;
}
2010-04-02 20:48:03 +04:00
if ( new_dbg_io_ops - > init ) {
err = new_dbg_io_ops - > init ( ) ;
2008-04-17 22:05:37 +04:00
if ( err ) {
spin_unlock ( & kgdb_registration_lock ) ;
return err ;
}
}
2010-04-02 20:48:03 +04:00
dbg_io_ops = new_dbg_io_ops ;
2008-04-17 22:05:37 +04:00
spin_unlock ( & kgdb_registration_lock ) ;
printk ( KERN_INFO " kgdb: Registered I/O driver %s. \n " ,
2010-04-02 20:48:03 +04:00
new_dbg_io_ops - > name ) ;
2008-04-17 22:05:37 +04:00
/* Arm KGDB now. */
kgdb_register_callbacks ( ) ;
if ( kgdb_break_asap )
kgdb_initial_breakpoint ( ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( kgdb_register_io_module ) ;
/**
* kkgdb_unregister_io_module - unregister KGDB IO module
2010-04-02 20:48:03 +04:00
* @ old_dbg_io_ops : the io ops vector
2008-04-17 22:05:37 +04:00
*
* Unregister it with the KGDB core .
*/
2010-04-02 20:48:03 +04:00
void kgdb_unregister_io_module ( struct kgdb_io * old_dbg_io_ops )
2008-04-17 22:05:37 +04:00
{
BUG_ON ( kgdb_connected ) ;
/*
* KGDB is no longer able to communicate out , so
* unregister our callbacks and reset state .
*/
kgdb_unregister_callbacks ( ) ;
spin_lock ( & kgdb_registration_lock ) ;
2010-04-02 20:48:03 +04:00
WARN_ON_ONCE ( dbg_io_ops ! = old_dbg_io_ops ) ;
dbg_io_ops = NULL ;
2008-04-17 22:05:37 +04:00
spin_unlock ( & kgdb_registration_lock ) ;
printk ( KERN_INFO
" kgdb: Unregistered I/O driver %s, debugger disabled. \n " ,
2010-04-02 20:48:03 +04:00
old_dbg_io_ops - > name ) ;
2008-04-17 22:05:37 +04:00
}
EXPORT_SYMBOL_GPL ( kgdb_unregister_io_module ) ;
2010-05-21 06:04:21 +04:00
int dbg_io_get_char ( void )
{
int ret = dbg_io_ops - > read_char ( ) ;
if ( ! dbg_kdb_mode )
return ret ;
if ( ret = = 127 )
return 8 ;
return ret ;
}
2008-04-17 22:05:37 +04:00
/**
* kgdb_breakpoint - generate breakpoint exception
*
* This function will generate a breakpoint exception . It is used at the
* beginning of a program to sync up with a debugger and can be used
* otherwise as a quick means to stop program execution and " break " into
* the debugger .
*/
void kgdb_breakpoint ( void )
{
2010-04-02 23:58:18 +04:00
atomic_inc ( & kgdb_setting_breakpoint ) ;
2008-04-17 22:05:37 +04:00
wmb ( ) ; /* Sync point before breakpoint */
arch_kgdb_breakpoint ( ) ;
wmb ( ) ; /* Sync point after breakpoint */
2010-04-02 23:58:18 +04:00
atomic_dec ( & kgdb_setting_breakpoint ) ;
2008-04-17 22:05:37 +04:00
}
EXPORT_SYMBOL_GPL ( kgdb_breakpoint ) ;
static int __init opt_kgdb_wait ( char * str )
{
kgdb_break_asap = 1 ;
2010-05-21 06:04:21 +04:00
kdb_init ( KDB_INIT_EARLY ) ;
2008-04-17 22:05:37 +04:00
if ( kgdb_io_module_registered )
kgdb_initial_breakpoint ( ) ;
return 0 ;
}
early_param ( " kgdbwait " , opt_kgdb_wait ) ;