Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb:
  kgdboc,tty: Fix tty polling search to use name correctly
  kgdb, x86_64: fix PS CS SS registers in gdb serial
  kgdb, x86_64: gdb serial has BX and DX reversed
  kgdb, x86, arm, mips, powerpc: ignore user space single stepping
  kgdb: could not write to the last of valid memory with kgdb
This commit is contained in:
Linus Torvalds 2008-09-29 08:30:11 -07:00
commit 929675d58c
7 changed files with 63 additions and 38 deletions

View file

@ -111,8 +111,6 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
case 'D': case 'D':
case 'k': case 'k':
case 'c': case 'c':
kgdb_contthread = NULL;
/* /*
* Try to read optional parameter, pc unchanged if no parm. * Try to read optional parameter, pc unchanged if no parm.
* If this was a compiled breakpoint, we need to move * If this was a compiled breakpoint, we need to move

View file

@ -236,8 +236,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
atomic_set(&kgdb_cpu_doing_single_step, -1); atomic_set(&kgdb_cpu_doing_single_step, -1);
if (remcom_in_buffer[0] == 's') if (remcom_in_buffer[0] == 's')
if (kgdb_contthread) atomic_set(&kgdb_cpu_doing_single_step, cpu);
atomic_set(&kgdb_cpu_doing_single_step, cpu);
return 0; return 0;
} }

View file

@ -347,9 +347,8 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
linux_regs->msr |= MSR_SE; linux_regs->msr |= MSR_SE;
#endif #endif
kgdb_single_step = 1; kgdb_single_step = 1;
if (kgdb_contthread) atomic_set(&kgdb_cpu_doing_single_step,
atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
raw_smp_processor_id());
} }
return 0; return 0;
} }

View file

@ -69,6 +69,9 @@ static int gdb_x86vector = -1;
*/ */
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{ {
#ifndef CONFIG_X86_32
u32 *gdb_regs32 = (u32 *)gdb_regs;
#endif
gdb_regs[GDB_AX] = regs->ax; gdb_regs[GDB_AX] = regs->ax;
gdb_regs[GDB_BX] = regs->bx; gdb_regs[GDB_BX] = regs->bx;
gdb_regs[GDB_CX] = regs->cx; gdb_regs[GDB_CX] = regs->cx;
@ -76,9 +79,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
gdb_regs[GDB_SI] = regs->si; gdb_regs[GDB_SI] = regs->si;
gdb_regs[GDB_DI] = regs->di; gdb_regs[GDB_DI] = regs->di;
gdb_regs[GDB_BP] = regs->bp; gdb_regs[GDB_BP] = regs->bp;
gdb_regs[GDB_PS] = regs->flags;
gdb_regs[GDB_PC] = regs->ip; gdb_regs[GDB_PC] = regs->ip;
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
gdb_regs[GDB_PS] = regs->flags;
gdb_regs[GDB_DS] = regs->ds; gdb_regs[GDB_DS] = regs->ds;
gdb_regs[GDB_ES] = regs->es; gdb_regs[GDB_ES] = regs->es;
gdb_regs[GDB_CS] = regs->cs; gdb_regs[GDB_CS] = regs->cs;
@ -94,6 +97,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
gdb_regs[GDB_R13] = regs->r13; gdb_regs[GDB_R13] = regs->r13;
gdb_regs[GDB_R14] = regs->r14; gdb_regs[GDB_R14] = regs->r14;
gdb_regs[GDB_R15] = regs->r15; gdb_regs[GDB_R15] = regs->r15;
gdb_regs32[GDB_PS] = regs->flags;
gdb_regs32[GDB_CS] = regs->cs;
gdb_regs32[GDB_SS] = regs->ss;
#endif #endif
gdb_regs[GDB_SP] = regs->sp; gdb_regs[GDB_SP] = regs->sp;
} }
@ -112,6 +118,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
*/ */
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{ {
#ifndef CONFIG_X86_32
u32 *gdb_regs32 = (u32 *)gdb_regs;
#endif
gdb_regs[GDB_AX] = 0; gdb_regs[GDB_AX] = 0;
gdb_regs[GDB_BX] = 0; gdb_regs[GDB_BX] = 0;
gdb_regs[GDB_CX] = 0; gdb_regs[GDB_CX] = 0;
@ -129,8 +138,10 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
gdb_regs[GDB_FS] = 0xFFFF; gdb_regs[GDB_FS] = 0xFFFF;
gdb_regs[GDB_GS] = 0xFFFF; gdb_regs[GDB_GS] = 0xFFFF;
#else #else
gdb_regs[GDB_PS] = *(unsigned long *)(p->thread.sp + 8); gdb_regs32[GDB_PS] = *(unsigned long *)(p->thread.sp + 8);
gdb_regs[GDB_PC] = 0; gdb_regs32[GDB_CS] = __KERNEL_CS;
gdb_regs32[GDB_SS] = __KERNEL_DS;
gdb_regs[GDB_PC] = p->thread.ip;
gdb_regs[GDB_R8] = 0; gdb_regs[GDB_R8] = 0;
gdb_regs[GDB_R9] = 0; gdb_regs[GDB_R9] = 0;
gdb_regs[GDB_R10] = 0; gdb_regs[GDB_R10] = 0;
@ -153,6 +164,9 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
*/ */
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{ {
#ifndef CONFIG_X86_32
u32 *gdb_regs32 = (u32 *)gdb_regs;
#endif
regs->ax = gdb_regs[GDB_AX]; regs->ax = gdb_regs[GDB_AX];
regs->bx = gdb_regs[GDB_BX]; regs->bx = gdb_regs[GDB_BX];
regs->cx = gdb_regs[GDB_CX]; regs->cx = gdb_regs[GDB_CX];
@ -160,9 +174,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
regs->si = gdb_regs[GDB_SI]; regs->si = gdb_regs[GDB_SI];
regs->di = gdb_regs[GDB_DI]; regs->di = gdb_regs[GDB_DI];
regs->bp = gdb_regs[GDB_BP]; regs->bp = gdb_regs[GDB_BP];
regs->flags = gdb_regs[GDB_PS];
regs->ip = gdb_regs[GDB_PC]; regs->ip = gdb_regs[GDB_PC];
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
regs->flags = gdb_regs[GDB_PS];
regs->ds = gdb_regs[GDB_DS]; regs->ds = gdb_regs[GDB_DS];
regs->es = gdb_regs[GDB_ES]; regs->es = gdb_regs[GDB_ES];
regs->cs = gdb_regs[GDB_CS]; regs->cs = gdb_regs[GDB_CS];
@ -175,6 +189,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
regs->r13 = gdb_regs[GDB_R13]; regs->r13 = gdb_regs[GDB_R13];
regs->r14 = gdb_regs[GDB_R14]; regs->r14 = gdb_regs[GDB_R14];
regs->r15 = gdb_regs[GDB_R15]; regs->r15 = gdb_regs[GDB_R15];
regs->flags = gdb_regs32[GDB_PS];
regs->cs = gdb_regs32[GDB_CS];
regs->ss = gdb_regs32[GDB_SS];
#endif #endif
} }
@ -378,10 +395,8 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
if (remcomInBuffer[0] == 's') { if (remcomInBuffer[0] == 's') {
linux_regs->flags |= X86_EFLAGS_TF; linux_regs->flags |= X86_EFLAGS_TF;
kgdb_single_step = 1; kgdb_single_step = 1;
if (kgdb_contthread) { atomic_set(&kgdb_cpu_doing_single_step,
atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
raw_smp_processor_id());
}
} }
get_debugreg(dr6, 6); get_debugreg(dr6, 6);
@ -466,9 +481,15 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
case DIE_DEBUG: case DIE_DEBUG:
if (atomic_read(&kgdb_cpu_doing_single_step) == if (atomic_read(&kgdb_cpu_doing_single_step) ==
raw_smp_processor_id() && raw_smp_processor_id()) {
user_mode(regs)) if (user_mode(regs))
return single_step_cont(regs, args); return single_step_cont(regs, args);
break;
} else if (test_thread_flag(TIF_SINGLESTEP))
/* This means a user thread is single stepping
* a system call which should be ignored
*/
return NOTIFY_DONE;
/* fall through */ /* fall through */
default: default:
if (user_mode(regs)) if (user_mode(regs))

View file

@ -695,13 +695,23 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
{ {
struct tty_driver *p, *res = NULL; struct tty_driver *p, *res = NULL;
int tty_line = 0; int tty_line = 0;
int len;
char *str; char *str;
for (str = name; *str; str++)
if ((*str >= '0' && *str <= '9') || *str == ',')
break;
if (!*str)
return NULL;
len = str - name;
tty_line = simple_strtoul(str, &str, 10);
mutex_lock(&tty_mutex); mutex_lock(&tty_mutex);
/* Search through the tty devices to look for a match */ /* Search through the tty devices to look for a match */
list_for_each_entry(p, &tty_drivers, tty_drivers) { list_for_each_entry(p, &tty_drivers, tty_drivers) {
str = name + strlen(p->name); if (strncmp(name, p->name, len) != 0)
tty_line = simple_strtoul(str, &str, 10); continue;
if (*str == ',') if (*str == ',')
str++; str++;
if (*str == '\0') if (*str == '\0')

View file

@ -39,12 +39,13 @@ enum regnames {
GDB_FS, /* 14 */ GDB_FS, /* 14 */
GDB_GS, /* 15 */ GDB_GS, /* 15 */
}; };
#define NUMREGBYTES ((GDB_GS+1)*4)
#else /* ! CONFIG_X86_32 */ #else /* ! CONFIG_X86_32 */
enum regnames { enum regnames64 {
GDB_AX, /* 0 */ GDB_AX, /* 0 */
GDB_DX, /* 1 */ GDB_BX, /* 1 */
GDB_CX, /* 2 */ GDB_CX, /* 2 */
GDB_BX, /* 3 */ GDB_DX, /* 3 */
GDB_SI, /* 4 */ GDB_SI, /* 4 */
GDB_DI, /* 5 */ GDB_DI, /* 5 */
GDB_BP, /* 6 */ GDB_BP, /* 6 */
@ -58,18 +59,15 @@ enum regnames {
GDB_R14, /* 14 */ GDB_R14, /* 14 */
GDB_R15, /* 15 */ GDB_R15, /* 15 */
GDB_PC, /* 16 */ GDB_PC, /* 16 */
GDB_PS, /* 17 */
}; };
#endif /* CONFIG_X86_32 */
/* enum regnames32 {
* Number of bytes of registers: GDB_PS = 34,
*/ GDB_CS,
#ifdef CONFIG_X86_32 GDB_SS,
# define NUMREGBYTES 64 };
#else #define NUMREGBYTES ((GDB_SS+1)*4)
# define NUMREGBYTES ((GDB_PS+1)*8) #endif /* CONFIG_X86_32 */
#endif
static inline void arch_kgdb_breakpoint(void) static inline void arch_kgdb_breakpoint(void)
{ {

View file

@ -488,7 +488,7 @@ static int write_mem_msg(int binary)
if (err) if (err)
return err; return err;
if (CACHE_FLUSH_IS_SAFE) if (CACHE_FLUSH_IS_SAFE)
flush_icache_range(addr, addr + length + 1); flush_icache_range(addr, addr + length);
return 0; return 0;
} }
@ -1462,7 +1462,7 @@ acquirelock:
* Get the passive CPU lock which will hold all the non-primary * Get the passive CPU lock which will hold all the non-primary
* CPU in a spin state while the debugger is active * CPU in a spin state while the debugger is active
*/ */
if (!kgdb_single_step || !kgdb_contthread) { if (!kgdb_single_step) {
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
atomic_set(&passive_cpu_wait[i], 1); atomic_set(&passive_cpu_wait[i], 1);
} }
@ -1475,7 +1475,7 @@ acquirelock:
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Signal the other CPUs to enter kgdb_wait() */ /* Signal the other CPUs to enter kgdb_wait() */
if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup) if ((!kgdb_single_step) && kgdb_do_roundup)
kgdb_roundup_cpus(flags); kgdb_roundup_cpus(flags);
#endif #endif
@ -1494,7 +1494,7 @@ acquirelock:
kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code);
kgdb_deactivate_sw_breakpoints(); kgdb_deactivate_sw_breakpoints();
kgdb_single_step = 0; kgdb_single_step = 0;
kgdb_contthread = NULL; kgdb_contthread = current;
exception_level = 0; exception_level = 0;
/* Talk to debugger with gdbserial protocol */ /* Talk to debugger with gdbserial protocol */
@ -1508,7 +1508,7 @@ acquirelock:
kgdb_info[ks->cpu].task = NULL; kgdb_info[ks->cpu].task = NULL;
atomic_set(&cpu_in_kgdb[ks->cpu], 0); atomic_set(&cpu_in_kgdb[ks->cpu], 0);
if (!kgdb_single_step || !kgdb_contthread) { if (!kgdb_single_step) {
for (i = NR_CPUS-1; i >= 0; i--) for (i = NR_CPUS-1; i >= 0; i--)
atomic_set(&passive_cpu_wait[i], 0); atomic_set(&passive_cpu_wait[i], 0);
/* /*