Commit 5d00b860 authored by Stephen Rothwell's avatar Stephen Rothwell

Merge commit 'kgdb/kgdb-next'

parents 2acf90bd 98517d8f
...@@ -85,10 +85,15 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) ...@@ -85,10 +85,15 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
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;
gdb_regs[GDB_SS] = __KERNEL_DS;
gdb_regs[GDB_FS] = 0xFFFF; gdb_regs[GDB_FS] = 0xFFFF;
gdb_regs[GDB_GS] = 0xFFFF; gdb_regs[GDB_GS] = 0xFFFF;
gdb_regs[GDB_SP] = (int)&regs->sp; if (user_mode_vm(regs)) {
gdb_regs[GDB_SS] = regs->ss;
gdb_regs[GDB_SP] = regs->sp;
} else {
gdb_regs[GDB_SS] = __KERNEL_DS;
gdb_regs[GDB_SP] = (unsigned long)&regs->sp;
}
#else #else
gdb_regs[GDB_R8] = regs->r8; gdb_regs[GDB_R8] = regs->r8;
gdb_regs[GDB_R9] = regs->r9; gdb_regs[GDB_R9] = regs->r9;
...@@ -220,7 +225,6 @@ static void kgdb_correct_hw_break(void) ...@@ -220,7 +225,6 @@ static void kgdb_correct_hw_break(void)
dr7 |= ((breakinfo[breakno].len << 2) | dr7 |= ((breakinfo[breakno].len << 2) |
breakinfo[breakno].type) << breakinfo[breakno].type) <<
((breakno << 2) + 16); ((breakno << 2) + 16);
if (breakno >= 0 && breakno <= 3)
set_debugreg(breakinfo[breakno].addr, breakno); set_debugreg(breakinfo[breakno].addr, breakno);
} else { } else {
......
...@@ -302,6 +302,7 @@ extern void sched_show_task(struct task_struct *p); ...@@ -302,6 +302,7 @@ extern void sched_show_task(struct task_struct *p);
#ifdef CONFIG_DETECT_SOFTLOCKUP #ifdef CONFIG_DETECT_SOFTLOCKUP
extern void softlockup_tick(void); extern void softlockup_tick(void);
extern void touch_softlockup_watchdog(void); extern void touch_softlockup_watchdog(void);
extern void touch_softlockup_watchdog_sync(void);
extern void touch_all_softlockup_watchdogs(void); extern void touch_all_softlockup_watchdogs(void);
extern int proc_dosoftlockup_thresh(struct ctl_table *table, int write, extern int proc_dosoftlockup_thresh(struct ctl_table *table, int write,
struct file *filp, void __user *buffer, struct file *filp, void __user *buffer,
...@@ -315,6 +316,9 @@ static inline void softlockup_tick(void) ...@@ -315,6 +316,9 @@ static inline void softlockup_tick(void)
static inline void touch_softlockup_watchdog(void) static inline void touch_softlockup_watchdog(void)
{ {
} }
static inline void touch_softlockup_watchdog_sync(void)
{
}
static inline void touch_all_softlockup_watchdogs(void) static inline void touch_all_softlockup_watchdogs(void)
{ {
} }
......
...@@ -129,6 +129,7 @@ struct task_struct *kgdb_usethread; ...@@ -129,6 +129,7 @@ struct task_struct *kgdb_usethread;
struct task_struct *kgdb_contthread; struct task_struct *kgdb_contthread;
int kgdb_single_step; int kgdb_single_step;
pid_t kgdb_sstep_pid;
/* Our I/O buffers. */ /* Our I/O buffers. */
static char remcom_in_buffer[BUFMAX]; static char remcom_in_buffer[BUFMAX];
...@@ -541,12 +542,17 @@ static struct task_struct *getthread(struct pt_regs *regs, int tid) ...@@ -541,12 +542,17 @@ static struct task_struct *getthread(struct pt_regs *regs, int tid)
*/ */
if (tid == 0 || tid == -1) if (tid == 0 || tid == -1)
tid = -atomic_read(&kgdb_active) - 2; tid = -atomic_read(&kgdb_active) - 2;
if (tid < 0) { if (tid < -1 && tid > -NR_CPUS - 2) {
if (kgdb_info[-tid - 2].task) if (kgdb_info[-tid - 2].task)
return kgdb_info[-tid - 2].task; return kgdb_info[-tid - 2].task;
else else
return idle_task(-tid - 2); return idle_task(-tid - 2);
} }
if (tid <= 0) {
printk(KERN_ERR "KGDB: Internal thread select error\n");
dump_stack();
return NULL;
}
/* /*
* find_task_by_pid_ns() does not take the tasklist lock anymore * find_task_by_pid_ns() does not take the tasklist lock anymore
...@@ -590,7 +596,7 @@ static void kgdb_wait(struct pt_regs *regs) ...@@ -590,7 +596,7 @@ static void kgdb_wait(struct pt_regs *regs)
/* Signal the primary CPU that we are done: */ /* Signal the primary CPU that we are done: */
atomic_set(&cpu_in_kgdb[cpu], 0); atomic_set(&cpu_in_kgdb[cpu], 0);
touch_softlockup_watchdog(); touch_softlockup_watchdog_sync();
clocksource_touch_watchdog(); clocksource_touch_watchdog();
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -1204,8 +1210,10 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks) ...@@ -1204,8 +1210,10 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks)
return 1; return 1;
} else { } else {
error_packet(remcom_out_buffer, -EINVAL); kgdb_msg_write("KGDB only knows signal 9 (pass)"
return 0; " and 15 (pass and disconnect)\n"
"Executing a continue without signal passing\n", 0);
remcom_in_buffer[0] = 'c';
} }
/* Indicate fall through */ /* Indicate fall through */
...@@ -1430,10 +1438,10 @@ acquirelock: ...@@ -1430,10 +1438,10 @@ acquirelock:
* debugger on a different CPU via a single step * debugger on a different CPU via a single step
*/ */
if (atomic_read(&kgdb_cpu_doing_single_step) != -1 && if (atomic_read(&kgdb_cpu_doing_single_step) != -1 &&
atomic_read(&kgdb_cpu_doing_single_step) != cpu) { kgdb_info[cpu].task &&
kgdb_info[cpu].task->pid != kgdb_sstep_pid) {
atomic_set(&kgdb_active, -1); atomic_set(&kgdb_active, -1);
touch_softlockup_watchdog(); touch_softlockup_watchdog_sync();
clocksource_touch_watchdog(); clocksource_touch_watchdog();
local_irq_restore(flags); local_irq_restore(flags);
...@@ -1524,9 +1532,16 @@ acquirelock: ...@@ -1524,9 +1532,16 @@ acquirelock:
} }
kgdb_restore: kgdb_restore:
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;
}
/* Free kgdb_active */ /* Free kgdb_active */
atomic_set(&kgdb_active, -1); atomic_set(&kgdb_active, -1);
touch_softlockup_watchdog(); touch_softlockup_watchdog_sync();
clocksource_touch_watchdog(); clocksource_touch_watchdog();
local_irq_restore(flags); local_irq_restore(flags);
......
...@@ -79,6 +79,14 @@ void touch_softlockup_watchdog(void) ...@@ -79,6 +79,14 @@ void touch_softlockup_watchdog(void)
} }
EXPORT_SYMBOL(touch_softlockup_watchdog); EXPORT_SYMBOL(touch_softlockup_watchdog);
static int softlock_touch_sync[NR_CPUS];
void touch_softlockup_watchdog_sync(void)
{
softlock_touch_sync[raw_smp_processor_id()] = 1;
__raw_get_cpu_var(touch_timestamp) = 0;
}
void touch_all_softlockup_watchdogs(void) void touch_all_softlockup_watchdogs(void)
{ {
int cpu; int cpu;
...@@ -118,6 +126,14 @@ void softlockup_tick(void) ...@@ -118,6 +126,14 @@ void softlockup_tick(void)
} }
if (touch_timestamp == 0) { if (touch_timestamp == 0) {
if (unlikely(softlock_touch_sync[this_cpu])) {
/*
* If the time stamp was touched atomically
* make sure the scheduler tick is up to date.
*/
softlock_touch_sync[this_cpu] = 0;
sched_clock_tick();
}
__touch_softlockup_watchdog(); __touch_softlockup_watchdog();
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment