Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753600AbYJaCLY (ORCPT ); Thu, 30 Oct 2008 22:11:24 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752136AbYJaCLN (ORCPT ); Thu, 30 Oct 2008 22:11:13 -0400 Received: from rv-out-0506.google.com ([209.85.198.228]:47099 "EHLO rv-out-0506.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751554AbYJaCLM (ORCPT ); Thu, 30 Oct 2008 22:11:12 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:cc:in-reply-to:mime-version :content-type:content-transfer-encoding:content-disposition :references; b=CMCsXxbFP4OXbojU/jVUFvvDtRCOGFUlCBnVyM5afMvz2c3cNTpMHsrsXgiqpcwIJr N5IL1smlWWiAzrq1sreQfZYz9fsvZZHh+BHqh3UR/7BuK6K+jdUttlXdIkfnRdsq3B5L Jl9ChpvzentFyPXFYh1cbwy8FVNlpMXs6J5kY= Message-ID: <4e5ebad50810301911mb4eed2du398826e79b0f2e28@mail.gmail.com> Date: Fri, 31 Oct 2008 10:11:11 +0800 From: "Sonic Zhang" To: "Jason Wessel" Subject: Re: [PATCH] [kgdb] Switch master cpu after gdb thread command for SMP (v3) Cc: "Linux Kernel" , "kgdb mailing list" In-Reply-To: <1224664817.15846.1.camel@eight.analog.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <1224664817.15846.1.camel@eight.analog.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10262 Lines: 268 Hi Jason, Does this patch applied on your developing tree well? Any comments? Thanks Sonic On Wed, Oct 22, 2008 at 4:40 PM, sonic zhang wrote: > In blackfin SMP architecture, different core has its own L1 SRAM and MMR > memory, which code running on the other core can't access. In current kgdb > impelemntation, cpus are represented by thread with minus prefix. > > If user run thread command in gdb to switch to the thread of the other cpu, > kgdb should: > 1. send IPI signal to master cpu > 2. release the specific passive cpu waiting in IPI handler > 3. exit kgdb exception loop on master cpu and trap into kgdb wait in IPI handler > 4. trap the released passive cpu into kgdb exception in IPI handler > > Signed-off-by: Sonic Zhang > --- > include/linux/kgdb.h | 16 +++++++++++- > kernel/kgdb.c | 66 +++++++++++++++++++++++++++++++++++++++++++------- > 2 files changed, 72 insertions(+), 10 deletions(-) > > diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h > index 6adcc29..664e396 100644 > --- a/include/linux/kgdb.h > +++ b/include/linux/kgdb.h > @@ -106,7 +106,8 @@ struct kgdb_bkpt { > # define KGDB_MAX_BREAKPOINTS 1000 > #endif > > -#define KGDB_HW_BREAKPOINT 1 > +#define KGDB_HW_BREAKPOINT 0x1 > +#define KGDB_THR_PROC_SWAP 0x2 > > /* > * Functions each KGDB-supporting architecture must provide: > @@ -203,6 +204,19 @@ kgdb_arch_handle_exception(int vector, int signo, int err_code, > */ > extern void kgdb_roundup_cpus(unsigned long flags); > > +/** > + * kgdb_roundup_cpu - Get spcific CPU into a holding pattern > + * @cpu: Specific cpu id > + * @flags: Current IRQ state > + * > + * On SMP systems, we need to switch cpu from current active one to > + * the other passive one. This get current active CPU into a known state > + * in kgdb_wait(). > + * > + * On non-SMP systems, this is not called. > + */ > +extern void kgdb_roundup_cpu(int cpu, unsigned long flags); > + > /* Optional functions. */ > extern int kgdb_validate_break_address(unsigned long addr); > extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr); > diff --git a/kernel/kgdb.c b/kernel/kgdb.c > index e4dcfb2..277986d 100644 > --- a/kernel/kgdb.c > +++ b/kernel/kgdb.c > @@ -565,6 +565,7 @@ static void kgdb_wait(struct pt_regs *regs) > { > unsigned long flags; > int cpu; > + struct task_struct *thread; > > local_irq_save(flags); > cpu = raw_smp_processor_id(); > @@ -577,6 +578,8 @@ static void kgdb_wait(struct pt_regs *regs) > smp_wmb(); > atomic_set(&cpu_in_kgdb[cpu], 1); > > + kgdb_disable_hw_debug(regs); > + > /* Wait till primary CPU is done with debugging */ > while (atomic_read(&passive_cpu_wait[cpu])) > cpu_relax(); > @@ -584,6 +587,16 @@ static void kgdb_wait(struct pt_regs *regs) > kgdb_info[cpu].debuggerinfo = NULL; > kgdb_info[cpu].task = NULL; > > + /* Trap into kgdb as the active CPU if gdb asks to switch. */ > + thread = getthread(regs, -raw_smp_processor_id() - 2); > + if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) && > + kgdb_contthread && kgdb_contthread == thread) { > + kgdb_breakpoint(); > + clocksource_touch_watchdog(); > + local_irq_restore(flags); > + return; > + } > + > /* fix up hardware debug registers on local cpu */ > if (arch_kgdb_ops.correct_hw_break) > arch_kgdb_ops.correct_hw_break(); > @@ -1066,13 +1079,16 @@ static void gdb_cmd_query(struct kgdb_state *ks) > sprintf(tmpstr, "shadowCPU%d", > (int)(-ks->threadid - 2)); > kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr)); > + > + if (arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) > + ks->thr_query = 1; > } > break; > } > } > > /* Handle the 'H' task query packets */ > -static void gdb_cmd_task(struct kgdb_state *ks) > +static int gdb_cmd_task(struct kgdb_state *ks) > { > struct task_struct *thread; > char *ptr; > @@ -1089,6 +1105,15 @@ static void gdb_cmd_task(struct kgdb_state *ks) > kgdb_usethread = thread; > ks->kgdb_usethreadid = ks->threadid; > strcpy(remcom_out_buffer, "OK"); > +#ifdef CONFIG_SMP > + if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) && > + !ks->thr_query && ks->kgdb_usethreadid < -1 && > + - ks->kgdb_usethreadid - 2 != raw_smp_processor_id()) { > + kgdb_roundup_cpu(raw_smp_processor_id(), 0); > + kgdb_contthread = kgdb_usethread; > + return 1; > + } > +#endif > break; > case 'c': > ptr = &remcom_in_buffer[2]; > @@ -1106,6 +1131,8 @@ static void gdb_cmd_task(struct kgdb_state *ks) > strcpy(remcom_out_buffer, "OK"); > break; > } > + > + return 0; > } > > /* Handle the 'T' thread query packets */ > @@ -1114,6 +1141,9 @@ static void gdb_cmd_thread(struct kgdb_state *ks) > char *ptr = &remcom_in_buffer[1]; > struct task_struct *thread; > > + if (arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) > + ks->thr_query = 0; > + > kgdb_hex2long(&ptr, &ks->threadid); > thread = getthread(ks->linux_regs, ks->threadid); > if (thread) > @@ -1223,7 +1253,12 @@ static int gdb_serial_stub(struct kgdb_state *ks) > /* Clear the out buffer. */ > memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer)); > > - if (kgdb_connected) { > + if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) && kgdb_contthread) { > + remcom_out_buffer[0] = 'O'; > + remcom_out_buffer[1] = 'K'; > + remcom_out_buffer[2] = 0; > + put_packet(remcom_out_buffer); > + } else if (kgdb_connected) { > unsigned char thref[8]; > char *ptr; > > @@ -1238,6 +1273,7 @@ static int gdb_serial_stub(struct kgdb_state *ks) > put_packet(remcom_out_buffer); > } > > + kgdb_contthread = current; > kgdb_usethread = kgdb_info[ks->cpu].task; > ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid); > ks->pass_exception = 0; > @@ -1284,7 +1320,8 @@ static int gdb_serial_stub(struct kgdb_state *ks) > gdb_cmd_query(ks); > break; > case 'H': /* task related */ > - gdb_cmd_task(ks); > + if (gdb_cmd_task(ks)) > + goto kgdb_exit; > break; > case 'T': /* Query thread status */ > gdb_cmd_thread(ks); > @@ -1324,6 +1361,7 @@ default_handle: > if (error >= 0 || remcom_in_buffer[0] == 'D' || > remcom_in_buffer[0] == 'k') { > error = 0; > + kgdb_contthread = NULL; > goto kgdb_exit; > } > > @@ -1464,11 +1502,15 @@ acquirelock: > * Get the passive CPU lock which will hold all the non-primary > * CPU in a spin state while the debugger is active > */ > - if (!kgdb_single_step) { > + if (!kgdb_single_step && !kgdb_contthread) { > for (i = 0; i < NR_CPUS; i++) > atomic_set(&passive_cpu_wait[i], 1); > } > > + if (kgdb_contthread) > + atomic_set(&passive_cpu_wait[raw_smp_processor_id()], 1); > + > + > /* > * spin_lock code is good enough as a barrier so we don't > * need one here: > @@ -1477,7 +1519,7 @@ acquirelock: > > #ifdef CONFIG_SMP > /* Signal the other CPUs to enter kgdb_wait() */ > - if ((!kgdb_single_step) && kgdb_do_roundup) > + if ((!kgdb_single_step && !kgdb_contthread) && kgdb_do_roundup) > kgdb_roundup_cpus(flags); > #endif > > @@ -1496,7 +1538,6 @@ acquirelock: > kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); > kgdb_deactivate_sw_breakpoints(); > kgdb_single_step = 0; > - kgdb_contthread = current; > exception_level = 0; > > /* Talk to debugger with gdbserial protocol */ > @@ -1510,7 +1551,14 @@ acquirelock: > kgdb_info[ks->cpu].task = NULL; > atomic_set(&cpu_in_kgdb[ks->cpu], 0); > > - if (!kgdb_single_step) { > +#ifdef CONFIG_SMP > + i = -(ks->kgdb_usethreadid + 2); > + if ((arch_kgdb_ops.flags & KGDB_THR_PROC_SWAP) && > + kgdb_contthread && i != cpu) { > + atomic_set(&passive_cpu_wait[i], 0); > + } > +#endif > + if (!kgdb_single_step && !kgdb_contthread) { > for (i = NR_CPUS-1; i >= 0; i--) > atomic_set(&passive_cpu_wait[i], 0); > /* > @@ -1536,9 +1584,9 @@ kgdb_restore: > int kgdb_nmicallback(int cpu, void *regs) > { > #ifdef CONFIG_SMP > - if (!atomic_read(&cpu_in_kgdb[cpu]) && > + if (!atomic_read(&cpu_in_kgdb[cpu]) && (kgdb_contthread || > atomic_read(&kgdb_active) != cpu && > - atomic_read(&cpu_in_kgdb[atomic_read(&kgdb_active)])) { > + atomic_read(&cpu_in_kgdb[atomic_read(&kgdb_active)]))) { > kgdb_wait((struct pt_regs *)regs); > return 0; > } > -- > 1.6.0 > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/