It is not entirely obvious to me what functions need to be called to
initiate the dump, but since you can do it from sysrq, I assume the
sysrq function could just be called from KGDB.

That way you could simply run something like the following from gdb:
maintenance packet qKexec

Assume that does what you want, then it is easy enough to add to the
text packet handler.

Jason.

> -----Original Message-----
> From: Pete/Piet Delaney [mailto:[EMAIL PROTECTED] 
> Sent: Wednesday, June 20, 2007 2:06 AM
> To: [email protected]; Wessel, Jason
> Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]; Sergei Shtylyov
> Subject: [Fwd: [PATCH] kexec/kdump and kdb] ----> kgdb patch
> 
> to create a KEXEC crash dump after finishing an interactive session.
> 
> Any thought on how hard it would be for us to do the same?
> I suspect that it's easy.
> 
> You could continue your crash analysis on a kernel core file 
> with gdb, or even better, with Dave Anderson's crash program.
> 
> If the attachment doesn't get thru SF you can pick it up on 
> the Keith Owens's KDB news group, 
> gmane.linux.kernel.debugging, at 05/24/2007 at 02:22AM or I 
> can send you a copy if you ask for one.
> 
> -piet
> 
> --------------040402050608090401060307
> Content-Type: message/rfc822;
>  name="[PATCH] kexec/kdump and kdb.eml"
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline;
>  filename="[PATCH] kexec/kdump and kdb.eml"
> 
> Path: news.gmane.org!not-for-mail
> From: Dan Aloni <[EMAIL PROTECTED]>
> Newsgroups: gmane.linux.kernel,gmane.linux.kernel.debugging
> Subject: [PATCH] kexec/kdump and kdb
> Date: Thu, 24 May 2007 12:22:21 +0300
> Approved: [EMAIL PROTECTED]
> Message-ID: <[EMAIL PROTECTED]>
> NNTP-Posting-Host: lo.gmane.org
> Mime-Version: 1.0
> Content-Type: text/plain; charset=us-ascii
> X-Trace: sea.gmane.org 1179998579 20647 80.91.229.12 (24 May 
> 2007 09:22:59 GMT)
> X-Complaints-To: [EMAIL PROTECTED]
> NNTP-Posting-Date: Thu, 24 May 2007 09:22:59 +0000 (UTC)
> To: [EMAIL PROTECTED], Linux Kernel List <[EMAIL PROTECTED]>
> Original-X-From: 
> linux-kernel-owner+glk-linux-kernel-3=40m.gmane.org-S1757574Ab
> [EMAIL PROTECTED] Thu May 24 11:22:53 2007
> Return-path: 
> <linux-kernel-owner+glk-linux-kernel-3=40m.gmane.org-S1757574A
> [EMAIL PROTECTED]>
> Envelope-to: [EMAIL PROTECTED]
> Original-Received: from vger.kernel.org ([209.132.176.167])
>       by lo.gmane.org with esmtp (Exim 4.50)
>       id 1Hr9X1-0000Fn-1J
>       for [EMAIL PROTECTED]; Thu, 24 May 2007 
> 11:22:51 +0200
> Original-Received: ([EMAIL PROTECTED]) by 
> vger.kernel.org via listexpand
>       id S1757574AbXEXJWm (ORCPT 
> <rfc822;[EMAIL PROTECTED]>);
>       Thu, 24 May 2007 05:22:42 -0400
> Original-Received: ([EMAIL PROTECTED]) by 
> vger.kernel.org id S1755052AbXEXJWc
>       (ORCPT <rfc822;linux-kernel-outgoing>);
>       Thu, 24 May 2007 05:22:32 -0400
> Original-Received: from noname.neutralserver.com 
> ([70.84.186.210]:32635 "EHLO
>       noname.neutralserver.com" rhost-flags-OK-OK-OK-OK) by 
> vger.kernel.org
>       with ESMTP id S1754665AbXEXJWa (ORCPT
>       <rfc822;[EMAIL PROTECTED]>);
>       Thu, 24 May 2007 05:22:30 -0400
> Original-Received: from bzq-88-153-198-148.red.bezeqint.net 
> ([88.153.198.148] helo=callisto.gotdns.org)
>       by noname.neutralserver.com with esmtpa (Exim 4.63)
>       (envelope-from <[EMAIL PROTECTED]>)
>       id 1HrAT0-0006FF-H1; Thu, 24 May 2007 05:22:47 -0500
> Content-Disposition: inline
> User-Agent: Mutt/1.5.13 (2006-08-11)
> X-AntiAbuse: This header was added to track abuse, please 
> include it with any abuse report
> X-AntiAbuse: Primary Hostname - noname.neutralserver.com
> X-AntiAbuse: Original Domain - vger.kernel.org
> X-AntiAbuse: Originator/Caller UID/GID - [0 0] / [47 12]
> X-AntiAbuse: Sender Address Domain - monatomic.org
> X-Source: 
> X-Source-Args: 
> X-Source-Dir: 
> Original-Sender: [EMAIL PROTECTED]
> Precedence: bulk
> X-Mailing-List: [EMAIL PROTECTED]
> Xref: news.gmane.org gmane.linux.kernel:533856 
> gmane.linux.kernel.debugging:1468
> Archived-At: <http://permalink.gmane.org/gmane.linux.kernel/533856>
> 
> Hello,
> 
> Below is a very preliminary patch that adds kexec/kdump 
> invocation functionality in kdb. It is currently based on 
> 2.6.20.11 and supported only for x86_64.
> 
> The main use case is for a user who would like to make use of 
> the interactive debugger but wants to conserve the option 
> whether to create a crash dump interactively. It also makes 
> it possible to dump even if the kernel hasn't crashed by 
> manually entering kdb and entering 'kdump' (yes I know sysrq 
> also allows you to trigger a crash dump).
> 
> There are a few issues with this patch (mainly being 
> incomplete), I'd like to check the public interest with this 
> feature before I develop it further.
> 
> 
> diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
> index 95a7a2c..b68a0f5 100644
> --- a/arch/x86_64/kernel/crash.c
> +++ b/arch/x86_64/kernel/crash.c
> @@ -31,6 +31,18 @@ static int crashing_cpu;
>  #ifdef CONFIG_SMP
>  static atomic_t waiting_for_crash_ipi;
>  
> +static void halt_current_cpu(struct pt_regs *regs)
> +{
> +     local_irq_disable();
> +
> +     crash_save_cpu(regs, raw_smp_processor_id());
> +     disable_local_APIC();
> +     atomic_dec(&waiting_for_crash_ipi);
> +     /* Assume hlt works */
> +     for(;;)
> +             halt();
> +}
> +
>  static int crash_nmi_callback(struct notifier_block *self,
>                               unsigned long val, void *data)
>  {
> @@ -50,15 +62,8 @@ static int crash_nmi_callback(struct 
> notifier_block *self,
>        */
>       if (cpu == crashing_cpu)
>               return NOTIFY_STOP;
> -     local_irq_disable();
> -
> -     crash_save_cpu(regs, cpu);
> -     disable_local_APIC();
> -     atomic_dec(&waiting_for_crash_ipi);
> -     /* Assume hlt works */
> -     for(;;)
> -             halt();
>  
> +     halt_current_cpu(regs);
>       return 1;
>  }
>  
> @@ -77,11 +82,26 @@ static struct notifier_block crash_nmi_nb = {
>       .notifier_call = crash_nmi_callback,
>  };
>  
> -static void nmi_shootdown_cpus(void)
> +static void wait_other_cpus(void)
>  {
>       unsigned long msecs;
>  
> +     msecs = 1000; /* Wait at most a second for the other 
> cpus to stop */
> +     while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
> +             mdelay(1);
> +             msecs--;
> +     }
> +}
> +
> +static void nmi_shootdown_cpus_init(void)
> +{
>       atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
> +}
> +
> +static void nmi_shootdown_cpus(void)
> +{
> +     nmi_shootdown_cpus_init();
> +
>       if (register_die_notifier(&crash_nmi_nb))
>               return;         /* return what? */
>  
> @@ -93,19 +113,23 @@ static void nmi_shootdown_cpus(void)
>  
>       smp_send_nmi_allbutself();
>  
> -     msecs = 1000; /* Wait at most a second for the other 
> cpus to stop */
> -     while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
> -             mdelay(1);
> -             msecs--;
> -     }
> +     wait_other_cpus();
>       /* Leave the nmi callback set */
> +
>       disable_local_APIC();
>  }
> +
>  #else
> +
>  static void nmi_shootdown_cpus(void)
>  {
>       /* There are no cpus to shootdown */
>  }
> +
> +static void nmi_shootdown_cpus_init(void) {};
> +static void wait_other_cpus() {}
> +static void halt_current_cpu(struct pt_regs *regs) {};
> +
>  #endif
>  
>  void machine_crash_shutdown(struct pt_regs *regs)
> @@ -133,3 +157,26 @@ void machine_crash_shutdown(struct pt_regs *regs)
>  
>       crash_save_cpu(regs, smp_processor_id());
>  }
> +
> +void machine_crash_shutdown_begin(void)
> +{
> +     local_irq_disable();
> +     nmi_shootdown_cpus_init();
> +}
> +
> +void machine_crash_shutdown_end(struct pt_regs *regs)
> +{
> +     wait_other_cpus();
> +
> +     local_irq_disable();
> +     if(cpu_has_apic)
> +             disable_local_APIC();
> +
> +     disable_IO_APIC();
> +     crash_save_cpu(regs, smp_processor_id());
> +}
> +
> +void machine_crash_shutdown_other_cpu(struct pt_regs *regs)
> +{
> +     halt_current_cpu(regs);
> +}
> diff --git a/include/linux/kdb.h b/include/linux/kdb.h
> index e4340d3..1cf413e 100644
> --- a/include/linux/kdb.h
> +++ b/include/linux/kdb.h
> @@ -161,4 +161,11 @@ int kdb_process_cpu(const struct task_struct *p)
>  
>  extern const char kdb_serial_str[];
>  
> +#ifdef CONFIG_KEXEC
> +
> +void kdb_kexec_prepare(struct pt_regs *regs);
> +void kexec_from_kdb(struct pt_regs *regs, int kdump);
> +
> +#endif
> +
>  #endif       /* !_KDB_H */
> diff --git a/include/linux/kdbprivate.h b/include/linux/kdbprivate.h
> index 50dee9f..ca2c3db 100644
> --- a/include/linux/kdbprivate.h
> +++ b/include/linux/kdbprivate.h
> @@ -162,6 +162,7 @@ volatile extern int kdb_state[ /*NR_CPUS*/ ];
>  #define KDB_STATE_IP_ADJUSTED        0x00008000      /* 
> Restart IP has been adjusted */
>  #define KDB_STATE_GO1                0x00010000      /* go 
> only releases one cpu */
>  #define KDB_STATE_KEYBOARD   0x00020000      /* kdb entered 
> via keyboard on this cpu */
> +#define KDB_STATE_KEXEC      0x00040000      /* kexec issued */
>  #define KDB_STATE_ARCH               0xff000000      /* 
> Reserved for arch specific use */
>  
>  #define KDB_STATE_CPU(flag,cpu)              (kdb_state[cpu] 
> & KDB_STATE_##flag)
> diff --git a/include/linux/reboot.h b/include/linux/reboot.h
> index 1dd1c70..f4d682c 100644
> --- a/include/linux/reboot.h
> +++ b/include/linux/reboot.h
> @@ -53,7 +53,10 @@ extern void machine_power_off(void);
>  
>  extern void machine_shutdown(void);
>  struct pt_regs;
> -extern void machine_crash_shutdown(struct pt_regs *);
> +extern void machine_crash_shutdown(struct pt_regs *regs);
> +extern void machine_crash_shutdown_begin(void);
> +extern void machine_crash_shutdown_other_cpu(struct pt_regs *regs);
> +extern void machine_crash_shutdown_end(struct pt_regs *regs);
>  
>  /* 
>   * Architecture independent implemenations of sys_reboot commands.
> diff --git a/kdb/kdbmain.c b/kdb/kdbmain.c
> index 9dfa3b3..2ecacfc 100644
> --- a/kdb/kdbmain.c
> +++ b/kdb/kdbmain.c
> @@ -1124,6 +1124,116 @@ kdb_reboot(int argc, const char **argv)
>       return 0;
>  }
>  
> +#ifdef CONFIG_KEXEC
> +
> +int kdb_kexec_state = -1;
> +
> +static int kdb_cpu(int argc, const char **argv);
> +
> +void kdb_kexec_prepare(struct pt_regs *regs)
> +{
> +     int i;
> +     struct pt_regs r;
> +     if (regs == NULL)
> +             regs = &r;
> +
> +     machine_crash_shutdown_begin();
> +     
> +     for (i = 1; i < NR_CPUS; ++i) {
> +             if (!cpu_online(i))
> +                     continue;
> +
> +             KDB_STATE_SET_CPU(KEXEC, i);
> +     }
> +
> +     machine_crash_shutdown_end(regs);
> +}
> +
> +void kdb_kexec_check(struct pt_regs *regs)
> +{
> +     if (kdb_kexec_state != -1) {
> +             kexec_from_kdb(regs, kdb_kexec_state);
> +
> +             /* If the call above returned then something 
> +                didn't work */
> +             kdb_kexec_state = -1;
> +     }
> +}
> +
> +static int 
> +kdb_switch_cpu_for_kexec(int new_state)
> +{
> +     const char *cpu_argv[] = {NULL, "0", NULL};
> +     int ret;
> +
> +     kdb_kexec_state = new_state;
> +     ret = kdb_cpu(1, cpu_argv);
> +     if (ret != KDB_CMD_CPU) {
> +             kdb_kexec_state = -1;
> +     }
> +
> +     return ret;
> +}
> +
> +
> +/*
> + * kdb_kexec
> + *
> + *     This function implements the 'kexec' command.
> + *
> + * Inputs:
> + *     argc    argument count
> + *     argv    argument vector
> + *     envp    environment vector
> + *     regs    registers at time kdb was entered.
> + * Outputs:
> + *     None.
> + * Returns:
> + *     zero for success, a kdb diagnostic if error
> + * Locking:
> + *     none.
> + * Remarks:
> + *     Shouldn't return from this function.
> + */
> +
> +static int
> +kdb_kexec(int argc, const char **argv)
> +{
> +     return kdb_switch_cpu_for_kexec(0);
> +}
> +
> +/*
> + * kdb_kdump
> + *
> + *     This function implements the 'kdump' command.
> + *
> + * Inputs:
> + *     argc    argument count
> + *     argv    argument vector
> + *     envp    environment vector
> + *     regs    registers at time kdb was entered.
> + * Outputs:
> + *     None.
> + * Returns:
> + *     zero for success, a kdb diagnostic if error
> + * Locking:
> + *     none.
> + * Remarks:
> + *     Shouldn't return from this function.
> + */
> +
> +static int
> +kdb_kdump(int argc, const char **argv)
> +{
> +     return kdb_switch_cpu_for_kexec(1);
> +}
> +
> +#else
> +
> +static inline void kdb_kexec_check(struct pt_regs *regs) {};
> +
> +#endif
> +
>  static int
>  kdb_quiet(int reason)
>  {
> @@ -1166,6 +1276,8 @@ kdb_local(kdb_reason_t reason, int 
> error, struct pt_regs *regs, kdb_dbtrap_t db_
>       int diag;
>       struct task_struct *kdb_current = 
> kdb_curr_task(smp_processor_id());
>  
> +     kdb_kexec_check(regs);
> +
>       /* If kdb has been entered for an event which has been/will be
>        * recovered then silently return.  We have to get this 
> far into kdb in
>        * order to synchronize all the cpus, typically only 
> one cpu (monarch)
> @@ -1553,7 +1665,18 @@ kdb_main_loop(kdb_reason_t reason, 
> kdb_reason_t reason2, int error,
>                       if (!KDB_STATE(KDB)) {
>                               KDB_STATE_SET(KDB);
>                       }
> +
> +#ifdef CONFIG_KEXEC
> +                     if (KDB_STATE(KEXEC)) {
> +                             struct pt_regs r;
> +                             if (regs == NULL)
> +                                     regs = &r;
> +                             machine_crash_shutdown_other_cpu(regs);
> +                             return 0;
> +                     }
> +#endif
>               }
> +
>               KDB_STATE_CLEAR(SUPPRESS);
>               KDB_DEBUG_STATE("kdb_main_loop 2", reason);
>               if (KDB_STATE(LEAVING))
> @@ -3821,6 +3944,10 @@ kdb_inittab(void)
>       kdb_register_repeat("ps", kdb_ps, "",           
> "Display active task list", 0, KDB_REPEAT_NONE);
>       kdb_register_repeat("pid", kdb_pid, "<pidnum>", "Switch 
> to another task", 0, KDB_REPEAT_NONE);
>       kdb_register_repeat("reboot", kdb_reboot, "",  "Reboot 
> the machine immediately", 0, KDB_REPEAT_NONE);
> +#if defined(CONFIG_KEXEC)
> +     kdb_register_repeat("kexec", kdb_kexec, "",    "Calls 
> kexec in crash mode", 0, KDB_REPEAT_NONE);
> +     kdb_register_repeat("kdump", kdb_kdump, "",    "Calls 
> kdump mode", 0, KDB_REPEAT_NONE);
> +#endif
>  #if defined(CONFIG_MODULES)
>       kdb_register_repeat("lsmod", kdb_lsmod, "",     "List 
> loaded kernel modules", 0, KDB_REPEAT_NONE);
>  #endif
> diff --git a/kernel/kexec.c b/kernel/kexec.c
> index 2a59c8a..5858db1 100644
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -22,6 +22,8 @@
>  #include <linux/hardirq.h>
>  #include <linux/elf.h>
>  #include <linux/elfcore.h>
> +#include <linux/module.h>
> +#include <linux/device.h>
>  
>  #include <asm/page.h>
>  #include <asm/uaccess.h>
> @@ -29,6 +31,10 @@
>  #include <asm/system.h>
>  #include <asm/semaphore.h>
>  
> +#ifdef CONFIG_KDB
> +#include <linux/kdb.h>
> +#endif
> +
>  /* Per cpu memory for storing cpu states in case of system crash. */
>  note_buf_t* crash_notes;
>  
> @@ -1045,6 +1051,12 @@ asmlinkage long 
> compat_sys_kexec_load(unsigned long entry,
>  
>  void crash_kexec(struct pt_regs *regs)
>  {
> +#if !CONFIG_KDB
> +     /*
> +      * If we enabled KDB, we don't want to automatically 
> +      * perform a kdump since KDB will be responsible for 
> +      * executing kdb through a special 'kdump' command.
> +      */
>       int locked;
>  
>  
> @@ -1067,8 +1079,38 @@ void crash_kexec(struct pt_regs *regs)
>               locked = xchg(&kexec_lock, 0);
>               BUG_ON(!locked);
>       }
> +#endif
>  }
>  
> +#ifdef CONFIG_KDB
> +
> +void kexec_from_kdb(struct pt_regs *regs, int kdump)
> +{
> +     struct kimage *image;
> +     int locked;
> +
> +     locked = xchg(&kexec_lock, 1);
> +     if (!locked) {
> +             if (kdump) 
> +                     image = kexec_crash_image;
> +             else 
> +                     image = kexec_image;
> +
> +             if (image) {
> +                     struct pt_regs fixed_regs;
> +
> +                     crash_setup_regs(&fixed_regs, regs);
> +                     kdb_kexec_prepare(&fixed_regs);
> +                     machine_kexec(image);
> +             }
> +
> +             locked = xchg(&kexec_lock, 0);
> +             BUG_ON(!locked);
> +     }
> +}
> +
> +#endif
> +
>  static u32 *append_elf_note(u32 *buf, char *name, unsigned 
> type, void *data,
>                           size_t data_len)
>  {
> 
> 
> -- 
> Dan Aloni
> XIV LTD, http://www.xivstorage.com
> da-x (at) monatomic.org, dan (at) xiv.co.il
> 
> --------------040402050608090401060307--
> 

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Kgdb-bugreport mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport

Reply via email to