Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / linux-2.6.10-fc3-lkcd.patch
1 Index: linux-2.6.10-base/drivers/dump/dump_ia64.c
2 ===================================================================
3 --- linux-2.6.10-base.orig/drivers/dump/dump_ia64.c     2003-09-02 06:26:13.000000000 +0800
4 +++ linux-2.6.10-base/drivers/dump/dump_ia64.c  2005-05-17 18:52:39.928056424 +0800
5 @@ -0,0 +1,458 @@
6 +/*
7 + * Architecture specific (ia64) functions for Linux crash dumps.
8 + *
9 + * Created by: Matt Robinson (yakker@sgi.com)
10 + * Contributions from SGI, IBM, and others.
11 + *
12 + * 2.4  kernel modifications by:  Matt D. Robinson (yakker@alacritech.com)
13 + * ia64 kernel modifications by: Piet Delaney (piet@www.piet.net)
14 + *
15 + * Copyright (C) 2001 - 2002 Matt D. Robinson (yakker@alacritech.com)
16 + * Copyright (C) 2002 Silicon Graphics, Inc. All rights reserved.
17 + * Copyright (C) 2002 Free Software Foundation, Inc. All rights reserved.
18 + *
19 + * This code is released under version 2 of the GNU GPL.
20 + */
21 +
22 +/*
23 + * The hooks for dumping the kernel virtual memory to disk are in this
24 + * file.  Any time a modification is made to the virtual memory mechanism,
25 + * these routines must be changed to use the new mechanisms.
26 + */
27 +#include <linux/init.h>
28 +#include <linux/types.h>
29 +#include <linux/kernel.h>
30 +#include <linux/smp.h>
31 +#include <linux/fs.h>
32 +#include <linux/vmalloc.h>
33 +#include <linux/dump.h>
34 +#include "dump_methods.h"
35 +#include <linux/mm.h>
36 +#include <asm/processor.h>
37 +#include <asm-ia64/dump.h>
38 +#include <asm/hardirq.h>
39 +#include <linux/irq.h>
40 +#include <linux/delay.h>
41 +
42 +static __s32         saved_irq_count;   /* saved preempt_count() flags */
43 +
44 +
45 +static int alloc_dha_stack(void)
46 +{
47 +       int i;
48 +       void *ptr;
49 +       
50 +       if (dump_header_asm.dha_stack[0])
51 +       {
52 +               return 0;
53 +       }
54 +               ptr = vmalloc(THREAD_SIZE * num_online_cpus());
55 +               if (!ptr) {
56 +               printk("vmalloc for dha_stacks failed\n");
57 +               return -ENOMEM;
58 +       }
59 +       bzero(ptr,THREAD_SIZE );
60 +
61 +       for (i = 0; i < num_online_cpus(); i++) {
62 +               dump_header_asm.dha_stack[i] = (uint64_t)((unsigned long)ptr + (i * THREAD_SIZE));
63 +       }
64 +       return 0;
65 +}
66 +
67 +static int free_dha_stack(void) 
68 +{
69 +       if (dump_header_asm.dha_stack[0])
70 +       {
71 +               vfree((void*)dump_header_asm.dha_stack[0]);
72 +               dump_header_asm.dha_stack[0] = 0;
73 +       }
74 +       return 0;
75 +}
76 +
77 +/* a structure to get arguments into the following callback routine */
78 +struct unw_args {
79 +       int cpu;
80 +       struct task_struct *tsk;
81 +};
82 +
83 +static void
84 +do_save_sw(struct unw_frame_info *info, void *arg)
85 +{
86 +       struct unw_args *uwargs = (struct unw_args *)arg;
87 +       int cpu = uwargs->cpu;
88 +       struct task_struct *tsk = uwargs->tsk;
89 +
90 +       dump_header_asm.dha_stack_ptr[cpu] = (uint64_t)info->sw;
91 +
92 +       if (tsk && dump_header_asm.dha_stack[cpu]) {
93 +               memcpy((void *)dump_header_asm.dha_stack[cpu],
94 +                               STACK_START_POSITION(tsk),
95 +                               THREAD_SIZE);
96 +       }
97 +}
98 +
99 +void
100 +__dump_save_context(int cpu, const struct pt_regs *regs, 
101 +       struct task_struct *tsk)
102 +{
103 +       struct unw_args uwargs;
104 +
105 +       dump_header_asm.dha_smp_current_task[cpu] = (unsigned long)tsk;
106 +
107 +       if (regs) {
108 +               dump_header_asm.dha_smp_regs[cpu] = *regs;
109 +       }
110 +
111 +       /* save a snapshot of the stack in a nice state for unwinding */
112 +       uwargs.cpu = cpu;
113 +       uwargs.tsk = tsk;
114 +
115 +       unw_init_running(do_save_sw, (void *)&uwargs);
116 +}
117 +
118 +#ifdef CONFIG_SMP
119 +
120 +extern cpumask_t irq_affinity[];
121 +#define irq_desc _irq_desc
122 +extern irq_desc_t irq_desc[];
123 +extern void dump_send_ipi(void);
124 +static cpumask_t saved_affinity[NR_IRQS];
125 +
126 +/*
127 + * Routine to save the old irq affinities and change affinities of all irqs to
128 + * the dumping cpu.
129 + */
130 +static void
131 +set_irq_affinity(void)
132 +{
133 +        int i;
134 +       cpumask_t cpu = CPU_MASK_NONE;
135 +
136 +       cpu_set(smp_processor_id(), cpu);
137 +        memcpy(saved_affinity, irq_affinity, NR_IRQS * sizeof(unsigned long));
138 +        for (i = 0; i < NR_IRQS; i++) {
139 +                if (irq_desc[i].handler == NULL)
140 +                        continue;
141 +               irq_affinity[i] = cpu;
142 +                if (irq_desc[i].handler->set_affinity != NULL)
143 +                        irq_desc[i].handler->set_affinity(i, irq_affinity[i]);
144 +        }
145 +}
146 +
147 +/*
148 + * Restore old irq affinities.
149 + */
150 +static void
151 +reset_irq_affinity(void)
152 +{
153 +        int i;
154 +
155 +        memcpy(irq_affinity, saved_affinity, NR_IRQS * sizeof(unsigned long));
156 +        for (i = 0; i < NR_IRQS; i++) {
157 +                if (irq_desc[i].handler == NULL)
158 +                        continue;
159 +                if (irq_desc[i].handler->set_affinity != NULL)
160 +                        irq_desc[i].handler->set_affinity(i, saved_affinity[i]);
161 +        }
162 +}
163 +
164 +#else /* !CONFIG_SMP */
165 +#define set_irq_affinity()      do { } while (0)
166 +#define reset_irq_affinity()    do { } while (0)
167 +#define save_other_cpu_states() do { } while (0)
168 +#endif /* !CONFIG_SMP */
169 +
170 +#ifdef CONFIG_SMP
171 +static int dump_expect_ipi[NR_CPUS];
172 +static atomic_t waiting_for_dump_ipi;
173 +static int wait_for_dump_ipi = 2000; /* wait 2000 ms for ipi to be handled */
174 +extern void (*dump_trace_ptr)(struct pt_regs *);
175 +
176 +
177 +extern void stop_this_cpu(void);
178 +
179 +static int
180 +dump_nmi_callback(struct pt_regs *regs, int cpu)
181 +{
182 +        if (!dump_expect_ipi[cpu])
183 +                return 0;
184 +
185 +        dump_expect_ipi[cpu] = 0;
186 +
187 +        dump_save_this_cpu(regs);
188 +        atomic_dec(&waiting_for_dump_ipi);
189 +
190 + level_changed:
191 +        switch (dump_silence_level) {
192 +        case DUMP_HARD_SPIN_CPUS:       /* Spin until dump is complete */
193 +                while (dump_oncpu) {
194 +                        barrier();      /* paranoia */
195 +                        if (dump_silence_level != DUMP_HARD_SPIN_CPUS)
196 +                                goto level_changed;
197 +
198 +                        cpu_relax();    /* kill time nicely */
199 +                }
200 +                break;
201 +
202 +        case DUMP_HALT_CPUS:            /* Execute halt */
203 +                stop_this_cpu();
204 +                break;
205 +
206 +        case DUMP_SOFT_SPIN_CPUS:
207 +                /* Mark the task so it spins in schedule */
208 +                set_tsk_thread_flag(current, TIF_NEED_RESCHED);
209 +                break;
210 +        }
211 +
212 +        return 1;
213 +}
214 +
215 +int IPI_handler(struct pt_regs *regs)
216 +{
217 +       int cpu;
218 +       cpu = task_cpu(current);
219 +       return(dump_nmi_callback(regs, cpu));
220 +}
221 +
222 +/* save registers on other processors */
223 +void
224 +__dump_save_other_cpus(void)
225 +{
226 +        int i, cpu = smp_processor_id();
227 +        int other_cpus = num_online_cpus()-1;
228 +       int wait_time = wait_for_dump_ipi;
229 +
230 +        if (other_cpus > 0) {
231 +                atomic_set(&waiting_for_dump_ipi, other_cpus);
232 +
233 +                for (i = 0; i < NR_CPUS; i++) {
234 +                        dump_expect_ipi[i] = (i != cpu && cpu_online(i));
235 +                }
236 +
237 +               dump_ipi_function_ptr = IPI_handler;
238 +               
239 +                wmb();
240 +
241 +                dump_send_ipi();
242 +                /* may be we dont need to wait for IPI to be processed.
243 +                 * just write out the header at the end of dumping, if
244 +                 * this IPI is not processed until then, there probably
245 +                 * is a problem and we just fail to capture state of
246 +                 * other cpus. */
247 +                while(wait_time-- && (atomic_read(&waiting_for_dump_ipi) > 0)) {
248 +                       barrier();
249 +                       mdelay(1);
250 +                }
251 +               if (wait_time <= 0) {
252 +                       printk("dump ipi timeout, proceeding...\n");
253 +               }
254 +        }
255 +}
256 +#endif
257 +/*
258 + * Kludge - dump from interrupt context is unreliable (Fixme)
259 + *
260 + * We do this so that softirqs initiated for dump i/o
261 + * get processed and we don't hang while waiting for i/o
262 + * to complete or in any irq synchronization attempt.
263 + *
264 + * This is not quite legal of course, as it has the side
265 + * effect of making all interrupts & softirqs triggered
266 + * while dump is in progress complete before currently
267 + * pending softirqs and the currently executing interrupt
268 + * code.
269 + */
270 +static inline void
271 +irq_bh_save(void)
272 +{
273 +        saved_irq_count = irq_count();
274 +        preempt_count() &= ~(HARDIRQ_MASK|SOFTIRQ_MASK);
275 +}
276 +
277 +static inline void
278 +irq_bh_restore(void)
279 +{
280 +        preempt_count() |= saved_irq_count;
281 +}
282 +
283 +/*
284 + * Name: __dump_configure_header()
285 + * Func: Configure the dump header with all proper values.
286 + */
287 +int
288 +__dump_configure_header(const struct pt_regs *regs)
289 +{
290 +       return (0);
291 +}
292 +
293 +
294 +#define dim(x) (sizeof(x)/sizeof(*(x)))
295 +
296 +/*
297 + * Name: __dump_irq_enable
298 + * Func: Reset system so interrupts are enabled.
299 + *       This is used for dump methods that require interrupts
300 + *       Eventually, all methods will have interrupts disabled
301 + *       and this code can be removed.
302 + *
303 + *     Change irq affinities
304 + *     Re-enable interrupts
305 + */
306 +int
307 +__dump_irq_enable(void)
308 +{
309 +        set_irq_affinity();
310 +        irq_bh_save();
311 +       ia64_srlz_d();
312 +       /* 
313 +        * reduce the task priority level
314 +        * to get disk interrupts
315 +        */
316 +       ia64_setreg(_IA64_REG_CR_TPR, 0);
317 +       ia64_srlz_d();
318 +        local_irq_enable();
319 +       return 0;
320 +}
321 +
322 +/*
323 + * Name: __dump_irq_restore
324 + * Func: Resume the system state in an architecture-specific way.
325 +
326 + */
327 +void
328 +__dump_irq_restore(void)
329 +{
330 +        local_irq_disable();
331 +        reset_irq_affinity();
332 +        irq_bh_restore();
333 +}
334 +
335 +/*
336 + * Name: __dump_page_valid()
337 + * Func: Check if page is valid to dump.
338 + */
339 +int
340 +__dump_page_valid(unsigned long index)
341 +{
342 +        if (!pfn_valid(index))
343 +       {
344 +                return 0;
345 +       }
346 +        return 1;
347 +}
348 +
349 +/*
350 + * Name: __dump_init()
351 + * Func: Initialize the dumping routine process.  This is in case
352 + *       it's necessary in the future.
353 + */
354 +void
355 +__dump_init(uint64_t local_memory_start)
356 +{
357 +       return;
358 +}
359 +
360 +/*
361 + * Name: __dump_open()
362 + * Func: Open the dump device (architecture specific).  This is in
363 + *       case it's necessary in the future.
364 + */
365 +void
366 +__dump_open(void)
367 +{
368 +       alloc_dha_stack();
369 +       return;
370 +}
371 +
372 +
373 +/*
374 + * Name: __dump_cleanup()
375 + * Func: Free any architecture specific data structures. This is called
376 + *       when the dump module is being removed.
377 + */
378 +void
379 +__dump_cleanup(void)
380 +{
381 +       free_dha_stack();
382 +
383 +       return;
384 +}
385 +
386 +
387 +
388 +int __dump_memcpy_mc_expected = 0;             /* Doesn't help yet */
389 +
390 +/*
391 + * An ia64 version of memcpy() that trys to avoid machine checks.
392 + *
393 + * NB: 
394 + *     By itself __dump_memcpy_mc_expected() ins't providing any
395 + *     protection against Machine Checks. We are looking into the
396 + *     possability of adding code to the arch/ia64/kernel/mca.c fuction
397 + *     ia64_mca_ucmc_handler() to restore state so that a IA64_MCA_CORRECTED
398 + *     can be returned to the firmware. Curently it always returns 
399 + *     IA64_MCA_COLD_BOOT and reboots the machine.
400 + */
401 +/*
402 +void * __dump_memcpy(void * dest, const void *src, size_t count)
403 +{
404 +       void *vp;
405 +
406 +       if (__dump_memcpy_mc_expected) {
407 +               ia64_pal_mc_expected((u64) 1, 0);
408 +       }
409 +
410 +       vp = memcpy(dest, src, count);
411 +
412 +       if (__dump_memcpy_mc_expected) {
413 +               ia64_pal_mc_expected((u64) 0, 0);
414 +       }
415 +       return(vp);
416 +}
417 +*/
418 +/*
419 + * Name: manual_handle_crashdump()
420 + * Func: Interface for the lkcd dump command. Calls dump_execute()
421 + */
422 +int
423 +manual_handle_crashdump(void) {
424 +
425 +        struct pt_regs regs;
426 +
427 +        get_current_regs(&regs);
428 +        dump_execute("manual", &regs);
429 +        return 0;
430 +}
431 +
432 +/*
433 + * Name: __dump_clean_irq_state()
434 + * Func: Clean up from the previous IRQ handling state. Such as oops from 
435 + *       interrupt handler or bottom half.
436 + */
437 +void
438 +__dump_clean_irq_state(void)
439 +{
440 +       unsigned long saved_tpr;
441 +       unsigned long TPR_MASK = 0xFFFFFFFFFFFEFF0F;
442 +       
443 +       
444 +       /* Get the processors task priority register */
445 +       saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
446 +       /* clear the mmi and mic bit's of the TPR to unmask interrupts */
447 +       saved_tpr = saved_tpr & TPR_MASK; 
448 +       ia64_setreg(_IA64_REG_CR_TPR, saved_tpr);
449 +       ia64_srlz_d();
450 +
451 +       /* Tell the processor we're done with the interrupt
452 +        * that got us here.
453 +        */
454 +       
455 +       ia64_eoi();
456 +
457 +       /* local implementation of irq_exit(); */
458 +       preempt_count() -= IRQ_EXIT_OFFSET;
459 +       preempt_enable_no_resched();
460 +
461 +       return;
462 +}
463 +
464 Index: linux-2.6.10-base/drivers/dump/dump_setup.c
465 ===================================================================
466 --- linux-2.6.10-base.orig/drivers/dump/dump_setup.c    2003-09-02 06:26:13.000000000 +0800
467 +++ linux-2.6.10-base/drivers/dump/dump_setup.c 2005-05-17 18:52:39.930056120 +0800
468 @@ -0,0 +1,923 @@
469 +/*
470 + * Standard kernel function entry points for Linux crash dumps.
471 + *
472 + * Created by: Matt Robinson (yakker@sourceforge.net)
473 + * Contributions from SGI, IBM, HP, MCL, and others.
474 + *
475 + * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
476 + * Copyright (C) 2000 - 2002 TurboLinux, Inc.  All rights reserved.
477 + * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
478 + * Copyright (C) 2002 Free Software Foundation, Inc. All rights reserved.
479 + *
480 + * This code is released under version 2 of the GNU GPL.
481 + */
482 +
483 +/*
484 + * -----------------------------------------------------------------------
485 + *
486 + * DUMP HISTORY
487 + *
488 + * This dump code goes back to SGI's first attempts at dumping system
489 + * memory on SGI systems running IRIX.  A few developers at SGI needed
490 + * a way to take this system dump and analyze it, and created 'icrash',
491 + * or IRIX Crash.  The mechanism (the dumps and 'icrash') were used
492 + * by support people to generate crash reports when a system failure
493 + * occurred.  This was vital for large system configurations that
494 + * couldn't apply patch after patch after fix just to hope that the
495 + * problems would go away.  So the system memory, along with the crash
496 + * dump analyzer, allowed support people to quickly figure out what the
497 + * problem was on the system with the crash dump.
498 + *
499 + * In comes Linux.  SGI started moving towards the open source community,
500 + * and upon doing so, SGI wanted to take its support utilities into Linux
501 + * with the hopes that they would end up the in kernel and user space to
502 + * be used by SGI's customers buying SGI Linux systems.  One of the first
503 + * few products to be open sourced by SGI was LKCD, or Linux Kernel Crash
504 + * Dumps.  LKCD comprises of a patch to the kernel to enable system
505 + * dumping, along with 'lcrash', or Linux Crash, to analyze the system
506 + * memory dump.  A few additional system scripts and kernel modifications
507 + * are also included to make the dump mechanism and dump data easier to
508 + * process and use.
509 + *
510 + * As soon as LKCD was released into the open source community, a number
511 + * of larger companies started to take advantage of it.  Today, there are
512 + * many community members that contribute to LKCD, and it continues to
513 + * flourish and grow as an open source project.
514 + */
515 +
516 +/*
517 + * DUMP TUNABLES (read/write with ioctl, readonly with /proc)
518 + *
519 + * This is the list of system tunables (via /proc) that are available
520 + * for Linux systems.  All the read, write, etc., functions are listed
521 + * here.  Currently, there are a few different tunables for dumps:
522 + *
523 + * dump_device (used to be dumpdev):
524 + *     The device for dumping the memory pages out to.  This 
525 + *     may be set to the primary swap partition for disruptive dumps,
526 + *     and must be an unused partition for non-disruptive dumps.
527 + *     Todo: In the case of network dumps, this may be interpreted 
528 + *     as the IP address of the netdump server to connect to.
529 + *
530 + * dump_compress (used to be dump_compress_pages):
531 + *     This is the flag which indicates which compression mechanism
532 + *     to use.  This is a BITMASK, not an index (0,1,2,4,8,16,etc.).
533 + *     This is the current set of values:
534 + *
535 + *     0: DUMP_COMPRESS_NONE -- Don't compress any pages.
536 + *     1: DUMP_COMPRESS_RLE  -- This uses RLE compression.
537 + *     2: DUMP_COMPRESS_GZIP -- This uses GZIP compression.
538 + *
539 + * dump_level:
540 + *     The amount of effort the dump module should make to save
541 + *     information for post crash analysis.  This value is now
542 + *     a BITMASK value, not an index:
543 + *
544 + *     0:   Do nothing, no dumping. (DUMP_LEVEL_NONE)
545 + *
546 + *     1:   Print out the dump information to the dump header, and
547 + *          write it out to the dump_device. (DUMP_LEVEL_HEADER)
548 + *
549 + *     2:   Write out the dump header and all kernel memory pages.
550 + *          (DUMP_LEVEL_KERN)
551 + *
552 + *     4:   Write out the dump header and all kernel and user
553 + *          memory pages.  (DUMP_LEVEL_USED)
554 + *
555 + *     8:   Write out the dump header and all conventional/cached 
556 + *         memory (RAM) pages in the system (kernel, user, free).  
557 + *         (DUMP_LEVEL_ALL_RAM)
558 + *
559 + *    16:   Write out everything, including non-conventional memory
560 + *         like firmware, proms, I/O registers, uncached memory.
561 + *         (DUMP_LEVEL_ALL)
562 + *
563 + *     The dump_level will default to 1.
564 + *
565 + * dump_flags:
566 + *     These are the flags to use when talking about dumps.  There
567 + *     are lots of possibilities.  This is a BITMASK value, not an index.
568 + * 
569 + * -----------------------------------------------------------------------
570 + */
571 +
572 +#include <linux/kernel.h>
573 +#include <linux/delay.h>
574 +#include <linux/reboot.h>
575 +#include <linux/fs.h>
576 +#include <linux/dump.h>
577 +#include <linux/ioctl32.h>
578 +#include <linux/syscalls.h>
579 +#include "dump_methods.h"
580 +#include <linux/proc_fs.h>
581 +#include <linux/module.h>
582 +#include <linux/utsname.h>
583 +#include <linux/highmem.h>
584 +#include <linux/miscdevice.h>
585 +#include <linux/sysrq.h>
586 +#include <linux/sysctl.h>
587 +#include <linux/nmi.h>
588 +#include <linux/init.h>
589 +#include <asm/hardirq.h>
590 +#include <asm/uaccess.h>
591 +
592 +
593 +/*
594 + * -----------------------------------------------------------------------
595 + *                         V A R I A B L E S
596 + * -----------------------------------------------------------------------
597 + */
598 +
599 +/* Dump tunables */
600 +struct dump_config dump_config = {
601 +       .level          = 0,
602 +       .flags          = 0,
603 +       .dump_device    = 0,
604 +       .dump_addr      = 0,
605 +       .dumper         = NULL
606 +};
607 +#ifdef CONFIG_ARM 
608 +static _dump_regs_t all_regs;
609 +#endif
610 +
611 +/* Global variables used in dump.h */
612 +/* degree of system freeze when dumping */
613 +enum dump_silence_levels dump_silence_level = DUMP_HARD_SPIN_CPUS;      
614 +
615 +/* Other global fields */
616 +extern struct __dump_header dump_header; 
617 +struct dump_dev *dump_dev = NULL;  /* Active dump device                   */
618 +static int dump_compress = 0;
619 +
620 +static u32 dump_compress_none(const u8 *old, u32 oldsize, u8 *new, u32 newsize,
621 +                               unsigned long loc);
622 +struct __dump_compress dump_none_compression = {
623 +       .compress_type  = DUMP_COMPRESS_NONE,
624 +       .compress_func  = dump_compress_none,
625 +       .compress_name  = "none",
626 +};
627 +
628 +/* our device operations and functions */
629 +static int dump_ioctl(struct inode *i, struct file *f,
630 +       unsigned int cmd, unsigned long arg);
631 +
632 +#ifdef CONFIG_COMPAT
633 +static int dw_long(unsigned int, unsigned int, unsigned long, struct file*);
634 +#endif
635 +
636 +static struct file_operations dump_fops = {
637 +       .owner  = THIS_MODULE,
638 +       .ioctl  = dump_ioctl,
639 +};
640 +
641 +static struct miscdevice dump_miscdev = {
642 +       .minor  = CRASH_DUMP_MINOR,
643 +       .name   = "dump",
644 +       .fops   = &dump_fops,
645 +};
646 +MODULE_ALIAS_MISCDEV(CRASH_DUMP_MINOR);
647 +
648 +/* static variables                                                    */
649 +static int dump_okay = 0;              /* can we dump out to disk?     */
650 +static spinlock_t dump_lock = SPIN_LOCK_UNLOCKED;
651 +
652 +/* used for dump compressors */
653 +static struct list_head dump_compress_list = LIST_HEAD_INIT(dump_compress_list);
654 +
655 +/* list of registered dump targets */
656 +static struct list_head dump_target_list = LIST_HEAD_INIT(dump_target_list);
657 +
658 +/* lkcd info structure -- this is used by lcrash for basic system data     */
659 +struct __lkcdinfo lkcdinfo = {
660 +       .ptrsz          = (sizeof(void *) * 8),
661 +#if defined(__LITTLE_ENDIAN) 
662 +       .byte_order     = __LITTLE_ENDIAN,
663 +#else
664 +       .byte_order     = __BIG_ENDIAN,
665 +#endif
666 +       .page_shift     = PAGE_SHIFT,
667 +       .page_size      = PAGE_SIZE,
668 +       .page_mask      = PAGE_MASK,
669 +       .page_offset    = PAGE_OFFSET,
670 +};
671 +
672 +/*
673 + * -----------------------------------------------------------------------
674 + *            / P R O C   T U N A B L E   F U N C T I O N S
675 + * -----------------------------------------------------------------------
676 + */
677 +
678 +static int proc_dump_device(ctl_table *ctl, int write, struct file *f,
679 +                           void __user *buffer, size_t *lenp, loff_t *ppos);
680 +
681 +static int proc_doulonghex(ctl_table *ctl, int write, struct file *f,
682 +                           void __user *buffer, size_t *lenp, loff_t *ppos);
683 +/*
684 + * sysctl-tuning infrastructure.
685 + */
686 +static ctl_table dump_table[] = {
687 +       { .ctl_name = CTL_DUMP_LEVEL,
688 +         .procname = DUMP_LEVEL_NAME, 
689 +         .data = &dump_config.level,    
690 +         .maxlen = sizeof(int),
691 +         .mode = 0444,
692 +         .proc_handler = proc_doulonghex, },
693 +
694 +       { .ctl_name = CTL_DUMP_FLAGS,
695 +         .procname = DUMP_FLAGS_NAME,
696 +         .data = &dump_config.flags,   
697 +         .maxlen = sizeof(int),
698 +         .mode = 0444,
699 +         .proc_handler = proc_doulonghex, },
700 +
701 +       { .ctl_name = CTL_DUMP_COMPRESS,
702 +         .procname = DUMP_COMPRESS_NAME,
703 +         .data = &dump_compress, /* FIXME */
704 +         .maxlen = sizeof(int),
705 +         .mode = 0444,
706 +         .proc_handler = proc_dointvec, },
707 +         
708 +       { .ctl_name = CTL_DUMP_DEVICE,
709 +         .procname = DUMP_DEVICE_NAME,
710 +         .mode = 0444,
711 +         .data = &dump_config.dump_device, /* FIXME */
712 +         .maxlen = sizeof(int),
713 +         .proc_handler = proc_dump_device },
714 +
715 +#ifdef CONFIG_CRASH_DUMP_MEMDEV
716 +       { .ctl_name = CTL_DUMP_ADDR,
717 +         .procname = DUMP_ADDR_NAME,
718 +         .mode = 0444,
719 +         .data = &dump_config.dump_addr,
720 +         .maxlen = sizeof(unsigned long),
721 +         .proc_handler = proc_doulonghex },
722 +#endif
723 +
724 +       { 0, }
725 +};
726 +
727 +static ctl_table dump_root[] = {
728 +       { .ctl_name = KERN_DUMP,
729 +         .procname = "dump",
730 +         .mode = 0555, 
731 +         .child = dump_table },
732 +       { 0, }
733 +};
734 +
735 +static ctl_table kernel_root[] = {
736 +       { .ctl_name = CTL_KERN,
737 +         .procname = "kernel",
738 +         .mode = 0555,
739 +         .child = dump_root, },
740 +       { 0, }
741 +};
742 +
743 +static struct ctl_table_header *sysctl_header;
744 +
745 +/*
746 + * -----------------------------------------------------------------------
747 + *              C O M P R E S S I O N   F U N C T I O N S
748 + * -----------------------------------------------------------------------
749 + */
750 +
751 +/*
752 + * Name: dump_compress_none()
753 + * Func: Don't do any compression, period.
754 + */
755 +static u32
756 +dump_compress_none(const u8 *old, u32 oldsize, u8 *new, u32 newsize,
757 +               unsigned long loc)
758 +{
759 +       /* just return the old size */
760 +       return oldsize;
761 +}
762 +
763 +
764 +/*
765 + * Name: dump_execute()
766 + * Func: Execute the dumping process.  This makes sure all the appropriate
767 + *       fields are updated correctly, and calls dump_execute_memdump(),
768 + *       which does the real work.
769 + */
770 +void
771 +dump_execute(const char *panic_str, const struct pt_regs *regs)
772 +{
773 +       int state = -1;
774 +       unsigned long flags;
775 +
776 +       /* make sure we can dump */
777 +       if (!dump_okay) {
778 +               pr_info("LKCD not yet configured, can't take dump now\n");
779 +               return;
780 +       }
781 +
782 +       /* Exclude multiple dumps at the same time,
783 +        * and disable interrupts,  some drivers may re-enable
784 +        * interrupts in with silence()
785 +        *
786 +        * Try and acquire spin lock. If successful, leave preempt
787 +        * and interrupts disabled.  See spin_lock_irqsave in spinlock.h
788 +        */
789 +       local_irq_save(flags);
790 +       if (!spin_trylock(&dump_lock)) {
791 +               local_irq_restore(flags);
792 +               pr_info("LKCD dump already in progress\n");
793 +               return;
794 +       }
795 +
796 +       /* What state are interrupts really in? */
797 +       if (in_interrupt()){ 
798 +               if(in_irq())
799 +                   printk(KERN_ALERT "Dumping from interrupt handler!\n");
800 +               else 
801 +                   printk(KERN_ALERT "Dumping from bottom half!\n");
802 +
803 +               __dump_clean_irq_state();
804 +       }
805 +
806 +
807 +       /* Bring system into the strictest level of quiescing for min drift 
808 +        * dump drivers can soften this as required in dev->ops->silence() 
809 +        */
810 +       dump_oncpu = smp_processor_id() + 1;
811 +       dump_silence_level = DUMP_HARD_SPIN_CPUS; 
812 +
813 +       state = dump_generic_execute(panic_str, regs);
814 +       
815 +       dump_oncpu = 0;
816 +       spin_unlock_irqrestore(&dump_lock, flags);
817 +
818 +       if (state < 0) {
819 +               printk("Dump Incomplete or failed!\n");
820 +       } else {
821 +               printk("Dump Complete; %d dump pages saved.\n", 
822 +                      dump_header.dh_num_dump_pages);
823 +       }
824 +}
825 +
826 +/*
827 + * Name: dump_register_compression()
828 + * Func: Register a dump compression mechanism.
829 + */
830 +void
831 +dump_register_compression(struct __dump_compress *item)
832 +{
833 +       if (item)
834 +               list_add(&(item->list), &dump_compress_list);
835 +}
836 +
837 +/*
838 + * Name: dump_unregister_compression()
839 + * Func: Remove a dump compression mechanism, and re-assign the dump
840 + *       compression pointer if necessary.
841 + */
842 +void
843 +dump_unregister_compression(int compression_type)
844 +{
845 +       struct list_head *tmp;
846 +       struct __dump_compress *dc;
847 +
848 +       /* let's make sure our list is valid */
849 +       if (compression_type != DUMP_COMPRESS_NONE) {
850 +               list_for_each(tmp, &dump_compress_list) {
851 +                       dc = list_entry(tmp, struct __dump_compress, list);
852 +                       if (dc->compress_type == compression_type) {
853 +                               list_del(&(dc->list));
854 +                               break;
855 +                       }
856 +               }
857 +       }
858 +}
859 +
860 +/*
861 + * Name: dump_compress_init()
862 + * Func: Initialize (or re-initialize) compression scheme.
863 + */
864 +static int
865 +dump_compress_init(int compression_type)
866 +{
867 +       struct list_head *tmp;
868 +       struct __dump_compress *dc;
869 +
870 +       /* try to remove the compression item */
871 +       list_for_each(tmp, &dump_compress_list) {
872 +               dc = list_entry(tmp, struct __dump_compress, list);
873 +               if (dc->compress_type == compression_type) {
874 +                       dump_config.dumper->compress = dc;
875 +                       dump_compress = compression_type;
876 +                       pr_debug("Dump Compress %s\n", dc->compress_name);
877 +                       return 0;
878 +               }
879 +       }
880 +
881 +       /* 
882 +        * nothing on the list -- return ENODATA to indicate an error 
883 +        *
884 +        * NB: 
885 +        *      EAGAIN: reports "Resource temporarily unavailable" which
886 +        *              isn't very enlightening.
887 +        */
888 +       printk("compression_type:%d not found\n", compression_type);
889 +
890 +       return -ENODATA;
891 +}
892 +
893 +static int
894 +dumper_setup(unsigned long flags, unsigned long devid)
895 +{
896 +       int ret = 0;
897 +
898 +       /* unconfigure old dumper if it exists */
899 +       dump_okay = 0;
900 +       if (dump_config.dumper) {
901 +               pr_debug("Unconfiguring current dumper\n");
902 +               dump_unconfigure();
903 +       }
904 +       /* set up new dumper */
905 +       if (dump_config.flags & DUMP_FLAGS_SOFTBOOT) {
906 +               printk("Configuring softboot based dump \n");
907 +#ifdef CONFIG_CRASH_DUMP_MEMDEV
908 +               dump_config.dumper = &dumper_stage1; 
909 +#else
910 +               printk("Requires CONFIG_CRASHDUMP_MEMDEV. Can't proceed.\n");
911 +               return -1;
912 +#endif
913 +       } else {
914 +               dump_config.dumper = &dumper_singlestage;
915 +       }       
916 +       dump_config.dumper->dev = dump_dev;
917 +
918 +       ret = dump_configure(devid);
919 +       if (!ret) {
920 +               dump_okay = 1;
921 +               pr_debug("%s dumper set up for dev 0x%lx\n", 
922 +                       dump_config.dumper->name, devid);
923 +               dump_config.dump_device = devid;
924 +       } else {
925 +               printk("%s dumper set up failed for dev 0x%lx\n", 
926 +                      dump_config.dumper->name, devid);
927 +               dump_config.dumper = NULL;
928 +       }
929 +       return ret;
930 +}
931 +
932 +static int
933 +dump_target_init(int target)
934 +{
935 +       char type[20];
936 +       struct list_head *tmp;
937 +       struct dump_dev *dev;
938 +       
939 +       switch (target) {
940 +               case DUMP_FLAGS_DISKDUMP:
941 +                       strcpy(type, "blockdev"); break;
942 +               case DUMP_FLAGS_NETDUMP:
943 +                       strcpy(type, "networkdev"); break;
944 +               default:
945 +                       return -1;
946 +       }
947 +
948 +       /*
949 +        * This is a bit stupid, generating strings from flag
950 +        * and doing strcmp. This is done because 'struct dump_dev'
951 +        * has string 'type_name' and not interger 'type'.
952 +        */
953 +       list_for_each(tmp, &dump_target_list) {
954 +               dev = list_entry(tmp, struct dump_dev, list);
955 +               if (strcmp(type, dev->type_name) == 0) {
956 +                       dump_dev = dev;
957 +                       return 0;
958 +               }
959 +       }
960 +       return -1;
961 +}
962 +
963 +/*
964 + * Name: dump_ioctl()
965 + * Func: Allow all dump tunables through a standard ioctl() mechanism.
966 + *       This is far better than before, where we'd go through /proc,
967 + *       because now this will work for multiple OS and architectures.
968 + */
969 +static int
970 +dump_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
971 +{
972 +       /* check capabilities */
973 +       if (!capable(CAP_SYS_ADMIN))
974 +               return -EPERM;
975 +
976 +       if (!dump_config.dumper && cmd == DIOSDUMPCOMPRESS)
977 +               /* dump device must be configured first */
978 +               return -ENODEV;
979 +
980 +       /*
981 +        * This is the main mechanism for controlling get/set data
982 +        * for various dump device parameters.  The real trick here
983 +        * is setting the dump device (DIOSDUMPDEV).  That's what
984 +        * triggers everything else.
985 +        */
986 +       switch (cmd) {
987 +       case DIOSDUMPDEV:       /* set dump_device */
988 +               pr_debug("Configuring dump device\n"); 
989 +               if (!(f->f_flags & O_RDWR))
990 +                       return -EPERM;
991 +
992 +               __dump_open();
993 +               return dumper_setup(dump_config.flags, arg);
994 +
995 +               
996 +       case DIOGDUMPDEV:       /* get dump_device */
997 +               return put_user((long)dump_config.dump_device, (long *)arg);
998 +
999 +       case DIOSDUMPLEVEL:     /* set dump_level */
1000 +               if (!(f->f_flags & O_RDWR))
1001 +                       return -EPERM;
1002 +
1003 +               /* make sure we have a positive value */
1004 +               if (arg < 0)
1005 +                       return -EINVAL;
1006 +
1007 +               /* Fixme: clean this up */
1008 +               dump_config.level = 0;
1009 +               switch ((int)arg) {
1010 +                       case DUMP_LEVEL_ALL:
1011 +                       case DUMP_LEVEL_ALL_RAM:
1012 +                               dump_config.level |= DUMP_MASK_UNUSED;
1013 +                       case DUMP_LEVEL_USED:
1014 +                               dump_config.level |= DUMP_MASK_USED;
1015 +                       case DUMP_LEVEL_KERN:
1016 +                               dump_config.level |= DUMP_MASK_KERN;
1017 +                       case DUMP_LEVEL_HEADER:
1018 +                               dump_config.level |= DUMP_MASK_HEADER;
1019 +                       case DUMP_LEVEL_NONE:
1020 +                               break;
1021 +                       default:
1022 +                               return (-EINVAL);
1023 +                       }
1024 +               pr_debug("Dump Level 0x%lx\n", dump_config.level);
1025 +               break;
1026 +
1027 +       case DIOGDUMPLEVEL:     /* get dump_level */
1028 +               /* fixme: handle conversion */
1029 +               return put_user((long)dump_config.level, (long *)arg);
1030 +
1031 +               
1032 +       case DIOSDUMPFLAGS:     /* set dump_flags */
1033 +               /* check flags */
1034 +               if (!(f->f_flags & O_RDWR))
1035 +                       return -EPERM;
1036 +
1037 +               /* make sure we have a positive value */
1038 +               if (arg < 0)
1039 +                       return -EINVAL;
1040 +                       
1041 +               if (dump_target_init(arg & DUMP_FLAGS_TARGETMASK) < 0)
1042 +                       return -EINVAL; /* return proper error */
1043 +
1044 +               dump_config.flags = arg;
1045 +               
1046 +               pr_debug("Dump Flags 0x%lx\n", dump_config.flags);
1047 +               break;
1048 +               
1049 +       case DIOGDUMPFLAGS:     /* get dump_flags */
1050 +               return put_user((long)dump_config.flags, (long *)arg);
1051 +
1052 +       case DIOSDUMPCOMPRESS:  /* set the dump_compress status */
1053 +               if (!(f->f_flags & O_RDWR))
1054 +                       return -EPERM;
1055 +
1056 +               return dump_compress_init((int)arg);
1057 +
1058 +       case DIOGDUMPCOMPRESS:  /* get the dump_compress status */
1059 +               return put_user((long)(dump_config.dumper ? 
1060 +                       dump_config.dumper->compress->compress_type : 0), 
1061 +                       (long *)arg);
1062 +       case DIOGDUMPOKAY: /* check if dump is configured */
1063 +               return put_user((long)dump_okay, (long *)arg);
1064 +       
1065 +       case DIOSDUMPTAKE: /* Trigger a manual dump */
1066 +               /* Do not proceed if lkcd not yet configured */
1067 +               if(!dump_okay) {
1068 +                       printk("LKCD not yet configured. Cannot take manual dump\n");
1069 +                       return -ENODEV;
1070 +               }
1071 +
1072 +               /* Take the dump */
1073 +               return  manual_handle_crashdump();
1074 +                       
1075 +       default:
1076 +               /* 
1077 +                * these are network dump specific ioctls, let the
1078 +                * module handle them.
1079 +                */
1080 +               return dump_dev_ioctl(cmd, arg);
1081 +       }
1082 +       return 0;
1083 +}
1084 +
1085 +/*
1086 + * Handle special cases for dump_device 
1087 + * changing dump device requires doing an opening the device
1088 + */
1089 +static int 
1090 +proc_dump_device(ctl_table *ctl, int write, struct file *f,
1091 +                void __user *buffer, size_t *lenp, loff_t *ppos)
1092 +{
1093 +       int *valp = ctl->data;
1094 +       int oval = *valp;
1095 +       int ret = -EPERM;
1096 +
1097 +       /* same permission checks as ioctl */
1098 +       if (capable(CAP_SYS_ADMIN)) {
1099 +               ret = proc_doulonghex(ctl, write, f, buffer, lenp, ppos);
1100 +               if (ret == 0 && write && *valp != oval) {
1101 +                       /* need to restore old value to close properly */
1102 +                       dump_config.dump_device = (dev_t) oval;
1103 +                       __dump_open();
1104 +                       ret = dumper_setup(dump_config.flags, (dev_t) *valp);
1105 +               }
1106 +       }
1107 +
1108 +       return ret;
1109 +}
1110 +
1111 +/* All for the want of a proc_do_xxx routine which prints values in hex */
1112 +/* Write is not implemented correctly, so mode is set to 0444 above. */
1113 +static int 
1114 +proc_doulonghex(ctl_table *ctl, int write, struct file *f,
1115 +                void __user *buffer, size_t *lenp, loff_t *ppos)
1116 +{
1117 +#define TMPBUFLEN 21
1118 +       unsigned long *i;
1119 +       size_t len, left;
1120 +       char buf[TMPBUFLEN];
1121 +
1122 +       if (!ctl->data || !ctl->maxlen || !*lenp || (*ppos && !write)) {
1123 +               *lenp = 0;
1124 +               return 0;
1125 +       }
1126 +       
1127 +       i = (unsigned long *) ctl->data;
1128 +       left = *lenp;
1129 +       
1130 +       sprintf(buf, "0x%lx\n", (*i));
1131 +       len = strlen(buf);
1132 +       if (len > left)
1133 +               len = left;
1134 +       if(copy_to_user(buffer, buf, len))
1135 +               return -EFAULT;
1136 +       
1137 +       left -= len;
1138 +       *lenp -= left;
1139 +       *ppos += *lenp;
1140 +       return 0;
1141 +}
1142 +
1143 +/*
1144 + * -----------------------------------------------------------------------
1145 + *                     I N I T   F U N C T I O N S
1146 + * -----------------------------------------------------------------------
1147 + */
1148 +
1149 +#ifdef CONFIG_COMPAT
1150 +static int dw_long(unsigned int fd, unsigned int cmd, unsigned long arg,
1151 +                struct file *f)
1152 +{
1153 +        mm_segment_t old_fs = get_fs();
1154 +        int err;
1155 +        unsigned long val;
1156 +
1157 +        set_fs (KERNEL_DS);
1158 +        err = sys_ioctl(fd, cmd, (u64)&val);
1159 +        set_fs (old_fs);
1160 +        if (!err && put_user((unsigned int) val, (u32 *)arg))
1161 +               return -EFAULT;
1162 +        return err;
1163 +}
1164 +#endif
1165 +
1166 +/*
1167 + * These register and unregister routines are exported for modules
1168 + * to register their dump drivers (like block, net etc)
1169 + */
1170 +int
1171 +dump_register_device(struct dump_dev *ddev)
1172 +{
1173 +       struct list_head *tmp;
1174 +       struct dump_dev *dev;
1175 +
1176 +       list_for_each(tmp, &dump_target_list) {
1177 +               dev = list_entry(tmp, struct dump_dev, list);
1178 +               if (strcmp(ddev->type_name, dev->type_name) == 0) {
1179 +                       printk("Target type %s already registered\n",
1180 +                                       dev->type_name);
1181 +                       return -1; /* return proper error */
1182 +               }
1183 +       }
1184 +       list_add(&(ddev->list), &dump_target_list);
1185 +       
1186 +       return 0;
1187 +}
1188 +
1189 +void
1190 +dump_unregister_device(struct dump_dev *ddev)
1191 +{
1192 +       list_del(&(ddev->list));
1193 +       if (ddev != dump_dev)
1194 +               return;
1195 +
1196 +       dump_okay = 0;
1197 +
1198 +       if (dump_config.dumper)
1199 +               dump_unconfigure();
1200 +
1201 +       dump_config.flags &= ~DUMP_FLAGS_TARGETMASK;
1202 +       dump_okay = 0;
1203 +       dump_dev = NULL;
1204 +       dump_config.dumper = NULL;
1205 +}
1206 +
1207 +static int panic_event(struct notifier_block *this, unsigned long event,
1208 +                      void *ptr)
1209 +{
1210 +#ifdef CONFIG_ARM
1211 +       get_current_general_regs(&all_regs);
1212 +       get_current_cp14_regs(&all_regs);
1213 +       get_current_cp15_regs(&all_regs);
1214 +       dump_execute((const char *)ptr, &all_regs);
1215 +#else
1216 +       struct pt_regs regs;
1217 +       
1218 +       get_current_regs(&regs);
1219 +       dump_execute((const char *)ptr, &regs);
1220 +#endif
1221 +       return 0;
1222 +}
1223 +
1224 +extern struct notifier_block *panic_notifier_list;
1225 +static int panic_event(struct notifier_block *, unsigned long, void *);
1226 +static struct notifier_block panic_block = {
1227 +       .notifier_call = panic_event,
1228 +};
1229 +
1230 +#ifdef CONFIG_MAGIC_SYSRQ
1231 +/* Sysrq handler */
1232 +static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
1233 +               struct tty_struct *tty) {
1234 +       if(!pt_regs) {
1235 +               struct pt_regs regs;
1236 +               get_current_regs(&regs);
1237 +               dump_execute("sysrq", &regs);
1238 +
1239 +       } else {
1240 +               dump_execute("sysrq", pt_regs);
1241 +       }
1242 +}
1243 +
1244 +static struct sysrq_key_op sysrq_crashdump_op = {
1245 +       .handler        =       sysrq_handle_crashdump,
1246 +       .help_msg       =       "Dump",
1247 +       .action_msg     =       "Starting crash dump",
1248 +};
1249 +#endif
1250 +
1251 +static inline void
1252 +dump_sysrq_register(void) 
1253 +{
1254 +#ifdef CONFIG_MAGIC_SYSRQ
1255 +       register_sysrq_key(DUMP_SYSRQ_KEY, &sysrq_crashdump_op);
1256 +#endif
1257 +}
1258 +
1259 +static inline void
1260 +dump_sysrq_unregister(void)
1261 +{
1262 +#ifdef CONFIG_MAGIC_SYSRQ
1263 +       unregister_sysrq_key(DUMP_SYSRQ_KEY, &sysrq_crashdump_op);
1264 +#endif
1265 +}
1266 +
1267 +/*
1268 + * Name: dump_init()
1269 + * Func: Initialize the dump process.  This will set up any architecture
1270 + *       dependent code.  The big key is we need the memory offsets before
1271 + *       the page table is initialized, because the base memory offset
1272 + *       is changed after paging_init() is called.
1273 + */
1274 +static int __init
1275 +dump_init(void)
1276 +{
1277 +       struct sysinfo info;
1278 +       int err;
1279 +
1280 +       /* try to create our dump device */
1281 +       err = misc_register(&dump_miscdev);
1282 +       if (err) {
1283 +               printk("cannot register dump character device!\n");
1284 +               return err;
1285 +       }
1286 +
1287 +       __dump_init((u64)PAGE_OFFSET);
1288 +
1289 +#ifdef CONFIG_COMPAT
1290 +       err = register_ioctl32_conversion(DIOSDUMPDEV, NULL);
1291 +       err |= register_ioctl32_conversion(DIOGDUMPDEV, NULL);
1292 +       err |= register_ioctl32_conversion(DIOSDUMPLEVEL, NULL);
1293 +       err |= register_ioctl32_conversion(DIOGDUMPLEVEL, dw_long);
1294 +       err |= register_ioctl32_conversion(DIOSDUMPFLAGS, NULL);
1295 +       err |= register_ioctl32_conversion(DIOGDUMPFLAGS, dw_long);
1296 +       err |= register_ioctl32_conversion(DIOSDUMPCOMPRESS, NULL);
1297 +       err |= register_ioctl32_conversion(DIOGDUMPCOMPRESS, dw_long);
1298 +       err |= register_ioctl32_conversion(DIOSTARGETIP, NULL);
1299 +       err |= register_ioctl32_conversion(DIOGTARGETIP, NULL);
1300 +       err |= register_ioctl32_conversion(DIOSTARGETPORT, NULL);
1301 +       err |= register_ioctl32_conversion(DIOGTARGETPORT, NULL);
1302 +       err |= register_ioctl32_conversion(DIOSSOURCEPORT, NULL);
1303 +       err |= register_ioctl32_conversion(DIOGSOURCEPORT, NULL);
1304 +       err |= register_ioctl32_conversion(DIOSETHADDR, NULL);
1305 +       err |= register_ioctl32_conversion(DIOGETHADDR, NULL);
1306 +       err |= register_ioctl32_conversion(DIOGDUMPOKAY, dw_long);
1307 +       err |= register_ioctl32_conversion(DIOSDUMPTAKE, NULL);
1308 +       if (err) {
1309 +                printk(KERN_ERR "LKCD: registering ioctl32 translations failed\
1310 +");
1311 +       }
1312 +#endif
1313 +       /* set the dump_compression_list structure up */
1314 +       dump_register_compression(&dump_none_compression);
1315 +
1316 +       /* grab the total memory size now (not if/when we crash) */
1317 +       si_meminfo(&info);
1318 +
1319 +       /* set the memory size */
1320 +       dump_header.dh_memory_size = (u64)info.totalram;
1321 +
1322 +       sysctl_header = register_sysctl_table(kernel_root, 0);
1323 +       dump_sysrq_register();
1324 +
1325 +       notifier_chain_register(&panic_notifier_list, &panic_block);
1326 +       dump_function_ptr = dump_execute;
1327 +
1328 +       pr_info("Crash dump driver initialized.\n");
1329 +       return 0;
1330 +}
1331 +
1332 +static void __exit
1333 +dump_cleanup(void)
1334 +{
1335 +       int err;
1336 +       dump_okay = 0;
1337 +
1338 +       if (dump_config.dumper)
1339 +               dump_unconfigure();
1340 +
1341 +       /* arch-specific cleanup routine */
1342 +       __dump_cleanup();
1343 +
1344 +#ifdef CONFIG_COMPAT
1345 +       err = unregister_ioctl32_conversion(DIOSDUMPDEV);
1346 +       err |= unregister_ioctl32_conversion(DIOGDUMPDEV);
1347 +       err |= unregister_ioctl32_conversion(DIOSDUMPLEVEL);
1348 +       err |= unregister_ioctl32_conversion(DIOGDUMPLEVEL);
1349 +       err |= unregister_ioctl32_conversion(DIOSDUMPFLAGS);
1350 +       err |= unregister_ioctl32_conversion(DIOGDUMPFLAGS);
1351 +       err |= unregister_ioctl32_conversion(DIOSDUMPCOMPRESS);
1352 +       err |= unregister_ioctl32_conversion(DIOGDUMPCOMPRESS);
1353 +       err |= unregister_ioctl32_conversion(DIOSTARGETIP);
1354 +       err |= unregister_ioctl32_conversion(DIOGTARGETIP);
1355 +       err |= unregister_ioctl32_conversion(DIOSTARGETPORT);
1356 +       err |= unregister_ioctl32_conversion(DIOGTARGETPORT);
1357 +       err |= unregister_ioctl32_conversion(DIOSSOURCEPORT);
1358 +       err |= unregister_ioctl32_conversion(DIOGSOURCEPORT);
1359 +       err |= unregister_ioctl32_conversion(DIOSETHADDR);
1360 +       err |= unregister_ioctl32_conversion(DIOGETHADDR);
1361 +       err |= unregister_ioctl32_conversion(DIOGDUMPOKAY);
1362 +       err |= unregister_ioctl32_conversion(DIOSDUMPTAKE);
1363 +       if (err) {
1364 +               printk(KERN_ERR "LKCD: Unregistering ioctl32 translations failed\n");
1365 +       }
1366 +#endif
1367 +
1368 +       /* ignore errors while unregistering -- since can't do anything */
1369 +       unregister_sysctl_table(sysctl_header);
1370 +       misc_deregister(&dump_miscdev);
1371 +       dump_sysrq_unregister();
1372 +       notifier_chain_unregister(&panic_notifier_list, &panic_block);
1373 +       dump_function_ptr = NULL;
1374 +}
1375 +
1376 +EXPORT_SYMBOL(dump_register_compression);
1377 +EXPORT_SYMBOL(dump_unregister_compression);
1378 +EXPORT_SYMBOL(dump_register_device);
1379 +EXPORT_SYMBOL(dump_unregister_device);
1380 +EXPORT_SYMBOL(dump_config);
1381 +EXPORT_SYMBOL(dump_silence_level);
1382 +
1383 +EXPORT_SYMBOL(__dump_irq_enable);
1384 +EXPORT_SYMBOL(__dump_irq_restore);
1385 +
1386 +MODULE_AUTHOR("Matt D. Robinson <yakker@sourceforge.net>");
1387 +MODULE_DESCRIPTION("Linux Kernel Crash Dump (LKCD) driver");
1388 +MODULE_LICENSE("GPL");
1389 +
1390 +module_init(dump_init);
1391 +module_exit(dump_cleanup);
1392 Index: linux-2.6.10-base/drivers/dump/dump_execute.c
1393 ===================================================================
1394 --- linux-2.6.10-base.orig/drivers/dump/dump_execute.c  2003-09-02 06:26:13.000000000 +0800
1395 +++ linux-2.6.10-base/drivers/dump/dump_execute.c       2005-05-17 18:52:39.930056120 +0800
1396 @@ -0,0 +1,144 @@
1397 +/*
1398 + * The file has the common/generic dump execution code 
1399 + *
1400 + * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
1401 + *     Split and rewrote high level dump execute code to make use 
1402 + *     of dump method interfaces.
1403 + *
1404 + * Derived from original code in dump_base.c created by 
1405 + *     Matt Robinson <yakker@sourceforge.net>)
1406 + *     
1407 + * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
1408 + * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
1409 + * Copyright (C) 2002 International Business Machines Corp. 
1410 + *
1411 + * Assumes dumper and dump config settings are in place
1412 + * (invokes corresponding dumper specific routines as applicable)
1413 + *
1414 + * This code is released under version 2 of the GNU GPL.
1415 + */
1416 +#include <linux/kernel.h>
1417 +#include <linux/notifier.h>
1418 +#include <linux/dump.h>
1419 +#include <linux/delay.h>
1420 +#include <linux/reboot.h>
1421 +#include "dump_methods.h"
1422 +
1423 +struct notifier_block *dump_notifier_list; /* dump started/ended callback */
1424 +
1425 +extern int panic_timeout;
1426 +
1427 +/* Dump progress indicator */
1428 +void 
1429 +dump_speedo(int i)
1430 +{
1431 +       static const char twiddle[4] =  { '|', '\\', '-', '/' };
1432 +       printk("%c\b", twiddle[i&3]);
1433 +}
1434 +
1435 +/* Make the device ready and write out the header */
1436 +int dump_begin(void)
1437 +{
1438 +       int err = 0;
1439 +
1440 +       /* dump_dev = dump_config.dumper->dev; */
1441 +       dumper_reset();
1442 +       if ((err = dump_dev_silence())) {
1443 +               /* quiesce failed, can't risk continuing */
1444 +               /* Todo/Future: switch to alternate dump scheme if possible */
1445 +               printk("dump silence dev failed ! error %d\n", err);
1446 +               return err;
1447 +       }
1448 +
1449 +       pr_debug("Writing dump header\n");
1450 +       if ((err = dump_update_header())) {
1451 +               printk("dump update header failed ! error %d\n", err);
1452 +               dump_dev_resume();
1453 +               return err;
1454 +       }
1455 +
1456 +       dump_config.dumper->curr_offset = DUMP_BUFFER_SIZE;
1457 +
1458 +       return 0;
1459 +}
1460 +
1461 +/* 
1462 + * Write the dump terminator, a final header update and let go of 
1463 + * exclusive use of the device for dump.
1464 + */
1465 +int dump_complete(void)
1466 +{
1467 +       int ret = 0;
1468 +
1469 +       if (dump_config.level != DUMP_LEVEL_HEADER) {
1470 +               if ((ret = dump_update_end_marker())) {
1471 +                       printk("dump update end marker error %d\n", ret);
1472 +               }
1473 +               if ((ret = dump_update_header())) {
1474 +                       printk("dump update header error %d\n", ret);
1475 +               }
1476 +       }
1477 +       ret = dump_dev_resume();
1478 +
1479 +       if ((panic_timeout > 0) && (!(dump_config.flags & (DUMP_FLAGS_SOFTBOOT | DUMP_FLAGS_NONDISRUPT)))) {
1480 +               mdelay(panic_timeout * 1000);
1481 +               machine_restart(NULL);
1482 +       }
1483 +
1484 +       return ret;
1485 +}
1486 +
1487 +/* Saves all dump data */
1488 +int dump_execute_savedump(void)
1489 +{
1490 +       int ret = 0, err = 0;
1491 +
1492 +       if ((ret = dump_begin()))  {
1493 +               return ret;
1494 +       }
1495 +
1496 +       if (dump_config.level != DUMP_LEVEL_HEADER) { 
1497 +               ret = dump_sequencer();
1498 +       }
1499 +       if ((err = dump_complete())) {
1500 +               printk("Dump complete failed. Error %d\n", err);
1501 +       }
1502 +
1503 +       return ret;
1504 +}
1505 +
1506 +extern void dump_calc_bootmap_pages(void);
1507 +
1508 +/* Does all the real work:  Capture and save state */
1509 +int dump_generic_execute(const char *panic_str, const struct pt_regs *regs)
1510 +{
1511 +       int ret = 0;
1512 +
1513 +#ifdef CONFIG_DISCONTIGMEM
1514 +        printk(KERN_INFO "Reconfiguring memory bank information....\n");
1515 +        printk(KERN_INFO "This may take a while....\n");
1516 +        dump_reconfigure_mbanks();
1517 +#endif
1518 +
1519 +       if ((ret = dump_configure_header(panic_str, regs))) {
1520 +               printk("dump config header failed ! error %d\n", ret);
1521 +               return ret;     
1522 +       }
1523 +
1524 +       dump_calc_bootmap_pages();
1525 +       /* tell interested parties that a dump is about to start */
1526 +       notifier_call_chain(&dump_notifier_list, DUMP_BEGIN, 
1527 +               &dump_config.dump_device);
1528 +
1529 +       if (dump_config.level != DUMP_LEVEL_NONE)
1530 +               ret = dump_execute_savedump();
1531 +
1532 +       pr_debug("dumped %ld blocks of %d bytes each\n", 
1533 +               dump_config.dumper->count, DUMP_BUFFER_SIZE);
1534 +       
1535 +       /* tell interested parties that a dump has completed */
1536 +       notifier_call_chain(&dump_notifier_list, DUMP_END, 
1537 +               &dump_config.dump_device);
1538 +
1539 +       return ret;
1540 +}
1541 Index: linux-2.6.10-base/drivers/dump/dump_x8664.c
1542 ===================================================================
1543 --- linux-2.6.10-base.orig/drivers/dump/dump_x8664.c    2003-09-02 06:26:13.000000000 +0800
1544 +++ linux-2.6.10-base/drivers/dump/dump_x8664.c 2005-05-18 15:26:17.477797232 +0800
1545 @@ -0,0 +1,362 @@
1546 +/*
1547 + * Architecture specific (x86-64) functions for Linux crash dumps.
1548 + *
1549 + * Created by: Matt Robinson (yakker@sgi.com)
1550 + *
1551 + * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
1552 + *
1553 + * 2.3 kernel modifications by: Matt D. Robinson (yakker@turbolinux.com)
1554 + * Copyright 2000 TurboLinux, Inc.  All rights reserved.
1555 + *
1556 + * x86-64 port Copyright 2002 Andi Kleen, SuSE Labs
1557 + * x86-64 port Sachin Sant ( sachinp@in.ibm.com )
1558 + * This code is released under version 2 of the GNU GPL.
1559 + */
1560 +
1561 +/*
1562 + * The hooks for dumping the kernel virtual memory to disk are in this
1563 + * file.  Any time a modification is made to the virtual memory mechanism,
1564 + * these routines must be changed to use the new mechanisms.
1565 + */
1566 +#include <linux/init.h>
1567 +#include <linux/types.h>
1568 +#include <linux/kernel.h>
1569 +#include <linux/smp.h>
1570 +#include <linux/fs.h>
1571 +#include <linux/vmalloc.h>
1572 +#include <linux/dump.h>
1573 +#include "dump_methods.h"
1574 +#include <linux/mm.h>
1575 +#include <linux/rcupdate.h>
1576 +#include <asm/processor.h>
1577 +#include <asm/hardirq.h>
1578 +#include <asm/kdebug.h>
1579 +#include <asm/uaccess.h>
1580 +#include <asm/nmi.h>
1581 +#include <asm/kdebug.h>
1582 +
1583 +static __s32   saved_irq_count; /* saved preempt_count() flag */
1584 +
1585 +void (*dump_trace_ptr)(struct pt_regs *);
1586 +
1587 +static int alloc_dha_stack(void)
1588 +{
1589 +       int i;
1590 +       void *ptr;
1591 +       
1592 +       if (dump_header_asm.dha_stack[0])
1593 +               return 0;
1594 +
1595 +               ptr = vmalloc(THREAD_SIZE * num_online_cpus());
1596 +       if (!ptr) {
1597 +               printk("vmalloc for dha_stacks failed\n");
1598 +               return -ENOMEM;
1599 +       }
1600 +
1601 +       for (i = 0; i < num_online_cpus(); i++) {
1602 +               dump_header_asm.dha_stack[i] = 
1603 +                       (uint64_t)((unsigned long)ptr + (i * THREAD_SIZE));
1604 +       }
1605 +       return 0;
1606 +}
1607 +
1608 +static int free_dha_stack(void) 
1609 +{
1610 +       if (dump_header_asm.dha_stack[0]) {
1611 +               vfree((void *)dump_header_asm.dha_stack[0]);    
1612 +               dump_header_asm.dha_stack[0] = 0;
1613 +       }       
1614 +       return 0;
1615 +}
1616 +
1617 +void
1618 +__dump_save_regs(struct pt_regs* dest_regs, const struct pt_regs* regs)
1619 +{
1620 +       if (regs)
1621 +               memcpy(dest_regs, regs, sizeof(struct pt_regs));
1622 +}
1623 +
1624 +void
1625 +__dump_save_context(int cpu, const struct pt_regs *regs, 
1626 +       struct task_struct *tsk)
1627 +{
1628 +       dump_header_asm.dha_smp_current_task[cpu] = (unsigned long)tsk;
1629 +       __dump_save_regs(&dump_header_asm.dha_smp_regs[cpu], regs);
1630 +
1631 +       /* take a snapshot of the stack */
1632 +       /* doing this enables us to tolerate slight drifts on this cpu */
1633 +
1634 +       if (dump_header_asm.dha_stack[cpu]) {
1635 +               memcpy((void *)dump_header_asm.dha_stack[cpu],
1636 +                               STACK_START_POSITION(tsk),
1637 +                               THREAD_SIZE);
1638 +       }
1639 +       dump_header_asm.dha_stack_ptr[cpu] = (unsigned long)(tsk->thread_info);
1640 +}
1641 +
1642 +#ifdef CONFIG_SMP
1643 +extern cpumask_t irq_affinity[];
1644 +extern irq_desc_t irq_desc[];
1645 +extern void dump_send_ipi(void);
1646 +static int dump_expect_ipi[NR_CPUS];
1647 +static atomic_t waiting_for_dump_ipi;
1648 +static cpumask_t saved_affinity[NR_IRQS];
1649 +
1650 +extern void stop_this_cpu(void *);
1651 +
1652 +static int
1653 +dump_nmi_callback(struct pt_regs *regs, int cpu) 
1654 +{
1655 +       if (!dump_expect_ipi[cpu]) {
1656 +               return 0;
1657 +       }
1658 +       
1659 +       dump_expect_ipi[cpu] = 0;
1660 +
1661 +       dump_save_this_cpu(regs);
1662 +       atomic_dec(&waiting_for_dump_ipi);
1663 +
1664 +level_changed:
1665 +
1666 +       switch (dump_silence_level) {
1667 +        case DUMP_HARD_SPIN_CPUS:       /* Spin until dump is complete */
1668 +                while (dump_oncpu) {
1669 +                        barrier();      /* paranoia */
1670 +                        if (dump_silence_level != DUMP_HARD_SPIN_CPUS)
1671 +                                goto level_changed;
1672 +
1673 +                        cpu_relax();    /* kill time nicely */
1674 +                }
1675 +                break;
1676 +
1677 +        case DUMP_HALT_CPUS:            /* Execute halt */
1678 +                stop_this_cpu(NULL);
1679 +                break;
1680 +
1681 +        case DUMP_SOFT_SPIN_CPUS:
1682 +                /* Mark the task so it spins in schedule */
1683 +                set_tsk_thread_flag(current, TIF_NEED_RESCHED);
1684 +                break;
1685 +        }
1686 +
1687 +       return 1;
1688 +}
1689 +
1690 +/* save registers on other processors */
1691 +void 
1692 +__dump_save_other_cpus(void) 
1693 +{
1694 +       int i, cpu = smp_processor_id();
1695 +       int other_cpus = num_online_cpus() - 1;
1696 +
1697 +       if (other_cpus > 0) {
1698 +               atomic_set(&waiting_for_dump_ipi, other_cpus);
1699 +
1700 +               for (i = 0; i < NR_CPUS; i++)
1701 +                       dump_expect_ipi[i] = (i != cpu && cpu_online(i));
1702 +               
1703 +               set_nmi_callback(dump_nmi_callback);
1704 +               wmb();
1705 +
1706 +               dump_send_ipi();
1707 +
1708 +               /* may be we dont need to wait for NMI to be processed. 
1709 +                  just write out the header at the end of dumping, if
1710 +                  this IPI is not processed untill then, there probably
1711 +                  is a problem and we just fail to capture state of 
1712 +                  other cpus. */
1713 +               while(atomic_read(&waiting_for_dump_ipi) > 0)
1714 +                       cpu_relax();
1715 +
1716 +               unset_nmi_callback();
1717 +       }
1718 +       return;
1719 +}
1720 +
1721 +/*
1722 + * Routine to save the old irq affinities and change affinities of all irqs to
1723 + * the dumping cpu.
1724 + */
1725 +static void
1726 +set_irq_affinity(void)
1727 +{
1728 +       int i;
1729 +       cpumask_t cpu = CPU_MASK_NONE;
1730 +
1731 +       cpu_set(smp_processor_id(), cpu); 
1732 +       memcpy(saved_affinity, irq_affinity, NR_IRQS * sizeof(unsigned long));
1733 +       for (i = 0; i < NR_IRQS; i++) {
1734 +               if (irq_desc[i].handler == NULL)
1735 +                       continue;
1736 +               irq_affinity[i] = cpu;
1737 +               if (irq_desc[i].handler->set_affinity != NULL)
1738 +                       irq_desc[i].handler->set_affinity(i, irq_affinity[i]);
1739 +       }
1740 +}
1741 +
1742 +/*
1743 + * Restore old irq affinities.
1744 + */
1745 +static void
1746 +reset_irq_affinity(void)
1747 +{
1748 +       int i;
1749 +
1750 +       memcpy(irq_affinity, saved_affinity, NR_IRQS * sizeof(unsigned long));
1751 +       for (i = 0; i < NR_IRQS; i++) {
1752 +               if (irq_desc[i].handler == NULL)
1753 +                       continue;
1754 +               if (irq_desc[i].handler->set_affinity != NULL)
1755 +                       irq_desc[i].handler->set_affinity(i, saved_affinity[i]);
1756 +       }
1757 +}
1758 +
1759 +#else /* !CONFIG_SMP */
1760 +#define set_irq_affinity()     do { } while (0)
1761 +#define reset_irq_affinity()   do { } while (0)
1762 +#define save_other_cpu_states() do { } while (0)
1763 +#endif /* !CONFIG_SMP */
1764 +
1765 +static inline void
1766 +irq_bh_save(void)
1767 +{
1768 +       saved_irq_count = irq_count();
1769 +       preempt_count() &= ~(HARDIRQ_MASK|SOFTIRQ_MASK);
1770 +}
1771 +
1772 +static inline void
1773 +irq_bh_restore(void)
1774 +{
1775 +       preempt_count() |= saved_irq_count;
1776 +}
1777 +
1778 +/*
1779 + * Name: __dump_irq_enable
1780 + * Func: Reset system so interrupts are enabled.
1781 + *       This is used for dump methods that require interrupts
1782 + *       Eventually, all methods will have interrupts disabled
1783 + *       and this code can be removed.
1784 + *
1785 + *     Change irq affinities
1786 + *     Re-enable interrupts
1787 + */
1788 +int
1789 +__dump_irq_enable(void)
1790 +{
1791 +        set_irq_affinity();
1792 +        irq_bh_save();
1793 +        local_irq_enable();
1794 +       return 0;
1795 +}
1796 +
1797 +/*
1798 + * Name: __dump_irq_restore
1799 + * Func: Resume the system state in an architecture-speeific way.
1800 + *
1801 + */
1802 +void
1803 +__dump_irq_restore(void)
1804 +{
1805 +        local_irq_disable();
1806 +        reset_irq_affinity();
1807 +        irq_bh_restore();
1808 +}
1809 +
1810 +/*
1811 + * Name: __dump_configure_header()
1812 + * Func: Configure the dump header with all proper values.
1813 + */
1814 +int
1815 +__dump_configure_header(const struct pt_regs *regs)
1816 +{
1817 +       /* Dummy function - return */
1818 +       return (0);
1819 +}
1820 +
1821 +static int notify(struct notifier_block *nb, unsigned long code, void *data)
1822 +{
1823 +       if (code == DIE_NMI_IPI && dump_oncpu)
1824 +               return NOTIFY_BAD; 
1825 +       return NOTIFY_DONE; 
1826 +} 
1827 +
1828 +static struct notifier_block dump_notifier = { 
1829 +       .notifier_call = notify,        
1830 +}; 
1831 +
1832 +/*
1833 + * Name: __dump_init()
1834 + * Func: Initialize the dumping routine process.
1835 + */
1836 +void
1837 +__dump_init(uint64_t local_memory_start)
1838 +{
1839 +       notifier_chain_register(&die_chain, &dump_notifier);
1840 +}
1841 +
1842 +/*
1843 + * Name: __dump_open()
1844 + * Func: Open the dump device (architecture specific).  This is in
1845 + *       case it's necessary in the future.
1846 + */
1847 +void
1848 +__dump_open(void)
1849 +{
1850 +       alloc_dha_stack();
1851 +       /* return */
1852 +       return;
1853 +}
1854 +
1855 +/*
1856 + * Name: __dump_cleanup()
1857 + * Func: Free any architecture specific data structures. This is called
1858 + *       when the dump module is being removed.
1859 + */
1860 +void
1861 +__dump_cleanup(void)
1862 +{
1863 +       free_dha_stack();
1864 +       notifier_chain_unregister(&die_chain, &dump_notifier);
1865 +       synchronize_kernel(); 
1866 +       return;
1867 +}
1868 +
1869 +extern int page_is_ram(unsigned long);
1870 +
1871 +/*
1872 + * Name: __dump_page_valid()
1873 + * Func: Check if page is valid to dump.
1874 + */
1875 +int
1876 +__dump_page_valid(unsigned long index)
1877 +{
1878 +       if (!pfn_valid(index))
1879 +               return 0;
1880 +
1881 +       return page_is_ram(index);
1882 +}
1883 +
1884 +/*
1885 + * Name: manual_handle_crashdump()
1886 + * Func: Interface for the lkcd dump command. Calls dump_execute()
1887 + */
1888 +int
1889 +manual_handle_crashdump(void) {
1890 +
1891 +        struct pt_regs regs;
1892 +
1893 +        get_current_regs(&regs);
1894 +        dump_execute("manual", &regs);
1895 +        return 0;
1896 +}
1897 +
1898 +/*
1899 + * Name: __dump_clean_irq_state()
1900 + * Func: Clean up from the previous IRQ handling state. Such as oops from 
1901 + *       interrupt handler or bottom half.
1902 + */
1903 +void
1904 +__dump_clean_irq_state(void)
1905 +{
1906 +    return;
1907 +}
1908 Index: linux-2.6.10-base/drivers/dump/dump_rle.c
1909 ===================================================================
1910 --- linux-2.6.10-base.orig/drivers/dump/dump_rle.c      2003-09-02 06:26:13.000000000 +0800
1911 +++ linux-2.6.10-base/drivers/dump/dump_rle.c   2005-05-17 18:52:39.931055968 +0800
1912 @@ -0,0 +1,176 @@
1913 +/*
1914 + * RLE Compression functions for kernel crash dumps.
1915 + *
1916 + * Created by: Matt Robinson (yakker@sourceforge.net)
1917 + * Copyright 2001 Matt D. Robinson.  All rights reserved.
1918 + *
1919 + * This code is released under version 2 of the GNU GPL.
1920 + */
1921 +
1922 +/* header files */
1923 +#include <linux/config.h>
1924 +#include <linux/module.h>
1925 +#include <linux/sched.h>
1926 +#include <linux/fs.h>
1927 +#include <linux/file.h>
1928 +#include <linux/init.h>
1929 +#include <linux/dump.h>
1930 +
1931 +/*
1932 + * Name: dump_compress_rle()
1933 + * Func: Compress a DUMP_PAGE_SIZE (hardware) page down to something more
1934 + *       reasonable, if possible.  This is the same routine we use in IRIX.
1935 + */
1936 +static u32
1937 +dump_compress_rle(const u8 *old, u32 oldsize, u8 *new, u32 newsize,
1938 +               unsigned long loc)
1939 +{
1940 +       u16 ri, wi, count = 0;
1941 +       u_char value = 0, cur_byte;
1942 +
1943 +       /*
1944 +        * If the block should happen to "compress" to larger than the
1945 +        * buffer size, allocate a larger one and change cur_buf_size.
1946 +        */
1947 +
1948 +       wi = ri = 0;
1949 +
1950 +       while (ri < oldsize) {
1951 +               if (!ri) {
1952 +                       cur_byte = value = old[ri];
1953 +                       count = 0;
1954 +               } else {
1955 +                       if (count == 255) {
1956 +                               if (wi + 3 > oldsize) {
1957 +                                       return oldsize;
1958 +                               }
1959 +                               new[wi++] = 0;
1960 +                               new[wi++] = count;
1961 +                               new[wi++] = value;
1962 +                               value = cur_byte = old[ri];
1963 +                               count = 0;
1964 +                       } else { 
1965 +                               if ((cur_byte = old[ri]) == value) {
1966 +                                       count++;
1967 +                               } else {
1968 +                                       if (count > 1) {
1969 +                                               if (wi + 3 > oldsize) {
1970 +                                                       return oldsize;
1971 +                                               }
1972 +                                               new[wi++] = 0;
1973 +                                               new[wi++] = count;
1974 +                                               new[wi++] = value;
1975 +                                       } else if (count == 1) {
1976 +                                               if (value == 0) {
1977 +                                                       if (wi + 3 > oldsize) {
1978 +                                                               return oldsize;
1979 +                                                       }
1980 +                                                       new[wi++] = 0;
1981 +                                                       new[wi++] = 1;
1982 +                                                       new[wi++] = 0;
1983 +                                               } else {
1984 +                                                       if (wi + 2 > oldsize) {
1985 +                                                               return oldsize;
1986 +                                                       }
1987 +                                                       new[wi++] = value;
1988 +                                                       new[wi++] = value;
1989 +                                               }
1990 +                                       } else { /* count == 0 */
1991 +                                               if (value == 0) {
1992 +                                                       if (wi + 2 > oldsize) {
1993 +                                                               return oldsize;
1994 +                                                       }
1995 +                                                       new[wi++] = value;
1996 +                                                       new[wi++] = value;
1997 +                                               } else {
1998 +                                                       if (wi + 1 > oldsize) {
1999 +                                                               return oldsize;
2000 +                                                       }
2001 +                                                       new[wi++] = value;
2002 +                                               }
2003 +                                       } /* if count > 1 */
2004 +
2005 +                                       value = cur_byte;
2006 +                                       count = 0;
2007 +
2008 +                               } /* if byte == value */
2009 +
2010 +                       } /* if count == 255 */
2011 +
2012 +               } /* if ri == 0 */
2013 +               ri++;
2014 +
2015 +       }
2016 +       if (count > 1) {
2017 +               if (wi + 3 > oldsize) {
2018 +                       return oldsize;
2019 +               }
2020 +               new[wi++] = 0;
2021 +               new[wi++] = count;
2022 +               new[wi++] = value;
2023 +       } else if (count == 1) {
2024 +               if (value == 0) {
2025 +                       if (wi + 3 > oldsize)
2026 +                               return oldsize;
2027 +                       new[wi++] = 0;
2028 +                       new[wi++] = 1;
2029 +                       new[wi++] = 0;
2030 +               } else {
2031 +                       if (wi + 2 > oldsize)
2032 +                               return oldsize;
2033 +                       new[wi++] = value;
2034 +                       new[wi++] = value;
2035 +               }
2036 +       } else { /* count == 0 */
2037 +               if (value == 0) {
2038 +                       if (wi + 2 > oldsize)
2039 +                               return oldsize;
2040 +                       new[wi++] = value;
2041 +                       new[wi++] = value;
2042 +               } else {
2043 +                       if (wi + 1 > oldsize)
2044 +                               return oldsize;
2045 +                       new[wi++] = value;
2046 +               }
2047 +       } /* if count > 1 */
2048 +
2049 +       value = cur_byte;
2050 +       count = 0;
2051 +       return wi;
2052 +}
2053 +
2054 +/* setup the rle compression functionality */
2055 +static struct __dump_compress dump_rle_compression = {
2056 +       .compress_type = DUMP_COMPRESS_RLE,
2057 +       .compress_func = dump_compress_rle,
2058 +       .compress_name = "RLE",
2059 +};
2060 +
2061 +/*
2062 + * Name: dump_compress_rle_init()
2063 + * Func: Initialize rle compression for dumping.
2064 + */
2065 +static int __init
2066 +dump_compress_rle_init(void)
2067 +{
2068 +       dump_register_compression(&dump_rle_compression);
2069 +       return 0;
2070 +}
2071 +
2072 +/*
2073 + * Name: dump_compress_rle_cleanup()
2074 + * Func: Remove rle compression for dumping.
2075 + */
2076 +static void __exit
2077 +dump_compress_rle_cleanup(void)
2078 +{
2079 +       dump_unregister_compression(DUMP_COMPRESS_RLE);
2080 +}
2081 +
2082 +/* module initialization */
2083 +module_init(dump_compress_rle_init);
2084 +module_exit(dump_compress_rle_cleanup);
2085 +
2086 +MODULE_LICENSE("GPL");
2087 +MODULE_AUTHOR("LKCD Development Team <lkcd-devel@lists.sourceforge.net>");
2088 +MODULE_DESCRIPTION("RLE compression module for crash dump driver");
2089 Index: linux-2.6.10-base/drivers/dump/dump_overlay.c
2090 ===================================================================
2091 --- linux-2.6.10-base.orig/drivers/dump/dump_overlay.c  2003-09-02 06:26:13.000000000 +0800
2092 +++ linux-2.6.10-base/drivers/dump/dump_overlay.c       2005-05-17 18:52:39.932055816 +0800
2093 @@ -0,0 +1,890 @@
2094 +/*
2095 + * Two-stage soft-boot based dump scheme methods (memory overlay
2096 + * with post soft-boot writeout)
2097 + *
2098 + * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
2099 + *
2100 + * This approach of saving the dump in memory and writing it 
2101 + * out after a softboot without clearing memory is derived from the 
2102 + * Mission Critical Linux dump implementation. Credits and a big
2103 + * thanks for letting the lkcd project make use of the excellent 
2104 + * piece of work and also for helping with clarifications and 
2105 + * tips along the way are due to:
2106 + *     Dave Winchell <winchell@mclx.com> (primary author of mcore)
2107 + *     and also to
2108 + *     Jeff Moyer <moyer@mclx.com>
2109 + *     Josh Huber <huber@mclx.com>
2110 + * 
2111 + * For those familiar with the mcore implementation, the key 
2112 + * differences/extensions here are in allowing entire memory to be 
2113 + * saved (in compressed form) through a careful ordering scheme 
2114 + * on both the way down as well on the way up after boot, the latter
2115 + * for supporting the LKCD notion of passes in which most critical 
2116 + * data is the first to be saved to the dump device. Also the post 
2117 + * boot writeout happens from within the kernel rather than driven 
2118 + * from userspace.
2119 + *
2120 + * The sequence is orchestrated through the abstraction of "dumpers",
2121 + * one for the first stage which then sets up the dumper for the next 
2122 + * stage, providing for a smooth and flexible reuse of the singlestage 
2123 + * dump scheme methods and a handle to pass dump device configuration 
2124 + * information across the soft boot. 
2125 + *
2126 + * Copyright (C) 2002 International Business Machines Corp. 
2127 + *
2128 + * This code is released under version 2 of the GNU GPL.
2129 + */
2130 +
2131 +/*
2132 + * Disruptive dumping using the second kernel soft-boot option
2133 + * for issuing dump i/o operates in 2 stages:
2134 + * 
2135 + * (1) - Saves the (compressed & formatted) dump in memory using a 
2136 + *       carefully ordered overlay scheme designed to capture the 
2137 + *       entire physical memory or selective portions depending on 
2138 + *       dump config settings, 
2139 + *     - Registers the stage 2 dumper and 
2140 + *     - Issues a soft reboot w/o clearing memory. 
2141 + *
2142 + *     The overlay scheme starts with a small bootstrap free area
2143 + *     and follows a reverse ordering of passes wherein it 
2144 + *     compresses and saves data starting with the least critical 
2145 + *     areas first, thus freeing up the corresponding pages to 
2146 + *     serve as destination for subsequent data to be saved, and
2147 + *     so on. With a good compression ratio, this makes it feasible
2148 + *     to capture an entire physical memory dump without significantly
2149 + *     reducing memory available during regular operation.
2150 + *
2151 + * (2) Post soft-reboot, runs through the saved memory dump and
2152 + *     writes it out to disk, this time around, taking care to
2153 + *     save the more critical data first (i.e. pages which figure 
2154 + *     in early passes for a regular dump). Finally issues a 
2155 + *     clean reboot.
2156 + *     
2157 + *     Since the data was saved in memory after selection/filtering
2158 + *     and formatted as per the chosen output dump format, at this 
2159 + *     stage the filter and format actions are just dummy (or
2160 + *     passthrough) actions, except for influence on ordering of
2161 + *     passes.
2162 + */
2163 +
2164 +#include <linux/types.h>
2165 +#include <linux/kernel.h>
2166 +#include <linux/highmem.h>
2167 +#include <linux/bootmem.h>
2168 +#include <linux/dump.h>
2169 +#ifdef CONFIG_KEXEC
2170 +#include <linux/delay.h>
2171 +#include <linux/reboot.h>
2172 +#include <linux/kexec.h>
2173 +#endif
2174 +#include "dump_methods.h"
2175 +
2176 +extern struct list_head dumper_list_head;
2177 +extern struct dump_memdev *dump_memdev;
2178 +extern struct dumper dumper_stage2;
2179 +struct dump_config_block *dump_saved_config = NULL;
2180 +extern struct dump_blockdev *dump_blockdev;
2181 +static struct dump_memdev *saved_dump_memdev = NULL;
2182 +static struct dumper *saved_dumper = NULL;
2183 +
2184 +#ifdef CONFIG_KEXEC
2185 +extern int panic_timeout;
2186 +#endif
2187 +
2188 +/* For testing 
2189 +extern void dump_display_map(struct dump_memdev *);
2190 +*/
2191 +
2192 +struct dumper *dumper_by_name(char *name)
2193 +{
2194 +#ifdef LATER
2195 +       struct dumper *dumper;
2196 +       list_for_each_entry(dumper, &dumper_list_head, dumper_list)
2197 +               if (!strncmp(dumper->name, name, 32))
2198 +                       return dumper;
2199 +
2200 +       /* not found */
2201 +       return NULL; 
2202 +#endif
2203 +       /* Temporary proof of concept */
2204 +       if (!strncmp(dumper_stage2.name, name, 32))
2205 +               return &dumper_stage2;
2206 +       else
2207 +               return NULL;
2208 +}
2209 +
2210 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
2211 +extern void dump_early_reserve_map(struct dump_memdev *);
2212 +
2213 +void crashdump_reserve(void)
2214 +{
2215 +       extern unsigned long crashdump_addr;
2216 +
2217 +       if (crashdump_addr == 0xdeadbeef) 
2218 +               return;
2219 +
2220 +       /* reserve dump config and saved dump pages */
2221 +       dump_saved_config = (struct dump_config_block *)crashdump_addr;
2222 +       /* magic verification */
2223 +       if (dump_saved_config->magic != DUMP_MAGIC_LIVE) {
2224 +               printk("Invalid dump magic. Ignoring dump\n");
2225 +               dump_saved_config = NULL;
2226 +               return;
2227 +       }
2228 +                       
2229 +       printk("Dump may be available from previous boot\n");
2230 +
2231 +#ifdef CONFIG_X86_64
2232 +       reserve_bootmem_node(NODE_DATA(0), 
2233 +               virt_to_phys((void *)crashdump_addr), 
2234 +               PAGE_ALIGN(sizeof(struct dump_config_block)));
2235 +#else
2236 +       reserve_bootmem(virt_to_phys((void *)crashdump_addr), 
2237 +               PAGE_ALIGN(sizeof(struct dump_config_block)));
2238 +#endif
2239 +       dump_early_reserve_map(&dump_saved_config->memdev);
2240 +
2241 +}
2242 +#endif
2243 +
2244 +/* 
2245 + * Loads the dump configuration from a memory block saved across soft-boot
2246 + * The ops vectors need fixing up as the corresp. routines may have 
2247 + * relocated in the new soft-booted kernel.
2248 + */
2249 +int dump_load_config(struct dump_config_block *config)
2250 +{
2251 +       struct dumper *dumper;
2252 +       struct dump_data_filter *filter_table, *filter;
2253 +       struct dump_dev *dev;
2254 +       int i;
2255 +
2256 +       if (config->magic != DUMP_MAGIC_LIVE)
2257 +               return -ENOENT; /* not a valid config */
2258 +
2259 +       /* initialize generic config data */
2260 +       memcpy(&dump_config, &config->config, sizeof(dump_config));
2261 +
2262 +       /* initialize dumper state */
2263 +       if (!(dumper = dumper_by_name(config->dumper.name)))  {
2264 +               printk("dumper name mismatch\n");
2265 +               return -ENOENT; /* dumper mismatch */
2266 +       }
2267 +       
2268 +       /* verify and fixup schema */
2269 +       if (strncmp(dumper->scheme->name, config->scheme.name, 32)) {
2270 +               printk("dumper scheme mismatch\n");
2271 +               return -ENOENT; /* mismatch */
2272 +       }
2273 +       config->scheme.ops = dumper->scheme->ops;
2274 +       config->dumper.scheme = &config->scheme;
2275 +       
2276 +       /* verify and fixup filter operations */
2277 +       filter_table = dumper->filter;
2278 +       for (i = 0, filter = config->filter_table; 
2279 +               ((i < MAX_PASSES) && filter_table[i].selector); 
2280 +               i++, filter++) {
2281 +               if (strncmp(filter_table[i].name, filter->name, 32)) {
2282 +                       printk("dump filter mismatch\n");
2283 +                       return -ENOENT; /* filter name mismatch */
2284 +               }
2285 +               filter->selector = filter_table[i].selector;
2286 +       }
2287 +       config->dumper.filter = config->filter_table;
2288 +
2289 +       /* fixup format */
2290 +       if (strncmp(dumper->fmt->name, config->fmt.name, 32)) {
2291 +               printk("dump format mismatch\n");
2292 +               return -ENOENT; /* mismatch */
2293 +       }
2294 +       config->fmt.ops = dumper->fmt->ops;
2295 +       config->dumper.fmt = &config->fmt;
2296 +
2297 +       /* fixup target device */
2298 +       dev = (struct dump_dev *)(&config->dev[0]);
2299 +       if (dumper->dev == NULL) {
2300 +               pr_debug("Vanilla dumper - assume default\n");
2301 +               if (dump_dev == NULL)
2302 +                       return -ENODEV;
2303 +               dumper->dev = dump_dev;
2304 +       }
2305 +
2306 +       if (strncmp(dumper->dev->type_name, dev->type_name, 32)) { 
2307 +               printk("dump dev type mismatch %s instead of %s\n",
2308 +                               dev->type_name, dumper->dev->type_name);
2309 +               return -ENOENT; /* mismatch */
2310 +       }
2311 +       dev->ops = dumper->dev->ops; 
2312 +       config->dumper.dev = dev;
2313 +       
2314 +       /* fixup memory device containing saved dump pages */
2315 +       /* assume statically init'ed dump_memdev */
2316 +       config->memdev.ddev.ops = dump_memdev->ddev.ops; 
2317 +       /* switch to memdev from prev boot */
2318 +       saved_dump_memdev = dump_memdev; /* remember current */
2319 +       dump_memdev = &config->memdev;
2320 +
2321 +       /* Make this the current primary dumper */
2322 +       dump_config.dumper = &config->dumper;
2323 +
2324 +       return 0;
2325 +}
2326 +
2327 +/* Saves the dump configuration in a memory block for use across a soft-boot */
2328 +int dump_save_config(struct dump_config_block *config)
2329 +{
2330 +       printk("saving dump config settings\n");
2331 +
2332 +       /* dump config settings */
2333 +       memcpy(&config->config, &dump_config, sizeof(dump_config));
2334 +
2335 +       /* dumper state */
2336 +       memcpy(&config->dumper, dump_config.dumper, sizeof(struct dumper));
2337 +       memcpy(&config->scheme, dump_config.dumper->scheme, 
2338 +               sizeof(struct dump_scheme));
2339 +       memcpy(&config->fmt, dump_config.dumper->fmt, sizeof(struct dump_fmt));
2340 +       memcpy(&config->dev[0], dump_config.dumper->dev, 
2341 +               sizeof(struct dump_anydev));
2342 +       memcpy(&config->filter_table, dump_config.dumper->filter, 
2343 +               sizeof(struct dump_data_filter)*MAX_PASSES);
2344 +
2345 +       /* handle to saved mem pages */
2346 +       memcpy(&config->memdev, dump_memdev, sizeof(struct dump_memdev));
2347 +
2348 +       config->magic = DUMP_MAGIC_LIVE;
2349 +       
2350 +       return 0;
2351 +}
2352 +
2353 +int dump_init_stage2(struct dump_config_block *saved_config)
2354 +{
2355 +       int err = 0;
2356 +
2357 +       pr_debug("dump_init_stage2\n");
2358 +       /* Check if dump from previous boot exists */
2359 +       if (saved_config) {
2360 +               printk("loading dumper from previous boot \n");
2361 +               /* load and configure dumper from previous boot */
2362 +               if ((err = dump_load_config(saved_config)))
2363 +                       return err;
2364 +
2365 +               if (!dump_oncpu) {
2366 +                       if ((err = dump_configure(dump_config.dump_device))) {
2367 +                               printk("Stage 2 dump configure failed\n");
2368 +                               return err;
2369 +                       }
2370 +               }
2371 +
2372 +               dumper_reset();
2373 +               dump_dev = dump_config.dumper->dev;
2374 +               /* write out the dump */
2375 +               err = dump_generic_execute(NULL, NULL);
2376 +               
2377 +               dump_saved_config = NULL;
2378 +
2379 +               if (!dump_oncpu) {
2380 +                       dump_unconfigure(); 
2381 +               }
2382 +               
2383 +               return err;
2384 +
2385 +       } else {
2386 +               /* no dump to write out */
2387 +               printk("no dumper from previous boot \n");
2388 +               return 0;
2389 +       }
2390 +}
2391 +
2392 +extern void dump_mem_markpages(struct dump_memdev *);
2393 +
2394 +int dump_switchover_stage(void)
2395 +{
2396 +       int ret = 0;
2397 +
2398 +       /* trigger stage 2 rightaway - in real life would be after soft-boot */
2399 +       /* dump_saved_config would be a boot param */
2400 +       saved_dump_memdev = dump_memdev;
2401 +       saved_dumper = dump_config.dumper;
2402 +       ret = dump_init_stage2(dump_saved_config);
2403 +       dump_memdev = saved_dump_memdev;
2404 +       dump_config.dumper = saved_dumper;
2405 +       return ret;
2406 +}
2407 +
2408 +int dump_activate_softboot(void) 
2409 +{
2410 +        int err = 0;
2411 +#ifdef CONFIG_KEXEC
2412 +        int num_cpus_online = 0;
2413 +        struct kimage *image;
2414 +#endif
2415 +
2416 +        /* temporary - switchover to writeout previously saved dump */
2417 +#ifndef CONFIG_KEXEC
2418 +        err = dump_switchover_stage(); /* non-disruptive case */
2419 +        if (dump_oncpu)
2420 +                       dump_config.dumper = &dumper_stage1; /* set things back */
2421 +
2422 +        return err;
2423 +#else
2424 +
2425 +        dump_silence_level = DUMP_HALT_CPUS;
2426 +        /* wait till we become the only cpu */
2427 +        /* maybe by checking for online cpus ? */
2428 +
2429 +        while((num_cpus_online = num_online_cpus()) > 1);
2430 +
2431 +        /* now call into kexec */
2432 +
2433 +        image = xchg(&kexec_image, 0);
2434 +        if (image) {
2435 +                       mdelay(panic_timeout*1000);
2436 +                               machine_kexec(image);
2437 +                               }
2438 +
2439 +
2440 +        /* TBD/Fixme:
2441 +        *          * should we call reboot notifiers ? inappropriate for panic ?
2442 +        *                   * what about device_shutdown() ?
2443 +        *                            * is explicit bus master disabling needed or can we do that
2444 +        *                                     * through driverfs ?
2445 +        *                                              */
2446 +        return 0;
2447 +#endif
2448 +}
2449 +
2450 +/* --- DUMP SCHEME ROUTINES  --- */
2451 +
2452 +static inline int dump_buf_pending(struct dumper *dumper)
2453 +{
2454 +       return (dumper->curr_buf - dumper->dump_buf);
2455 +}
2456 +
2457 +/* Invoked during stage 1 of soft-reboot based dumping */
2458 +int dump_overlay_sequencer(void)
2459 +{
2460 +       struct dump_data_filter *filter = dump_config.dumper->filter;
2461 +       struct dump_data_filter *filter2 = dumper_stage2.filter;
2462 +       int pass = 0, err = 0, save = 0;
2463 +       int (*action)(unsigned long, unsigned long);
2464 +
2465 +       /* Make sure gzip compression is being used */
2466 +       if (dump_config.dumper->compress->compress_type != DUMP_COMPRESS_GZIP) {
2467 +               printk(" Please set GZIP compression \n");
2468 +               return -EINVAL;
2469 +       }
2470 +
2471 +       /* start filling in dump data right after the header */
2472 +       dump_config.dumper->curr_offset = 
2473 +               PAGE_ALIGN(dump_config.dumper->header_len);
2474 +
2475 +       /* Locate the last pass */
2476 +       for (;filter->selector; filter++, pass++);
2477 +       
2478 +       /* 
2479 +        * Start from the end backwards: overlay involves a reverse 
2480 +        * ordering of passes, since less critical pages are more
2481 +        * likely to be reusable as scratch space once we are through
2482 +        * with them. 
2483 +        */
2484 +       for (--pass, --filter; pass >= 0; pass--, filter--)
2485 +       {
2486 +               /* Assumes passes are exclusive (even across dumpers) */
2487 +               /* Requires care when coding the selection functions */
2488 +               if ((save = filter->level_mask & dump_config.level))
2489 +                       action = dump_save_data;
2490 +               else
2491 +                       action = dump_skip_data;
2492 +
2493 +               /* Remember the offset where this pass started */
2494 +               /* The second stage dumper would use this */
2495 +               if (dump_buf_pending(dump_config.dumper) & (PAGE_SIZE - 1)) {
2496 +                       pr_debug("Starting pass %d with pending data\n", pass);
2497 +                       pr_debug("filling dummy data to page-align it\n");
2498 +                       dump_config.dumper->curr_buf = (void *)PAGE_ALIGN(
2499 +                               (unsigned long)dump_config.dumper->curr_buf);
2500 +               }
2501 +               
2502 +               filter2[pass].start[0] = dump_config.dumper->curr_offset
2503 +                       + dump_buf_pending(dump_config.dumper);
2504 +
2505 +               err = dump_iterator(pass, action, filter);
2506 +
2507 +               filter2[pass].end[0] = dump_config.dumper->curr_offset
2508 +                       + dump_buf_pending(dump_config.dumper);
2509 +               filter2[pass].num_mbanks = 1;
2510 +
2511 +               if (err < 0) {
2512 +                       printk("dump_overlay_seq: failure %d in pass %d\n", 
2513 +                               err, pass);
2514 +                       break;
2515 +               }       
2516 +               printk("\n %d overlay pages %s of %d each in pass %d\n", 
2517 +               err, save ? "saved" : "skipped", DUMP_PAGE_SIZE, pass);
2518 +       }
2519 +
2520 +       return err;
2521 +}
2522 +
2523 +/* from dump_memdev.c */
2524 +extern struct page *dump_mem_lookup(struct dump_memdev *dev, unsigned long loc);
2525 +extern struct page *dump_mem_next_page(struct dump_memdev *dev);
2526 +
2527 +static inline struct page *dump_get_saved_page(loff_t loc)
2528 +{
2529 +       return (dump_mem_lookup(dump_memdev, loc >> PAGE_SHIFT));
2530 +}
2531 +
2532 +static inline struct page *dump_next_saved_page(void)
2533 +{
2534 +       return (dump_mem_next_page(dump_memdev));
2535 +}
2536 +
2537 +/* 
2538 + * Iterates over list of saved dump pages. Invoked during second stage of 
2539 + * soft boot dumping
2540 + *
2541 + * Observation: If additional selection is desired at this stage then
2542 + * a different iterator could be written which would advance 
2543 + * to the next page header everytime instead of blindly picking up
2544 + * the data. In such a case loc would be interpreted differently. 
2545 + * At this moment however a blind pass seems sufficient, cleaner and
2546 + * faster.
2547 + */
2548 +int dump_saved_data_iterator(int pass, int (*action)(unsigned long, 
2549 +       unsigned long), struct dump_data_filter *filter)
2550 +{
2551 +       loff_t loc, end;
2552 +       struct page *page;
2553 +       unsigned long count = 0;
2554 +       int i, err = 0;
2555 +       unsigned long sz;
2556 +
2557 +       for (i = 0; i < filter->num_mbanks; i++) {
2558 +               loc  = filter->start[i];
2559 +               end = filter->end[i];
2560 +               printk("pass %d, start off 0x%llx end offset 0x%llx\n", pass,
2561 +                       loc, end);
2562 +
2563 +               /* loc will get treated as logical offset into stage 1 */
2564 +               page = dump_get_saved_page(loc);
2565 +                       
2566 +               for (; loc < end; loc += PAGE_SIZE) {
2567 +                       dump_config.dumper->curr_loc = loc;
2568 +                       if (!page) {
2569 +                               printk("no more saved data for pass %d\n", 
2570 +                                       pass);
2571 +                               break;
2572 +                       }
2573 +                       sz = (loc + PAGE_SIZE > end) ? end - loc : PAGE_SIZE;
2574 +
2575 +                       if (page && filter->selector(pass, (unsigned long)page, 
2576 +                               PAGE_SIZE))  {
2577 +                               pr_debug("mem offset 0x%llx\n", loc);
2578 +                               if ((err = action((unsigned long)page, sz))) 
2579 +                                       break;
2580 +                               else
2581 +                                       count++;
2582 +                               /* clear the contents of page */
2583 +                               /* fixme: consider using KM_DUMP instead */
2584 +                               clear_highpage(page);
2585 +                       
2586 +                       }
2587 +                       page = dump_next_saved_page();
2588 +               }
2589 +       }
2590 +
2591 +       return err ? err : count;
2592 +}
2593 +
2594 +static inline int dump_overlay_pages_done(struct page *page, int nr)
2595 +{
2596 +       int ret=0;
2597 +
2598 +       for (; nr ; page++, nr--) {
2599 +               if (dump_check_and_free_page(dump_memdev, page))
2600 +                       ret++;
2601 +       }
2602 +       return ret;
2603 +}
2604 +
2605 +int dump_overlay_save_data(unsigned long loc, unsigned long len)
2606 +{
2607 +       int err = 0;
2608 +       struct page *page = (struct page *)loc;
2609 +       static unsigned long cnt = 0;
2610 +
2611 +       if ((err = dump_generic_save_data(loc, len)))
2612 +               return err;
2613 +
2614 +       if (dump_overlay_pages_done(page, len >> PAGE_SHIFT)) {
2615 +               cnt++;
2616 +               if (!(cnt & 0x7f))
2617 +                       pr_debug("released page 0x%lx\n", page_to_pfn(page));
2618 +       }
2619 +       
2620 +       return err;
2621 +}
2622 +
2623 +
2624 +int dump_overlay_skip_data(unsigned long loc, unsigned long len)
2625 +{
2626 +       struct page *page = (struct page *)loc;
2627 +
2628 +       dump_overlay_pages_done(page, len >> PAGE_SHIFT);
2629 +       return 0;
2630 +}
2631 +
2632 +int dump_overlay_resume(void)
2633 +{
2634 +       int err = 0;
2635 +
2636 +       /* 
2637 +        * switch to stage 2 dumper, save dump_config_block
2638 +        * and then trigger a soft-boot
2639 +        */
2640 +       dumper_stage2.header_len = dump_config.dumper->header_len;
2641 +       dump_config.dumper = &dumper_stage2;
2642 +       if ((err = dump_save_config(dump_saved_config)))
2643 +               return err;
2644 +
2645 +       dump_dev = dump_config.dumper->dev;
2646 +
2647 +#ifdef CONFIG_KEXEC
2648 +        /* If we are doing a disruptive dump, activate softboot now */
2649 +        if((panic_timeout > 0) && (!(dump_config.flags & DUMP_FLAGS_NONDISRUPT)))
2650 +        err = dump_activate_softboot();
2651 +#endif
2652 +               
2653 +       return err;
2654 +       err = dump_switchover_stage();  /* plugs into soft boot mechanism */
2655 +       dump_config.dumper = &dumper_stage1; /* set things back */
2656 +       return err;
2657 +}
2658 +
2659 +int dump_overlay_configure(unsigned long devid)
2660 +{
2661 +       struct dump_dev *dev;
2662 +       struct dump_config_block *saved_config = dump_saved_config;
2663 +       int err = 0;
2664 +
2665 +       /* If there is a previously saved dump, write it out first */
2666 +       if (saved_config) {
2667 +               printk("Processing old dump pending writeout\n");
2668 +               err = dump_switchover_stage();
2669 +               if (err) {
2670 +                       printk("failed to writeout saved dump\n");
2671 +                       return err;
2672 +               }
2673 +               dump_free_mem(saved_config); /* testing only: not after boot */
2674 +       }
2675 +
2676 +       dev = dumper_stage2.dev = dump_config.dumper->dev;
2677 +       /* From here on the intermediate dump target is memory-only */
2678 +       dump_dev = dump_config.dumper->dev = &dump_memdev->ddev;
2679 +       if ((err = dump_generic_configure(0))) {
2680 +               printk("dump generic configure failed: err %d\n", err);
2681 +               return err;
2682 +       }
2683 +       /* temporary */
2684 +       dumper_stage2.dump_buf = dump_config.dumper->dump_buf;
2685 +
2686 +       /* Sanity check on the actual target dump device */
2687 +       if (!dev || (err = dev->ops->open(dev, devid))) {
2688 +               return err;
2689 +       }
2690 +       /* TBD: should we release the target if this is soft-boot only ? */
2691 +
2692 +       /* alloc a dump config block area to save across reboot */
2693 +       if (!(dump_saved_config = dump_alloc_mem(sizeof(struct 
2694 +               dump_config_block)))) {
2695 +               printk("dump config block alloc failed\n");
2696 +               /* undo configure */
2697 +               dump_generic_unconfigure();
2698 +               return -ENOMEM;
2699 +       }
2700 +       dump_config.dump_addr = (unsigned long)dump_saved_config;
2701 +       printk("Dump config block of size %d set up at 0x%lx\n", 
2702 +               sizeof(*dump_saved_config), (unsigned long)dump_saved_config);
2703 +       return 0;
2704 +}
2705 +
2706 +int dump_overlay_unconfigure(void)
2707 +{
2708 +       struct dump_dev *dev = dumper_stage2.dev;
2709 +       int err = 0;
2710 +
2711 +       pr_debug("dump_overlay_unconfigure\n");
2712 +       /* Close the secondary device */
2713 +       dev->ops->release(dev); 
2714 +       pr_debug("released secondary device\n");
2715 +
2716 +       err = dump_generic_unconfigure();
2717 +       pr_debug("Unconfigured generic portions\n");
2718 +       dump_free_mem(dump_saved_config);
2719 +       dump_saved_config = NULL;
2720 +       pr_debug("Freed saved config block\n");
2721 +       dump_dev = dump_config.dumper->dev = dumper_stage2.dev;
2722 +
2723 +       printk("Unconfigured overlay dumper\n");
2724 +       return err;
2725 +}
2726 +
2727 +int dump_staged_unconfigure(void)
2728 +{
2729 +       int err = 0;
2730 +       struct dump_config_block *saved_config = dump_saved_config;
2731 +       struct dump_dev *dev;
2732 +
2733 +       pr_debug("dump_staged_unconfigure\n");
2734 +       err = dump_generic_unconfigure();
2735 +
2736 +       /* now check if there is a saved dump waiting to be written out */
2737 +       if (saved_config) {
2738 +               printk("Processing saved dump pending writeout\n");
2739 +               if ((err = dump_switchover_stage())) {
2740 +                       printk("Error in commiting saved dump at 0x%lx\n", 
2741 +                               (unsigned long)saved_config);
2742 +                       printk("Old dump may hog memory\n");
2743 +               } else {
2744 +                       dump_free_mem(saved_config);
2745 +                       pr_debug("Freed saved config block\n");
2746 +               }
2747 +               dump_saved_config = NULL;
2748 +       } else {
2749 +               dev = &dump_memdev->ddev;
2750 +               dev->ops->release(dev);
2751 +       }
2752 +       printk("Unconfigured second stage dumper\n");
2753 +
2754 +       return 0;
2755 +}
2756 +
2757 +/* ----- PASSTHRU FILTER ROUTINE --------- */
2758 +
2759 +/* transparent - passes everything through */
2760 +int dump_passthru_filter(int pass, unsigned long loc, unsigned long sz)
2761 +{
2762 +       return 1;
2763 +}
2764 +
2765 +/* ----- PASSTRU FORMAT ROUTINES ---- */
2766 +
2767 +
2768 +int dump_passthru_configure_header(const char *panic_str, const struct pt_regs *regs)
2769 +{
2770 +       dump_config.dumper->header_dirty++;
2771 +       return 0;
2772 +}
2773 +
2774 +/* Copies bytes of data from page(s) to the specified buffer */
2775 +int dump_copy_pages(void *buf, struct page *page, unsigned long sz)
2776 +{
2777 +       unsigned long len = 0, bytes;
2778 +       void *addr;
2779 +
2780 +       while (len < sz) {
2781 +               addr = kmap_atomic(page, KM_DUMP);
2782 +               bytes = (sz > len + PAGE_SIZE) ? PAGE_SIZE : sz - len;  
2783 +               memcpy(buf, addr, bytes); 
2784 +               kunmap_atomic(addr, KM_DUMP);
2785 +               buf += bytes;
2786 +               len += bytes;
2787 +               page++;
2788 +       }
2789 +       /* memset(dump_config.dumper->curr_buf, 0x57, len); temporary */
2790 +
2791 +       return sz - len;
2792 +}
2793 +
2794 +int dump_passthru_update_header(void)
2795 +{
2796 +       long len = dump_config.dumper->header_len;
2797 +       struct page *page;
2798 +       void *buf = dump_config.dumper->dump_buf;
2799 +       int err = 0;
2800 +
2801 +       if (!dump_config.dumper->header_dirty)
2802 +               return 0;
2803 +
2804 +       pr_debug("Copying header of size %ld bytes from memory\n", len);
2805 +       if (len > DUMP_BUFFER_SIZE) 
2806 +               return -E2BIG;
2807 +
2808 +       page = dump_mem_lookup(dump_memdev, 0);
2809 +       for (; (len > 0) && page; buf += PAGE_SIZE, len -= PAGE_SIZE) {
2810 +               if ((err = dump_copy_pages(buf, page, PAGE_SIZE)))
2811 +                       return err;
2812 +               page = dump_mem_next_page(dump_memdev);
2813 +       }
2814 +       if (len > 0) {
2815 +               printk("Incomplete header saved in mem\n");
2816 +               return -ENOENT;
2817 +       }
2818 +
2819 +       if ((err = dump_dev_seek(0))) {
2820 +               printk("Unable to seek to dump header offset\n");
2821 +               return err;
2822 +       }
2823 +       err = dump_ll_write(dump_config.dumper->dump_buf, 
2824 +               buf - dump_config.dumper->dump_buf);
2825 +       if (err < dump_config.dumper->header_len)
2826 +               return (err < 0) ? err : -ENOSPC;
2827 +
2828 +       dump_config.dumper->header_dirty = 0;
2829 +       return 0;
2830 +}
2831 +
2832 +static loff_t next_dph_offset = 0;
2833 +
2834 +static int dph_valid(struct __dump_page *dph)
2835 +{
2836 +       if ((dph->dp_address & (PAGE_SIZE - 1)) || (dph->dp_flags 
2837 +             > DUMP_DH_COMPRESSED) || (!dph->dp_flags) ||
2838 +               (dph->dp_size > PAGE_SIZE)) {
2839 +       printk("dp->address = 0x%llx, dp->size = 0x%x, dp->flag = 0x%x\n",
2840 +               dph->dp_address, dph->dp_size, dph->dp_flags);
2841 +               return 0;
2842 +       }
2843 +       return 1;
2844 +}
2845 +
2846 +int dump_verify_lcrash_data(void *buf, unsigned long sz)
2847 +{
2848 +       struct __dump_page *dph;
2849 +
2850 +       /* sanity check for page headers */
2851 +       while (next_dph_offset + sizeof(*dph) < sz) {
2852 +               dph = (struct __dump_page *)(buf + next_dph_offset);
2853 +               if (!dph_valid(dph)) {
2854 +                       printk("Invalid page hdr at offset 0x%llx\n",
2855 +                               next_dph_offset);
2856 +                       return -EINVAL;
2857 +               }
2858 +               next_dph_offset += dph->dp_size + sizeof(*dph);
2859 +       }
2860 +
2861 +       next_dph_offset -= sz;  
2862 +       return 0;
2863 +}
2864 +
2865 +/* 
2866 + * TBD/Later: Consider avoiding the copy by using a scatter/gather 
2867 + * vector representation for the dump buffer
2868 + */
2869 +int dump_passthru_add_data(unsigned long loc, unsigned long sz)
2870 +{
2871 +       struct page *page = (struct page *)loc;
2872 +       void *buf = dump_config.dumper->curr_buf;
2873 +       int err = 0;
2874 +
2875 +       if ((err = dump_copy_pages(buf, page, sz))) {
2876 +               printk("dump_copy_pages failed");
2877 +               return err;
2878 +       }
2879 +
2880 +       if ((err = dump_verify_lcrash_data(buf, sz))) {
2881 +               printk("dump_verify_lcrash_data failed\n");
2882 +               printk("Invalid data for pfn 0x%lx\n", page_to_pfn(page));
2883 +               printk("Page flags 0x%lx\n", page->flags);
2884 +               printk("Page count 0x%x\n", page_count(page));
2885 +               return err;
2886 +       }
2887 +
2888 +       dump_config.dumper->curr_buf = buf + sz;
2889 +
2890 +       return 0;
2891 +}
2892 +
2893 +
2894 +/* Stage 1 dumper: Saves compressed dump in memory and soft-boots system */
2895 +
2896 +/* Scheme to overlay saved data in memory for writeout after a soft-boot */
2897 +struct dump_scheme_ops dump_scheme_overlay_ops = {
2898 +       .configure      = dump_overlay_configure,
2899 +       .unconfigure    = dump_overlay_unconfigure,
2900 +       .sequencer      = dump_overlay_sequencer,
2901 +       .iterator       = dump_page_iterator,
2902 +       .save_data      = dump_overlay_save_data,
2903 +       .skip_data      = dump_overlay_skip_data,
2904 +       .write_buffer   = dump_generic_write_buffer
2905 +};
2906 +
2907 +struct dump_scheme dump_scheme_overlay = {
2908 +       .name           = "overlay",
2909 +       .ops            = &dump_scheme_overlay_ops
2910 +};
2911 +
2912 +
2913 +/* Stage 1 must use a good compression scheme - default to gzip */
2914 +extern struct __dump_compress dump_gzip_compression;
2915 +
2916 +struct dumper dumper_stage1 = {
2917 +       .name           = "stage1",
2918 +       .scheme         = &dump_scheme_overlay,
2919 +       .fmt            = &dump_fmt_lcrash,
2920 +       .compress       = &dump_none_compression, /* needs to be gzip */
2921 +       .filter         = dump_filter_table,
2922 +       .dev            = NULL,
2923 +};             
2924 +
2925 +/* Stage 2 dumper: Activated after softboot to write out saved dump to device */
2926 +
2927 +/* Formatter that transfers data as is (transparent) w/o further conversion */
2928 +struct dump_fmt_ops dump_fmt_passthru_ops = {
2929 +       .configure_header       = dump_passthru_configure_header,
2930 +       .update_header          = dump_passthru_update_header,
2931 +       .save_context           = NULL, /* unused */
2932 +       .add_data               = dump_passthru_add_data,
2933 +       .update_end_marker      = dump_lcrash_update_end_marker
2934 +};
2935 +
2936 +struct dump_fmt dump_fmt_passthru = {
2937 +       .name   = "passthru",
2938 +       .ops    = &dump_fmt_passthru_ops
2939 +};
2940 +
2941 +/* Filter that simply passes along any data within the range (transparent)*/
2942 +/* Note: The start and end ranges in the table are filled in at run-time */
2943 +
2944 +extern int dump_filter_none(int pass, unsigned long loc, unsigned long sz);
2945 +
2946 +struct dump_data_filter dump_passthru_filtertable[MAX_PASSES] = {
2947 +{.name = "passkern", .selector = dump_passthru_filter, 
2948 +       .level_mask = DUMP_MASK_KERN },
2949 +{.name = "passuser", .selector = dump_passthru_filter, 
2950 +       .level_mask = DUMP_MASK_USED },
2951 +{.name = "passunused", .selector = dump_passthru_filter, 
2952 +       .level_mask = DUMP_MASK_UNUSED },
2953 +{.name = "none", .selector = dump_filter_none, 
2954 +       .level_mask = DUMP_MASK_REST }
2955 +};
2956 +
2957 +
2958 +/* Scheme to handle data staged / preserved across a soft-boot */
2959 +struct dump_scheme_ops dump_scheme_staged_ops = {
2960 +       .configure      = dump_generic_configure,
2961 +       .unconfigure    = dump_staged_unconfigure,
2962 +       .sequencer      = dump_generic_sequencer,
2963 +       .iterator       = dump_saved_data_iterator,
2964 +       .save_data      = dump_generic_save_data,
2965 +       .skip_data      = dump_generic_skip_data,
2966 +       .write_buffer   = dump_generic_write_buffer
2967 +};
2968 +
2969 +struct dump_scheme dump_scheme_staged = {
2970 +       .name           = "staged",
2971 +       .ops            = &dump_scheme_staged_ops
2972 +};
2973 +
2974 +/* The stage 2 dumper comprising all these */
2975 +struct dumper dumper_stage2 = {
2976 +       .name           = "stage2",
2977 +       .scheme         = &dump_scheme_staged,
2978 +       .fmt            = &dump_fmt_passthru,
2979 +       .compress       = &dump_none_compression,
2980 +       .filter         = dump_passthru_filtertable,
2981 +       .dev            = NULL,
2982 +};             
2983 +
2984 Index: linux-2.6.10-base/drivers/dump/dump_fmt.c
2985 ===================================================================
2986 --- linux-2.6.10-base.orig/drivers/dump/dump_fmt.c      2003-09-02 06:26:13.000000000 +0800
2987 +++ linux-2.6.10-base/drivers/dump/dump_fmt.c   2005-05-17 18:52:39.933055664 +0800
2988 @@ -0,0 +1,407 @@
2989 +/*
2990 + * Implements the routines which handle the format specific
2991 + * aspects of dump for the default dump format.
2992 + *
2993 + * Used in single stage dumping and stage 1 of soft-boot based dumping 
2994 + * Saves data in LKCD (lcrash) format 
2995 + *
2996 + * Previously a part of dump_base.c
2997 + *
2998 + * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
2999 + *     Split off and reshuffled LKCD dump format code around generic
3000 + *     dump method interfaces.
3001 + *
3002 + * Derived from original code created by 
3003 + *     Matt Robinson <yakker@sourceforge.net>)
3004 + *
3005 + * Contributions from SGI, IBM, HP, MCL, and others.
3006 + *
3007 + * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
3008 + * Copyright (C) 2000 - 2002 TurboLinux, Inc.  All rights reserved.
3009 + * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
3010 + * Copyright (C) 2002 International Business Machines Corp. 
3011 + *
3012 + * This code is released under version 2 of the GNU GPL.
3013 + */
3014 +
3015 +#include <linux/types.h>
3016 +#include <linux/kernel.h>
3017 +#include <linux/time.h>
3018 +#include <linux/sched.h>
3019 +#include <linux/ptrace.h>
3020 +#include <linux/utsname.h>
3021 +#include <linux/dump.h>
3022 +#include <asm/dump.h>
3023 +#include "dump_methods.h"
3024 +
3025 +/*
3026 + * SYSTEM DUMP LAYOUT
3027 + * 
3028 + * System dumps are currently the combination of a dump header and a set
3029 + * of data pages which contain the system memory.  The layout of the dump
3030 + * (for full dumps) is as follows:
3031 + *
3032 + *             +-----------------------------+
3033 + *             |     generic dump header     |
3034 + *             +-----------------------------+
3035 + *             |   architecture dump header  |
3036 + *             +-----------------------------+
3037 + *             |         page header         |
3038 + *             +-----------------------------+
3039 + *             |          page data          |
3040 + *             +-----------------------------+
3041 + *             |         page header         |
3042 + *             +-----------------------------+
3043 + *             |          page data          |
3044 + *             +-----------------------------+
3045 + *             |              |              |
3046 + *             |              |              |
3047 + *             |              |              |
3048 + *             |              |              |
3049 + *             |              V              |
3050 + *             +-----------------------------+
3051 + *             |        PAGE_END header      |
3052 + *             +-----------------------------+
3053 + *
3054 + * There are two dump headers, the first which is architecture
3055 + * independent, and the other which is architecture dependent.  This
3056 + * allows different architectures to dump different data structures
3057 + * which are specific to their chipset, CPU, etc.
3058 + *
3059 + * After the dump headers come a succession of dump page headers along
3060 + * with dump pages.  The page header contains information about the page
3061 + * size, any flags associated with the page (whether it's compressed or
3062 + * not), and the address of the page.  After the page header is the page
3063 + * data, which is either compressed (or not).  Each page of data is
3064 + * dumped in succession, until the final dump header (PAGE_END) is
3065 + * placed at the end of the dump, assuming the dump device isn't out
3066 + * of space.
3067 + *
3068 + * This mechanism allows for multiple compression types, different
3069 + * types of data structures, different page ordering, etc., etc., etc.
3070 + * It's a very straightforward mechanism for dumping system memory.
3071 + */
3072 +
3073 +struct __dump_header dump_header;  /* the primary dump header              */
3074 +struct __dump_header_asm dump_header_asm; /* the arch-specific dump header */
3075 +
3076 +/* Replace a runtime sanity check on the DUMP_BUFFER_SIZE with a 
3077 + * compile-time check.  The compile_time_assertions routine will not
3078 + * compile if the assertion is false. 
3079 + *
3080 + * If you fail this assert you are most likely on a large machine and 
3081 + * should use a special 6.0.0 version of LKCD or a version > 7.0.0. See
3082 + * the LKCD website for more information.
3083 + */
3084 +
3085 +#define COMPILE_TIME_ASSERT(const_expr) \
3086 +       switch(0){case 0: case (const_expr):;}
3087 +
3088 +static inline void compile_time_assertions(void)
3089 +{
3090 +       COMPILE_TIME_ASSERT((sizeof(struct __dump_header) +
3091 +               sizeof(struct __dump_header_asm)) <= DUMP_BUFFER_SIZE);
3092 +}
3093 +
3094 +/*
3095 + *  Set up common header fields (mainly the arch indep section) 
3096 + *  Per-cpu state is handled by lcrash_save_context
3097 + *  Returns the size of the header in bytes.
3098 + */
3099 +static int lcrash_init_dump_header(const char *panic_str)
3100 +{
3101 +       struct timeval dh_time;
3102 +       u64 temp_memsz = dump_header.dh_memory_size;
3103 +
3104 +       /* initialize the dump headers to zero */
3105 +       /* save dha_stack pointer because it may contains pointer for stack! */
3106 +       memset(&dump_header, 0, sizeof(dump_header));
3107 +       memset(&dump_header_asm, 0,
3108 +               offsetof(struct __dump_header_asm, dha_stack));
3109 +       memset(&dump_header_asm.dha_stack+1, 0,
3110 +               sizeof(dump_header_asm) -
3111 +               offsetof(struct __dump_header_asm, dha_stack) -
3112 +               sizeof(dump_header_asm.dha_stack));
3113 +       dump_header.dh_memory_size = temp_memsz;
3114 +
3115 +       /* configure dump header values */
3116 +       dump_header.dh_magic_number = DUMP_MAGIC_NUMBER;
3117 +       dump_header.dh_version = DUMP_VERSION_NUMBER;
3118 +       dump_header.dh_memory_start = PAGE_OFFSET;
3119 +       dump_header.dh_memory_end = DUMP_MAGIC_NUMBER;
3120 +       dump_header.dh_header_size = sizeof(struct __dump_header);
3121 +       dump_header.dh_page_size = PAGE_SIZE;
3122 +       dump_header.dh_dump_level = dump_config.level;
3123 +       dump_header.dh_current_task = (unsigned long) current;
3124 +       dump_header.dh_dump_compress = dump_config.dumper->compress->
3125 +               compress_type;
3126 +       dump_header.dh_dump_flags = dump_config.flags;
3127 +       dump_header.dh_dump_device = dump_config.dumper->dev->device_id; 
3128 +
3129 +#if DUMP_DEBUG >= 6
3130 +       dump_header.dh_num_bytes = 0;
3131 +#endif
3132 +       dump_header.dh_num_dump_pages = 0;
3133 +       do_gettimeofday(&dh_time);
3134 +       dump_header.dh_time.tv_sec = dh_time.tv_sec;
3135 +       dump_header.dh_time.tv_usec = dh_time.tv_usec;
3136 +
3137 +       memcpy((void *)&(dump_header.dh_utsname_sysname), 
3138 +               (const void *)&(system_utsname.sysname), __NEW_UTS_LEN + 1);
3139 +       memcpy((void *)&(dump_header.dh_utsname_nodename), 
3140 +               (const void *)&(system_utsname.nodename), __NEW_UTS_LEN + 1);
3141 +       memcpy((void *)&(dump_header.dh_utsname_release), 
3142 +               (const void *)&(system_utsname.release), __NEW_UTS_LEN + 1);
3143 +       memcpy((void *)&(dump_header.dh_utsname_version), 
3144 +               (const void *)&(system_utsname.version), __NEW_UTS_LEN + 1);
3145 +       memcpy((void *)&(dump_header.dh_utsname_machine), 
3146 +               (const void *)&(system_utsname.machine), __NEW_UTS_LEN + 1);
3147 +       memcpy((void *)&(dump_header.dh_utsname_domainname), 
3148 +               (const void *)&(system_utsname.domainname), __NEW_UTS_LEN + 1);
3149 +
3150 +       if (panic_str) {
3151 +               memcpy((void *)&(dump_header.dh_panic_string),
3152 +                       (const void *)panic_str, DUMP_PANIC_LEN);
3153 +       }
3154 +
3155 +        dump_header_asm.dha_magic_number = DUMP_ASM_MAGIC_NUMBER;
3156 +        dump_header_asm.dha_version = DUMP_ASM_VERSION_NUMBER;
3157 +        dump_header_asm.dha_header_size = sizeof(dump_header_asm);
3158 +#ifdef CONFIG_ARM
3159 +       dump_header_asm.dha_physaddr_start = PHYS_OFFSET;
3160 +#endif
3161 +
3162 +       dump_header_asm.dha_smp_num_cpus = num_online_cpus();
3163 +       pr_debug("smp_num_cpus in header %d\n", 
3164 +               dump_header_asm.dha_smp_num_cpus);
3165 +
3166 +       dump_header_asm.dha_dumping_cpu = smp_processor_id();
3167 +       
3168 +       return sizeof(dump_header) + sizeof(dump_header_asm);
3169 +}
3170 +
3171 +
3172 +int dump_lcrash_configure_header(const char *panic_str, 
3173 +       const struct pt_regs *regs)
3174 +{
3175 +       int retval = 0;
3176 +
3177 +       dump_config.dumper->header_len = lcrash_init_dump_header(panic_str);
3178 +
3179 +       /* capture register states for all processors */
3180 +       dump_save_this_cpu(regs);
3181 +       __dump_save_other_cpus(); /* side effect:silence cpus */
3182 +
3183 +       /* configure architecture-specific dump header values */
3184 +       if ((retval = __dump_configure_header(regs))) 
3185 +               return retval;
3186 +
3187 +       dump_config.dumper->header_dirty++;
3188 +       return 0;
3189 +}
3190 +/* save register and task context */
3191 +void dump_lcrash_save_context(int cpu, const struct pt_regs *regs, 
3192 +       struct task_struct *tsk)
3193 +{
3194 +       /* This level of abstraction might be redundantly redundant */
3195 +       __dump_save_context(cpu, regs, tsk);
3196 +}
3197 +
3198 +/* write out the header */
3199 +int dump_write_header(void)
3200 +{
3201 +       int retval = 0, size;
3202 +       void *buf = dump_config.dumper->dump_buf;
3203 +
3204 +       /* accounts for DUMP_HEADER_OFFSET if applicable */
3205 +       if ((retval = dump_dev_seek(0))) {
3206 +               printk("Unable to seek to dump header offset: %d\n", 
3207 +                       retval);
3208 +               return retval;
3209 +       }
3210 +
3211 +       memcpy(buf, (void *)&dump_header, sizeof(dump_header));
3212 +       size = sizeof(dump_header);
3213 +       memcpy(buf + size, (void *)&dump_header_asm, sizeof(dump_header_asm));
3214 +       size += sizeof(dump_header_asm);
3215 +       size = PAGE_ALIGN(size);
3216 +       retval = dump_ll_write(buf , size);
3217 +
3218 +       if (retval < size) 
3219 +               return (retval >= 0) ? ENOSPC : retval;
3220 +       return 0;
3221 +}
3222 +
3223 +int dump_generic_update_header(void)
3224 +{
3225 +       int err = 0;
3226 +
3227 +       if (dump_config.dumper->header_dirty) {
3228 +               if ((err = dump_write_header())) {
3229 +                       printk("dump write header failed !err %d\n", err);
3230 +               } else {
3231 +                       dump_config.dumper->header_dirty = 0;
3232 +               }
3233 +       }
3234 +
3235 +       return err;
3236 +}
3237 +
3238 +static inline int is_curr_stack_page(struct page *page, unsigned long size)
3239 +{
3240 +       unsigned long thread_addr = (unsigned long)current_thread_info();
3241 +       unsigned long addr = (unsigned long)page_address(page);
3242 +
3243 +       return !PageHighMem(page) && (addr < thread_addr + THREAD_SIZE)
3244 +               && (addr + size > thread_addr);
3245 +}
3246 +
3247 +static inline int is_dump_page(struct page *page, unsigned long size)
3248 +{
3249 +       unsigned long addr = (unsigned long)page_address(page);
3250 +       unsigned long dump_buf = (unsigned long)dump_config.dumper->dump_buf;
3251 +
3252 +       return !PageHighMem(page) && (addr < dump_buf + DUMP_BUFFER_SIZE)
3253 +               && (addr + size > dump_buf);
3254 +}
3255 +
3256 +int dump_allow_compress(struct page *page, unsigned long size)
3257 +{
3258 +       /*
3259 +        * Don't compress the page if any part of it overlaps
3260 +        * with the current stack or dump buffer (since the contents
3261 +        * in these could be changing while compression is going on)
3262 +        */
3263 +       return !is_curr_stack_page(page, size) && !is_dump_page(page, size);
3264 +}
3265 +
3266 +void lcrash_init_pageheader(struct __dump_page *dp, struct page *page, 
3267 +       unsigned long sz)
3268 +{
3269 +       memset(dp, sizeof(struct __dump_page), 0);
3270 +       dp->dp_flags = 0; 
3271 +       dp->dp_size = 0;
3272 +       if (sz > 0)
3273 +               dp->dp_address = (loff_t)page_to_pfn(page) << PAGE_SHIFT;
3274 +
3275 +#if DUMP_DEBUG > 6
3276 +       dp->dp_page_index = dump_header.dh_num_dump_pages;
3277 +       dp->dp_byte_offset = dump_header.dh_num_bytes + DUMP_BUFFER_SIZE
3278 +               + DUMP_HEADER_OFFSET; /* ?? */
3279 +#endif /* DUMP_DEBUG */
3280 +}
3281 +
3282 +int dump_lcrash_add_data(unsigned long loc, unsigned long len)
3283 +{
3284 +       struct page *page = (struct page *)loc;
3285 +       void *addr, *buf = dump_config.dumper->curr_buf;
3286 +       struct __dump_page *dp = (struct __dump_page *)buf; 
3287 +       int bytes, size;
3288 +
3289 +       if (buf > dump_config.dumper->dump_buf + DUMP_BUFFER_SIZE)
3290 +               return -ENOMEM;
3291 +
3292 +       lcrash_init_pageheader(dp, page, len);
3293 +       buf += sizeof(struct __dump_page);
3294 +
3295 +       while (len) {
3296 +               addr = kmap_atomic(page, KM_DUMP);
3297 +               size = bytes = (len > PAGE_SIZE) ? PAGE_SIZE : len;     
3298 +               /* check for compression */
3299 +               if (dump_allow_compress(page, bytes)) {
3300 +                       size = dump_compress_data((char *)addr, bytes, 
3301 +                               (char *)buf, loc);
3302 +               }
3303 +               /* set the compressed flag if the page did compress */
3304 +               if (size && (size < bytes)) {
3305 +                       dp->dp_flags |= DUMP_DH_COMPRESSED;
3306 +               } else {
3307 +                       /* compression failed -- default to raw mode */
3308 +                       dp->dp_flags |= DUMP_DH_RAW;
3309 +                       memcpy(buf, addr, bytes);
3310 +                       size = bytes;
3311 +               }
3312 +               /* memset(buf, 'A', size); temporary: testing only !! */
3313 +               kunmap_atomic(addr, KM_DUMP);
3314 +               dp->dp_size += size;
3315 +               buf += size;
3316 +               len -= bytes;
3317 +               page++;
3318 +       }
3319 +
3320 +       /* now update the header */
3321 +#if DUMP_DEBUG > 6
3322 +       dump_header.dh_num_bytes += dp->dp_size + sizeof(*dp);
3323 +#endif
3324 +       dump_header.dh_num_dump_pages++;
3325 +       dump_config.dumper->header_dirty++;
3326 +
3327 +       dump_config.dumper->curr_buf = buf;     
3328 +
3329 +       return len;
3330 +}
3331 +
3332 +int dump_lcrash_update_end_marker(void)
3333 +{
3334 +       struct __dump_page *dp = 
3335 +               (struct __dump_page *)dump_config.dumper->curr_buf;
3336 +       unsigned long left;
3337 +       int ret = 0;
3338 +               
3339 +       lcrash_init_pageheader(dp, NULL, 0);
3340 +       dp->dp_flags |= DUMP_DH_END; /* tbd: truncation test ? */
3341 +       
3342 +       /* now update the header */
3343 +#if DUMP_DEBUG > 6
3344 +       dump_header.dh_num_bytes += sizeof(*dp);
3345 +#endif
3346 +       dump_config.dumper->curr_buf += sizeof(*dp);
3347 +       left = dump_config.dumper->curr_buf - dump_config.dumper->dump_buf;
3348 +
3349 +       printk("\n");
3350 +
3351 +       while (left) {
3352 +               if ((ret = dump_dev_seek(dump_config.dumper->curr_offset))) {
3353 +                       printk("Seek failed at offset 0x%llx\n", 
3354 +                       dump_config.dumper->curr_offset);
3355 +                       return ret;
3356 +               }
3357 +
3358 +               if (DUMP_BUFFER_SIZE > left) 
3359 +                       memset(dump_config.dumper->curr_buf, 'm', 
3360 +                               DUMP_BUFFER_SIZE - left);
3361 +
3362 +               if ((ret = dump_ll_write(dump_config.dumper->dump_buf, 
3363 +                       DUMP_BUFFER_SIZE)) < DUMP_BUFFER_SIZE) {
3364 +                       return (ret < 0) ? ret : -ENOSPC;
3365 +               }
3366 +
3367 +               dump_config.dumper->curr_offset += DUMP_BUFFER_SIZE;
3368 +       
3369 +               if (left > DUMP_BUFFER_SIZE) {
3370 +                       left -= DUMP_BUFFER_SIZE;
3371 +                       memcpy(dump_config.dumper->dump_buf, 
3372 +                       dump_config.dumper->dump_buf + DUMP_BUFFER_SIZE, left);
3373 +                       dump_config.dumper->curr_buf -= DUMP_BUFFER_SIZE;
3374 +               } else {
3375 +                       left = 0;
3376 +               }
3377 +       }
3378 +       return 0;
3379 +}
3380 +
3381 +
3382 +/* Default Formatter (lcrash) */
3383 +struct dump_fmt_ops dump_fmt_lcrash_ops = {
3384 +       .configure_header       = dump_lcrash_configure_header,
3385 +       .update_header          = dump_generic_update_header,
3386 +       .save_context           = dump_lcrash_save_context,
3387 +       .add_data               = dump_lcrash_add_data,
3388 +       .update_end_marker      = dump_lcrash_update_end_marker
3389 +};
3390 +
3391 +struct dump_fmt dump_fmt_lcrash = {
3392 +       .name   = "lcrash",
3393 +       .ops    = &dump_fmt_lcrash_ops
3394 +};
3395 +
3396 Index: linux-2.6.10-base/drivers/dump/dump_netdev.c
3397 ===================================================================
3398 --- linux-2.6.10-base.orig/drivers/dump/dump_netdev.c   2003-09-02 06:26:13.000000000 +0800
3399 +++ linux-2.6.10-base/drivers/dump/dump_netdev.c        2005-05-17 18:52:39.934055512 +0800
3400 @@ -0,0 +1,566 @@
3401 +/*
3402 + * Implements the dump driver interface for saving a dump via network
3403 + * interface. 
3404 + *
3405 + * Some of this code has been taken/adapted from Ingo Molnar's netconsole
3406 + * code. LKCD team expresses its thanks to Ingo.
3407 + *
3408 + * Started: June 2002 - Mohamed Abbas <mohamed.abbas@intel.com>
3409 + *     Adapted netconsole code to implement LKCD dump over the network.
3410 + *
3411 + * Nov 2002 - Bharata B. Rao <bharata@in.ibm.com>
3412 + *     Innumerable code cleanups, simplification and some fixes.
3413 + *     Netdump configuration done by ioctl instead of using module parameters.
3414 + * Oct 2003 - Prasanna S Panchamukhi <prasanna@in.ibm.com>
3415 + *     Netdump code modified to use Netpoll API's.
3416 + *
3417 + * Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
3418 + * Copyright (C) 2002 International Business Machines Corp. 
3419 + *
3420 + *  This code is released under version 2 of the GNU GPL.
3421 + */
3422 +
3423 +#include <net/tcp.h>
3424 +#include <net/udp.h>
3425 +#include <linux/delay.h>
3426 +#include <linux/random.h>
3427 +#include <linux/reboot.h>
3428 +#include <linux/module.h>
3429 +#include <linux/dump.h>
3430 +#include <linux/dump_netdev.h>
3431 +
3432 +#include <asm/unaligned.h>
3433 +
3434 +static int startup_handshake;
3435 +static int page_counter;
3436 +static unsigned long flags_global;
3437 +static int netdump_in_progress;
3438 +
3439 +/*
3440 + * security depends on the trusted path between the netconsole
3441 + * server and netconsole client, since none of the packets are
3442 + * encrypted. The random magic number protects the protocol
3443 + * against spoofing.
3444 + */
3445 +static u64 dump_magic;
3446 +
3447 +/*
3448 + * We maintain a small pool of fully-sized skbs,
3449 + * to make sure the message gets out even in
3450 + * extreme OOM situations.
3451 + */
3452 +
3453 +static void rx_hook(struct netpoll *np, int port, char *msg, int size);
3454 +int new_req = 0;
3455 +static req_t req;
3456 +
3457 +static void rx_hook(struct netpoll *np, int port, char *msg, int size)
3458 +{
3459 +       req_t * __req = (req_t *) msg;
3460 +       /* 
3461 +        * First check if were are dumping or doing startup handshake, if
3462 +        * not quickly return.
3463 +        */
3464 +
3465 +       if (!netdump_in_progress)
3466 +               return ;
3467 +
3468 +       if ((ntohl(__req->command) != COMM_GET_MAGIC) &&
3469 +           (ntohl(__req->command) != COMM_HELLO) &&
3470 +           (ntohl(__req->command) != COMM_START_WRITE_NETDUMP_ACK) &&
3471 +           (ntohl(__req->command) != COMM_START_NETDUMP_ACK) &&
3472 +           (memcmp(&__req->magic, &dump_magic, sizeof(dump_magic)) != 0))
3473 +               goto out;
3474 +
3475 +       req.magic = ntohl(__req->magic);
3476 +       req.command = ntohl(__req->command);
3477 +       req.from = ntohl(__req->from);
3478 +       req.to = ntohl(__req->to);
3479 +       req.nr = ntohl(__req->nr);
3480 +       new_req = 1;
3481 +out:
3482 +       return ;
3483 +}
3484 +static char netdump_membuf[1024 + HEADER_LEN + 1];
3485 +/*
3486 + * Fill the netdump_membuf with the header information from reply_t structure 
3487 + * and send it down to netpoll_send_udp() routine.
3488 + */
3489 +static void 
3490 +netdump_send_packet(struct netpoll *np, reply_t *reply, size_t data_len) {
3491 +       char *b;
3492 +
3493 +       b = &netdump_membuf[1];
3494 +       netdump_membuf[0] = NETCONSOLE_VERSION;
3495 +       put_unaligned(htonl(reply->nr), (u32 *) b);
3496 +       put_unaligned(htonl(reply->code), (u32 *) (b + sizeof(reply->code)));
3497 +       put_unaligned(htonl(reply->info), (u32 *) (b + sizeof(reply->code) + 
3498 +               sizeof(reply->info)));
3499 +       netpoll_send_udp(np, netdump_membuf, data_len + HEADER_LEN);
3500 +}
3501 +
3502 +static void
3503 +dump_send_mem(struct netpoll *np, req_t *req, const char* buff, size_t len)
3504 +{
3505 +       int i;
3506 +
3507 +       int nr_chunks = len/1024;
3508 +       reply_t reply;
3509 +
3510 +       reply.nr = req->nr;
3511 +       reply.code = REPLY_MEM;
3512 +        if ( nr_chunks <= 0)
3513 +                nr_chunks = 1;
3514 +       for (i = 0; i < nr_chunks; i++) {
3515 +               unsigned int offset = i*1024;
3516 +               reply.info = offset;
3517 +               memcpy((netdump_membuf + HEADER_LEN), (buff + offset), 1024);
3518 +               netdump_send_packet(np, &reply, 1024);
3519 +       }
3520 +}
3521 +
3522 +/*
3523 + * This function waits for the client to acknowledge the receipt
3524 + * of the netdump startup reply, with the possibility of packets
3525 + * getting lost. We resend the startup packet if no ACK is received,
3526 + * after a 1 second delay.
3527 + *
3528 + * (The client can test the success of the handshake via the HELLO
3529 + * command, and send ACKs until we enter netdump mode.)
3530 + */
3531 +static int
3532 +dump_handshake(struct dump_dev *net_dev)
3533 +{
3534 +       reply_t reply;
3535 +       int i, j;
3536 +       size_t str_len;
3537 +
3538 +       if (startup_handshake) {
3539 +               sprintf((netdump_membuf + HEADER_LEN), 
3540 +                       "NETDUMP start, waiting for start-ACK.\n");
3541 +               reply.code = REPLY_START_NETDUMP;
3542 +               reply.nr = 0;
3543 +               reply.info = 0;
3544 +       } else {
3545 +               sprintf((netdump_membuf + HEADER_LEN), 
3546 +                       "NETDUMP start, waiting for start-ACK.\n");
3547 +               reply.code = REPLY_START_WRITE_NETDUMP;
3548 +               reply.nr = net_dev->curr_offset;
3549 +               reply.info = net_dev->curr_offset;
3550 +       }
3551 +       str_len = strlen(netdump_membuf + HEADER_LEN);
3552 +       
3553 +       /* send 300 handshake packets before declaring failure */
3554 +       for (i = 0; i < 300; i++) {
3555 +               netdump_send_packet(&net_dev->np, &reply, str_len);
3556 +
3557 +               /* wait 1 sec */
3558 +               for (j = 0; j < 10000; j++) {
3559 +                       udelay(100);
3560 +                       netpoll_poll(&net_dev->np);
3561 +                       if (new_req)
3562 +                               break;
3563 +               }
3564 +
3565 +               /* 
3566 +                * if there is no new request, try sending the handshaking
3567 +                * packet again
3568 +                */
3569 +               if (!new_req)
3570 +                       continue;
3571 +
3572 +               /* 
3573 +                * check if the new request is of the expected type,
3574 +                * if so, return, else try sending the handshaking
3575 +                * packet again
3576 +                */
3577 +               if (startup_handshake) {
3578 +                       if (req.command == COMM_HELLO || req.command ==
3579 +                               COMM_START_NETDUMP_ACK) {
3580 +                               return 0;
3581 +                       } else {
3582 +                               new_req = 0;
3583 +                               continue;
3584 +                       }
3585 +               } else {
3586 +                       if (req.command == COMM_SEND_MEM) {
3587 +                               return 0;
3588 +                       } else {
3589 +                               new_req = 0;
3590 +                               continue;
3591 +                       }
3592 +               }
3593 +       }
3594 +       return -1;
3595 +}
3596 +
3597 +static ssize_t
3598 +do_netdump(struct dump_dev *net_dev, const char* buff, size_t len)
3599 +{
3600 +       reply_t reply;
3601 +       ssize_t  ret = 0;
3602 +       int repeatCounter, counter, total_loop;
3603 +       size_t str_len;
3604 +       
3605 +       netdump_in_progress = 1;
3606 +
3607 +       if (dump_handshake(net_dev) < 0) {
3608 +               printk("network dump failed due to handshake failure\n");
3609 +               goto out;
3610 +       }
3611 +
3612 +       /*
3613 +        * Ideally startup handshake should be done during dump configuration,
3614 +        * i.e., in dump_net_open(). This will be done when I figure out
3615 +        * the dependency between startup handshake, subsequent write and
3616 +        * various commands wrt to net-server.
3617 +        */
3618 +       if (startup_handshake)
3619 +               startup_handshake = 0;
3620 +
3621 +        counter = 0;
3622 +       repeatCounter = 0;
3623 +       total_loop = 0;
3624 +       while (1) {
3625 +                if (!new_req) {
3626 +                       netpoll_poll(&net_dev->np);
3627 +               }
3628 +               if (!new_req) {
3629 +                       repeatCounter++;
3630 +
3631 +                       if (repeatCounter > 5) {
3632 +                               counter++;
3633 +                               if (counter > 10000) {
3634 +                                       if (total_loop >= 100000) {
3635 +                                               printk("Time OUT LEAVE NOW\n");
3636 +                                               goto out;
3637 +                                       } else {
3638 +                                               total_loop++;
3639 +                                               printk("Try number %d out of "
3640 +                                                       "10 before Time Out\n",
3641 +                                                       total_loop);
3642 +                                       }
3643 +                               }
3644 +                               mdelay(1);
3645 +                               repeatCounter = 0;
3646 +                       }       
3647 +                       continue;
3648 +               }
3649 +               repeatCounter = 0;
3650 +               counter = 0;
3651 +               total_loop = 0;
3652 +               new_req = 0;
3653 +               switch (req.command) {
3654 +               case COMM_NONE:
3655 +                       break;
3656 +
3657 +               case COMM_SEND_MEM:
3658 +                       dump_send_mem(&net_dev->np, &req, buff, len);
3659 +                       break;
3660 +
3661 +               case COMM_EXIT:
3662 +                case COMM_START_WRITE_NETDUMP_ACK:
3663 +                       ret = len;
3664 +                       goto out;
3665 +
3666 +               case COMM_HELLO:
3667 +                       sprintf((netdump_membuf + HEADER_LEN), 
3668 +                               "Hello, this is netdump version " "0.%02d\n",
3669 +                                NETCONSOLE_VERSION);
3670 +                       str_len = strlen(netdump_membuf + HEADER_LEN);
3671 +                       reply.code = REPLY_HELLO;
3672 +                       reply.nr = req.nr;
3673 +                        reply.info = net_dev->curr_offset;
3674 +                       netdump_send_packet(&net_dev->np, &reply, str_len);
3675 +                       break;
3676 +
3677 +               case COMM_GET_PAGE_SIZE:
3678 +                       sprintf((netdump_membuf + HEADER_LEN), 
3679 +                               "PAGE_SIZE: %ld\n", PAGE_SIZE);
3680 +                       str_len = strlen(netdump_membuf + HEADER_LEN);
3681 +                       reply.code = REPLY_PAGE_SIZE;
3682 +                       reply.nr = req.nr;
3683 +                       reply.info = PAGE_SIZE;
3684 +                       netdump_send_packet(&net_dev->np, &reply, str_len);
3685 +                       break;
3686 +
3687 +               case COMM_GET_NR_PAGES:
3688 +                       reply.code = REPLY_NR_PAGES;
3689 +                       reply.nr = req.nr;
3690 +                       reply.info = num_physpages;
3691 +                       reply.info = page_counter;
3692 +                       sprintf((netdump_membuf + HEADER_LEN), 
3693 +                               "Number of pages: %ld\n", num_physpages);
3694 +                       str_len = strlen(netdump_membuf + HEADER_LEN);
3695 +                       netdump_send_packet(&net_dev->np, &reply, str_len);
3696 +                       break;
3697 +
3698 +               case COMM_GET_MAGIC:
3699 +                       reply.code = REPLY_MAGIC;
3700 +                       reply.nr = req.nr;
3701 +                       reply.info = NETCONSOLE_VERSION;
3702 +                       sprintf((netdump_membuf + HEADER_LEN), 
3703 +                               (char *)&dump_magic, sizeof(dump_magic));
3704 +                       str_len = strlen(netdump_membuf + HEADER_LEN);
3705 +                       netdump_send_packet(&net_dev->np, &reply, str_len);
3706 +                       break;
3707 +
3708 +               default:
3709 +                       reply.code = REPLY_ERROR;
3710 +                       reply.nr = req.nr;
3711 +                       reply.info = req.command;
3712 +                       sprintf((netdump_membuf + HEADER_LEN), 
3713 +                               "Got unknown command code %d!\n", req.command);
3714 +                       str_len = strlen(netdump_membuf + HEADER_LEN);
3715 +                       netdump_send_packet(&net_dev->np, &reply, str_len);
3716 +                       break;
3717 +               }
3718 +       }
3719 +out:
3720 +       netdump_in_progress = 0;
3721 +       return ret;
3722 +}
3723 +
3724 +static int
3725 +dump_validate_config(struct netpoll *np)
3726 +{
3727 +       if (!np->local_ip) {
3728 +               printk("network device %s has no local address, "
3729 +                               "aborting.\n", np->name);
3730 +               return -1;
3731 +       }
3732 +
3733 +#define IP(x) ((unsigned char *)&np->local_ip)[x]
3734 +       printk("Source %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
3735 +#undef IP
3736 +
3737 +       if (!np->local_port) {
3738 +               printk("source_port parameter not specified, aborting.\n");
3739 +               return -1;
3740 +       }
3741 +
3742 +       if (!np->remote_ip) {
3743 +               printk("target_ip parameter not specified, aborting.\n");
3744 +               return -1;
3745 +       }
3746 +
3747 +       np->remote_ip = ntohl(np->remote_ip);
3748 +#define IP(x) ((unsigned char *)&np->remote_ip)[x]
3749 +       printk("Target %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
3750 +#undef IP
3751 +
3752 +       if (!np->remote_port) {
3753 +               printk("target_port parameter not specified, aborting.\n");
3754 +               return -1;
3755 +       }
3756 +       printk("Target Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x",
3757 +               np->remote_mac[0], np->remote_mac[1], np->remote_mac[2], 
3758 +               np->remote_mac[3], np->remote_mac[4], np->remote_mac[5]);
3759 +
3760 +       if ((np->remote_mac[0] & np->remote_mac[1] & np->remote_mac[2] & 
3761 +               np->remote_mac[3] & np->remote_mac[4] & np->remote_mac[5]) == 255)
3762 +               printk("(Broadcast)");
3763 +       printk("\n");
3764 +       return 0;
3765 +}
3766 +
3767 +/*
3768 + * Prepares the dump device so we can take a dump later. 
3769 + * Validates the netdump configuration parameters.
3770 + *
3771 + * TODO: Network connectivity check should be done here.
3772 + */
3773 +static int
3774 +dump_net_open(struct dump_dev *net_dev, unsigned long arg)
3775 +{
3776 +       int retval = 0;
3777 +
3778 +       /* get the interface name */
3779 +       if (copy_from_user(net_dev->np.dev_name, (void *)arg, IFNAMSIZ))
3780 +               return -EFAULT;
3781 +       net_dev->np.rx_hook = rx_hook;  
3782 +       retval = netpoll_setup(&net_dev->np);
3783 +
3784 +       dump_validate_config(&net_dev->np);
3785 +       net_dev->curr_offset = 0;
3786 +       printk("Network device %s successfully configured for dumping\n",
3787 +                       net_dev->np.dev_name);
3788 +       return retval;
3789 +}
3790 +
3791 +/*
3792 + * Close the dump device and release associated resources
3793 + * Invoked when unconfiguring the dump device.
3794 + */
3795 +static int
3796 +dump_net_release(struct dump_dev *net_dev)
3797 +{
3798 +       netpoll_cleanup(&net_dev->np);
3799 +       return 0;
3800 +}
3801 +
3802 +/*
3803 + * Prepare the dump device for use (silence any ongoing activity
3804 + * and quiesce state) when the system crashes.
3805 + */
3806 +static int
3807 +dump_net_silence(struct dump_dev *net_dev)
3808 +{
3809 +       netpoll_set_trap(1);
3810 +       local_irq_save(flags_global);
3811 +        startup_handshake = 1;
3812 +       net_dev->curr_offset = 0;
3813 +       printk("Dumping to network device %s on CPU %d ...\n", net_dev->np.name,
3814 +                       smp_processor_id());
3815 +       return 0;
3816 +}
3817 +
3818 +/*
3819 + * Invoked when dumping is done. This is the time to put things back 
3820 + * (i.e. undo the effects of dump_block_silence) so the device is 
3821 + * available for normal use.
3822 + */
3823 +static int
3824 +dump_net_resume(struct dump_dev *net_dev)
3825 +{
3826 +       int indx;
3827 +       size_t str_len;
3828 +       reply_t reply;
3829 +
3830 +       sprintf((netdump_membuf + HEADER_LEN), "NETDUMP end.\n");
3831 +       str_len = strlen(netdump_membuf + HEADER_LEN);
3832 +       for( indx = 0; indx < 6; indx++) {
3833 +               reply.code = REPLY_END_NETDUMP;
3834 +               reply.nr = 0;
3835 +               reply.info = 0;
3836 +               netdump_send_packet(&net_dev->np, &reply, str_len);
3837 +       }
3838 +       printk("NETDUMP END!\n");
3839 +       local_irq_restore(flags_global);
3840 +       netpoll_set_trap(0);
3841 +       startup_handshake = 0;
3842 +       return 0;
3843 +}
3844 +
3845 +/*
3846 + * Seek to the specified offset in the dump device.
3847 + * Makes sure this is a valid offset, otherwise returns an error.
3848 + */
3849 +static  int
3850 +dump_net_seek(struct dump_dev *net_dev, loff_t off)
3851 +{
3852 +       net_dev->curr_offset = off;
3853 +       return 0;
3854 +}
3855 +
3856 +/*
3857 + *
3858 + */
3859 +static int
3860 +dump_net_write(struct dump_dev *net_dev, void *buf, unsigned long len)
3861 +{
3862 +       int cnt, i, off;
3863 +       ssize_t ret;
3864 +
3865 +       cnt = len/ PAGE_SIZE;
3866 +
3867 +       for (i = 0; i < cnt; i++) {
3868 +               off = i* PAGE_SIZE;
3869 +               ret = do_netdump(net_dev, buf+off, PAGE_SIZE);
3870 +               if (ret <= 0)
3871 +                       return -1;
3872 +               net_dev->curr_offset = net_dev->curr_offset + PAGE_SIZE;
3873 +       }
3874 +       return len;
3875 +}
3876 +
3877 +/*
3878 + * check if the last dump i/o is over and ready for next request
3879 + */
3880 +static int
3881 +dump_net_ready(struct dump_dev *net_dev, void *buf)
3882 +{
3883 +       return 0;
3884 +}
3885 +
3886 +/*
3887 + * ioctl function used for configuring network dump
3888 + */
3889 +static int
3890 +dump_net_ioctl(struct dump_dev *net_dev, unsigned int cmd, unsigned long arg)
3891 +{
3892 +       switch (cmd) {
3893 +       case DIOSTARGETIP:
3894 +               net_dev->np.remote_ip= arg;
3895 +               break;
3896 +       case DIOSTARGETPORT:
3897 +               net_dev->np.remote_port = (u16)arg;
3898 +               break;
3899 +       case DIOSSOURCEPORT:
3900 +               net_dev->np.local_port = (u16)arg;
3901 +               break;
3902 +       case DIOSETHADDR:
3903 +               return copy_from_user(net_dev->np.remote_mac, (void *)arg, 6);
3904 +               break;
3905 +       case DIOGTARGETIP:
3906 +       case DIOGTARGETPORT:
3907 +       case DIOGSOURCEPORT:
3908 +       case DIOGETHADDR:
3909 +               break;
3910 +       default:
3911 +               return -EINVAL;
3912 +       }
3913 +       return 0;
3914 +}
3915 +
3916 +struct dump_dev_ops dump_netdev_ops = {
3917 +       .open           = dump_net_open,
3918 +       .release        = dump_net_release,
3919 +       .silence        = dump_net_silence,
3920 +       .resume         = dump_net_resume,
3921 +       .seek           = dump_net_seek,
3922 +       .write          = dump_net_write,
3923 +       /* .read not implemented */
3924 +       .ready          = dump_net_ready,
3925 +       .ioctl          = dump_net_ioctl
3926 +};
3927 +
3928 +static struct dump_dev default_dump_netdev = {
3929 +       .type_name = "networkdev", 
3930 +       .ops = &dump_netdev_ops, 
3931 +       .curr_offset = 0,
3932 +       .np.name = "netdump",
3933 +       .np.dev_name = "eth0",
3934 +       .np.rx_hook = rx_hook,
3935 +       .np.local_port = 6688,
3936 +       .np.remote_port = 6688,
3937 +       .np.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
3938 +};
3939 +
3940 +static int __init
3941 +dump_netdev_init(void)
3942 +{
3943 +       default_dump_netdev.curr_offset = 0;
3944 +
3945 +       if (dump_register_device(&default_dump_netdev) < 0) {
3946 +               printk("network dump device driver registration failed\n");
3947 +               return -1;
3948 +       }
3949 +       printk("network device driver for LKCD registered\n");
3950
3951 +       get_random_bytes(&dump_magic, sizeof(dump_magic));
3952 +       return 0;
3953 +}
3954 +
3955 +static void __exit
3956 +dump_netdev_cleanup(void)
3957 +{
3958 +       dump_unregister_device(&default_dump_netdev);
3959 +}
3960 +
3961 +MODULE_AUTHOR("LKCD Development Team <lkcd-devel@lists.sourceforge.net>");
3962 +MODULE_DESCRIPTION("Network Dump Driver for Linux Kernel Crash Dump (LKCD)");
3963 +MODULE_LICENSE("GPL");
3964 +
3965 +module_init(dump_netdev_init);
3966 +module_exit(dump_netdev_cleanup);
3967 Index: linux-2.6.10-base/drivers/dump/dump_methods.h
3968 ===================================================================
3969 --- linux-2.6.10-base.orig/drivers/dump/dump_methods.h  2003-09-02 06:26:13.000000000 +0800
3970 +++ linux-2.6.10-base/drivers/dump/dump_methods.h       2005-05-17 18:52:39.934055512 +0800
3971 @@ -0,0 +1,357 @@
3972 +/*
3973 + * Generic interfaces for flexible system dump 
3974 + *
3975 + * Started: Oct 2002 -  Suparna Bhattacharya (suparna@in.ibm.com)
3976 + *
3977 + * Copyright (C) 2002 International Business Machines Corp. 
3978 + *
3979 + * This code is released under version 2 of the GNU GPL.
3980 + */
3981 +
3982 +#ifndef _LINUX_DUMP_METHODS_H
3983 +#define _LINUX_DUMP_METHODS_H
3984 +
3985 +/*
3986 + * Inspired by Matt Robinson's suggestion of introducing dump 
3987 + * methods as a way to enable different crash dump facilities to 
3988 + * coexist where each employs its own scheme or dumping policy.
3989 + *
3990 + * The code here creates a framework for flexible dump by defining 
3991 + * a set of methods and providing associated helpers that differentiate
3992 + * between the underlying mechanism (how to dump), overall scheme 
3993 + * (sequencing of stages and data dumped and associated quiescing), 
3994 + * output format (what the dump output looks like), target type 
3995 + * (where to save the dump; see dumpdev.h), and selection policy 
3996 + * (state/data to dump).
3997 + * 
3998 + * These sets of interfaces can be mixed and matched to build a 
3999 + * dumper suitable for a given situation, allowing for 
4000 + * flexibility as well appropriate degree of code reuse.
4001 + * For example all features and options of lkcd (including
4002 + * granular selective dumping in the near future) should be
4003 + * available even when say, the 2 stage soft-boot based mechanism 
4004 + * is used for taking disruptive dumps.
4005 + *
4006 + * Todo: Additionally modules or drivers may supply their own
4007 + * custom dumpers which extend dump with module specific
4008 + * information or hardware state, and can even tweak the
4009 + * mechanism when it comes to saving state relevant to
4010 + * them.
4011 + */
4012 +
4013 +#include <linux/sched.h>
4014 +#include <linux/slab.h>
4015 +#include <linux/highmem.h>
4016 +#include <linux/dumpdev.h>
4017 +#include <asm/page.h>  /* get_order */
4018 +
4019 +#define MAX_PASSES     6
4020 +#define MAX_DEVS       4
4021 +
4022 +
4023 +/* To customise selection of pages to be dumped in a given pass/group */
4024 +struct dump_data_filter{
4025 +       char name[32];
4026 +       int (*selector)(int, unsigned long, unsigned long);
4027 +       ulong level_mask; /* dump level(s) for which this filter applies */
4028 +       loff_t start[MAX_NUMNODES], end[MAX_NUMNODES]; /* location range applicable */
4029 +       ulong num_mbanks;  /* Number of memory banks. Greater than one for discontig memory (NUMA) */
4030 +};
4031 +
4032 +
4033 +/* 
4034 + * Determined by the kind of dump mechanism and appropriate 
4035 + * overall scheme 
4036 + */ 
4037 +struct dump_scheme_ops {
4038 +       /* sets aside memory, inits data structures etc */
4039 +       int (*configure)(unsigned long devid); 
4040 +       /* releases  resources */
4041 +       int (*unconfigure)(void); 
4042 +
4043 +       /* ordering of passes, invoking iterator */
4044 +       int (*sequencer)(void); 
4045 +        /* iterates over system data, selects and acts on data to dump */
4046 +       int (*iterator)(int, int (*)(unsigned long, unsigned long), 
4047 +               struct dump_data_filter *); 
4048 +        /* action when data is selected for dump */
4049 +       int (*save_data)(unsigned long, unsigned long); 
4050 +        /* action when data is to be excluded from dump */
4051 +       int (*skip_data)(unsigned long, unsigned long); 
4052 +       /* policies for space, multiple dump devices etc */
4053 +       int (*write_buffer)(void *, unsigned long); 
4054 +};
4055 +
4056 +struct dump_scheme {
4057 +       /* the name serves as an anchor to locate the scheme after reboot */
4058 +       char name[32]; 
4059 +       struct dump_scheme_ops *ops;
4060 +       struct list_head list;
4061 +};
4062 +
4063 +/* Quiescing/Silence levels (controls IPI callback behaviour) */
4064 +extern enum dump_silence_levels {
4065 +       DUMP_SOFT_SPIN_CPUS     = 1,
4066 +       DUMP_HARD_SPIN_CPUS     = 2,
4067 +       DUMP_HALT_CPUS          = 3,
4068 +} dump_silence_level;
4069 +
4070 +/* determined by the dump (file) format */
4071 +struct dump_fmt_ops {
4072 +       /* build header */
4073 +       int (*configure_header)(const char *, const struct pt_regs *); 
4074 +       int (*update_header)(void); /* update header and write it out */
4075 +       /* save curr context  */
4076 +       void (*save_context)(int, const struct pt_regs *, 
4077 +               struct task_struct *); 
4078 +       /* typically called by the save_data action */
4079 +       /* add formatted data to the dump buffer */
4080 +       int (*add_data)(unsigned long, unsigned long); 
4081 +       int (*update_end_marker)(void);
4082 +};
4083 +
4084 +struct dump_fmt {
4085 +       unsigned long magic; 
4086 +       char name[32];  /* lcrash, crash, elf-core etc */
4087 +       struct dump_fmt_ops *ops;
4088 +       struct list_head list;
4089 +};
4090 +
4091 +/* 
4092 + * Modules will be able add their own data capture schemes by 
4093 + * registering their own dumpers. Typically they would use the 
4094 + * primary dumper as a template and tune it with their routines.
4095 + * Still Todo.
4096 + */
4097 +
4098 +/* The combined dumper profile (mechanism, scheme, dev, fmt) */
4099 +struct dumper {
4100 +       char name[32]; /* singlestage, overlay (stg1), passthru(stg2), pull */
4101 +       struct dump_scheme *scheme;
4102 +       struct dump_fmt *fmt;
4103 +       struct __dump_compress *compress;
4104 +       struct dump_data_filter *filter;
4105 +       struct dump_dev *dev; 
4106 +       /* state valid only for active dumper(s) - per instance */
4107 +       /* run time state/context */
4108 +       int curr_pass;
4109 +       unsigned long count;
4110 +       loff_t curr_offset; /* current logical offset into dump device */
4111 +       loff_t curr_loc; /* current memory location */
4112 +       void *curr_buf; /* current position in the dump buffer */
4113 +       void *dump_buf; /* starting addr of dump buffer */
4114 +       int header_dirty; /* whether the header needs to be written out */
4115 +       int header_len; 
4116 +       struct list_head dumper_list; /* links to other dumpers */
4117 +};     
4118 +
4119 +/* Starting point to get to the current configured state */
4120 +struct dump_config {
4121 +       ulong level;
4122 +       ulong flags;
4123 +       struct dumper *dumper;
4124 +       unsigned long dump_device;
4125 +       unsigned long dump_addr; /* relevant only for in-memory dumps */
4126 +       struct list_head dump_dev_list;
4127 +};     
4128 +
4129 +extern struct dump_config dump_config;
4130 +
4131 +/* Used to save the dump config across a reboot for 2-stage dumps: 
4132 + * 
4133 + * Note: The scheme, format, compression and device type should be 
4134 + * registered at bootup, for this config to be sharable across soft-boot. 
4135 + * The function addresses could have changed and become invalid, and
4136 + * need to be set up again.
4137 + */
4138 +struct dump_config_block {
4139 +       u64 magic; /* for a quick sanity check after reboot */
4140 +       struct dump_memdev memdev; /* handle to dump stored in memory */
4141 +       struct dump_config config;
4142 +       struct dumper dumper;
4143 +       struct dump_scheme scheme;
4144 +       struct dump_fmt fmt;
4145 +       struct __dump_compress compress;
4146 +       struct dump_data_filter filter_table[MAX_PASSES];
4147 +       struct dump_anydev dev[MAX_DEVS]; /* target dump device */
4148 +};
4149 +
4150 +
4151 +/* Wrappers that invoke the methods for the current (active) dumper */
4152 +
4153 +/* Scheme operations */
4154 +
4155 +static inline int dump_sequencer(void)
4156 +{
4157 +       return dump_config.dumper->scheme->ops->sequencer();
4158 +}
4159 +
4160 +static inline int dump_iterator(int pass, int (*action)(unsigned long, 
4161 +       unsigned long), struct dump_data_filter *filter)
4162 +{
4163 +       return dump_config.dumper->scheme->ops->iterator(pass, action, filter);
4164 +}
4165 +
4166 +#define dump_save_data dump_config.dumper->scheme->ops->save_data
4167 +#define dump_skip_data dump_config.dumper->scheme->ops->skip_data
4168 +
4169 +static inline int dump_write_buffer(void *buf, unsigned long len)
4170 +{
4171 +       return dump_config.dumper->scheme->ops->write_buffer(buf, len);
4172 +}
4173 +
4174 +static inline int dump_configure(unsigned long devid)
4175 +{
4176 +       return dump_config.dumper->scheme->ops->configure(devid);
4177 +}
4178 +
4179 +static inline int dump_unconfigure(void)
4180 +{
4181 +       return dump_config.dumper->scheme->ops->unconfigure();
4182 +}
4183 +
4184 +/* Format operations */
4185 +
4186 +static inline int dump_configure_header(const char *panic_str, 
4187 +       const struct pt_regs *regs)
4188 +{
4189 +       return dump_config.dumper->fmt->ops->configure_header(panic_str, regs);
4190 +}
4191 +
4192 +static inline void dump_save_context(int cpu, const struct pt_regs *regs, 
4193 +               struct task_struct *tsk)
4194 +{
4195 +       dump_config.dumper->fmt->ops->save_context(cpu, regs, tsk);
4196 +}
4197 +
4198 +static inline int dump_save_this_cpu(const struct pt_regs *regs)
4199 +{
4200 +       int cpu = smp_processor_id();
4201 +
4202 +       dump_save_context(cpu, regs, current);
4203 +       return 1;
4204 +}
4205 +
4206 +static inline int dump_update_header(void)
4207 +{
4208 +       return dump_config.dumper->fmt->ops->update_header();
4209 +}
4210 +
4211 +static inline int dump_update_end_marker(void)
4212 +{
4213 +       return dump_config.dumper->fmt->ops->update_end_marker();
4214 +}
4215 +
4216 +static inline int dump_add_data(unsigned long loc, unsigned long sz)
4217 +{
4218 +       return dump_config.dumper->fmt->ops->add_data(loc, sz);
4219 +}
4220 +
4221 +/* Compression operation */
4222 +static inline int dump_compress_data(char *src, int slen, char *dst,
4223 +               unsigned long loc)
4224 +{
4225 +       return dump_config.dumper->compress->compress_func(src, slen, 
4226 +               dst, DUMP_DPC_PAGE_SIZE, loc);
4227 +}
4228 +
4229 +
4230 +/* Prototypes of some default implementations of dump methods */
4231 +
4232 +extern struct __dump_compress dump_none_compression;
4233 +
4234 +/* Default scheme methods (dump_scheme.c) */
4235 +
4236 +extern int dump_generic_sequencer(void);
4237 +extern int dump_page_iterator(int pass, int (*action)(unsigned long, unsigned
4238 +       long), struct dump_data_filter *filter);
4239 +extern int dump_generic_save_data(unsigned long loc, unsigned long sz);
4240 +extern int dump_generic_skip_data(unsigned long loc, unsigned long sz);
4241 +extern int dump_generic_write_buffer(void *buf, unsigned long len);
4242 +extern int dump_generic_configure(unsigned long);
4243 +extern int dump_generic_unconfigure(void);
4244 +#ifdef CONFIG_DISCONTIGMEM
4245 +extern void dump_reconfigure_mbanks(void);
4246 +#endif
4247 +
4248 +/* Default scheme template */
4249 +extern struct dump_scheme dump_scheme_singlestage;
4250 +
4251 +/* Default dump format methods */
4252 +
4253 +extern int dump_lcrash_configure_header(const char *panic_str, 
4254 +       const struct pt_regs *regs);
4255 +extern void dump_lcrash_save_context(int  cpu, const struct pt_regs *regs, 
4256 +       struct task_struct *tsk);
4257 +extern int dump_generic_update_header(void);
4258 +extern int dump_lcrash_add_data(unsigned long loc, unsigned long sz);
4259 +extern int dump_lcrash_update_end_marker(void);
4260 +
4261 +/* Default format (lcrash) template */
4262 +extern struct dump_fmt dump_fmt_lcrash;
4263 +
4264 +/* Default dump selection filter table */
4265 +
4266 +/* 
4267 + * Entries listed in order of importance and correspond to passes
4268 + * The last entry (with a level_mask of zero) typically reflects data that 
4269 + * won't be dumped  -- this may for example be used to identify data 
4270 + * that will be skipped for certain so the corresponding memory areas can be 
4271 + * utilized as scratch space.
4272 + */   
4273 +extern struct dump_data_filter dump_filter_table[];
4274 +
4275 +/* Some pre-defined dumpers */
4276 +extern struct dumper dumper_singlestage;
4277 +extern struct dumper dumper_stage1;
4278 +extern struct dumper dumper_stage2;
4279 +
4280 +/* These are temporary */
4281 +#define DUMP_MASK_HEADER       DUMP_LEVEL_HEADER
4282 +#define DUMP_MASK_KERN         DUMP_LEVEL_KERN
4283 +#define DUMP_MASK_USED         DUMP_LEVEL_USED
4284 +#define DUMP_MASK_UNUSED       DUMP_LEVEL_ALL_RAM
4285 +#define DUMP_MASK_REST         0 /* dummy for now */
4286 +
4287 +/* Helpers - move these to dump.h later ? */
4288 +
4289 +int dump_generic_execute(const char *panic_str, const struct pt_regs *regs);
4290 +extern int dump_ll_write(void *buf, unsigned long len); 
4291 +int dump_check_and_free_page(struct dump_memdev *dev, struct page *page);
4292 +
4293 +static inline void dumper_reset(void)
4294 +{
4295 +       dump_config.dumper->curr_buf = dump_config.dumper->dump_buf;
4296 +       dump_config.dumper->curr_loc = 0;
4297 +       dump_config.dumper->curr_offset = 0;
4298 +       dump_config.dumper->count = 0;
4299 +       dump_config.dumper->curr_pass = 0;
4300 +}
4301 +
4302 +/* 
4303 + * May later be moulded to perform boot-time allocations so we can dump 
4304 + * earlier during bootup 
4305 + */
4306 +static inline void *dump_alloc_mem(unsigned long size)
4307 +{
4308 +       return (void *) __get_free_pages(GFP_KERNEL, get_order(size));
4309 +}
4310 +
4311 +static inline void dump_free_mem(void *buf)
4312 +{
4313 +       struct page *page;
4314 +
4315 +       /* ignore reserved pages (e.g. post soft boot stage) */
4316 +       if (buf && (page = virt_to_page(buf))) {
4317 +               if (PageReserved(page))
4318 +                       return;
4319 +       }
4320 +       /*
4321 +        * Allocated using __get_free_pages().
4322 +        */
4323 +       free_pages((unsigned long)buf, 
4324 +               get_order(DUMP_BUFFER_SIZE + 3 * DUMP_PAGE_SIZE));
4325 +}
4326 +
4327 +
4328 +#endif /*  _LINUX_DUMP_METHODS_H */
4329 Index: linux-2.6.10-base/drivers/dump/dump_gzip.c
4330 ===================================================================
4331 --- linux-2.6.10-base.orig/drivers/dump/dump_gzip.c     2003-09-02 06:26:13.000000000 +0800
4332 +++ linux-2.6.10-base/drivers/dump/dump_gzip.c  2005-05-17 18:52:39.935055360 +0800
4333 @@ -0,0 +1,174 @@
4334 +/*
4335 + * GZIP Compression functions for kernel crash dumps.
4336 + *
4337 + * Created by: Matt Robinson (yakker@sourceforge.net)
4338 + * Copyright 2001 Matt D. Robinson.  All rights reserved.
4339 + *
4340 + * This code is released under version 2 of the GNU GPL.
4341 + */
4342 +
4343 +/* header files */
4344 +#include <linux/config.h>
4345 +#include <linux/module.h>
4346 +#include <linux/sched.h>
4347 +#include <linux/fs.h>
4348 +#include <linux/file.h>
4349 +#include <linux/init.h>
4350 +#include <linux/slab.h>
4351 +#include <linux/dump.h>
4352 +#include <linux/zlib.h>
4353 +#include <linux/vmalloc.h>
4354 +
4355 +static void *deflate_workspace;
4356 +static unsigned long workspace_paddr[2];
4357 +
4358 +static u8 *safety_buffer;
4359 +
4360 +/*
4361 + * Name: dump_compress_gzip()
4362 + * Func: Compress a DUMP_PAGE_SIZE page using gzip-style algorithms (the.
4363 + *       deflate functions similar to what's used in PPP).
4364 + */
4365 +static u32
4366 +dump_compress_gzip(const u8 *old, u32 oldsize, u8 *new, u32 newsize,
4367 +               unsigned long loc)
4368 +{
4369 +       /* error code and dump stream */
4370 +       int err;
4371 +       z_stream dump_stream;
4372 +       struct page *pg = (struct page *)loc;
4373 +       unsigned long paddr =  page_to_pfn(pg) << PAGE_SHIFT;
4374 +       static int warning = 0;
4375 +
4376 +       dump_stream.workspace = deflate_workspace;
4377 +       if ((paddr == workspace_paddr[0]) || (paddr == workspace_paddr[1])) {
4378 +               /* 
4379 +                * This page belongs to deflate_workspace used as temporary 
4380 +                * buffer for compression. Hence, dump them without compression.
4381 +                */
4382 +               return(0);
4383 +       }
4384 +       if ((err = zlib_deflateInit(&dump_stream, Z_BEST_COMPRESSION)) != Z_OK) {
4385 +               /* fall back to RLE compression */
4386 +               printk("dump_compress_gzip(): zlib_deflateInit() "
4387 +                       "failed (%d)!\n", err);
4388 +               return 0;
4389 +       }
4390 +
4391 +       /* copy the old page to the safety buffer */
4392 +       if (oldsize <= DUMP_PAGE_SIZE) {
4393 +               memcpy(safety_buffer, old, oldsize);
4394 +               dump_stream.next_in = (u8 *) safety_buffer;
4395 +       } else {
4396 +               if (!warning) {
4397 +                       printk("dump_compress_gzip oversize input: %d\n",
4398 +                                       oldsize);
4399 +                       warning++;
4400 +               }
4401 +               dump_stream.next_in = (u8 *) old;
4402 +       }
4403 +
4404 +       /* use old (page of memory) and size (DUMP_PAGE_SIZE) as in-streams */
4405 +       dump_stream.avail_in = oldsize;
4406 +
4407 +       /* out streams are new (dpcpage) and new size (DUMP_DPC_PAGE_SIZE) */
4408 +       dump_stream.next_out = new;
4409 +       dump_stream.avail_out = newsize;
4410 +
4411 +       /* deflate the page -- check for error */
4412 +       err = zlib_deflate(&dump_stream, Z_FINISH);
4413 +       if (err != Z_STREAM_END) {
4414 +               /* zero is return code here */
4415 +               (void)zlib_deflateEnd(&dump_stream);
4416 +               printk("dump_compress_gzip(): zlib_deflate() failed (%d)!\n",
4417 +                       err);
4418 +               return 0;
4419 +       }
4420 +
4421 +       /* let's end the deflated compression stream */
4422 +       if ((err = zlib_deflateEnd(&dump_stream)) != Z_OK) {
4423 +               printk("dump_compress_gzip(): zlib_deflateEnd() "
4424 +                       "failed (%d)!\n", err);
4425 +       }
4426 +
4427 +       /* return the compressed byte total (if it's smaller) */
4428 +       if (dump_stream.total_out >= oldsize) {
4429 +               return oldsize;
4430 +       }
4431 +       return dump_stream.total_out;
4432 +}
4433 +
4434 +/* setup the gzip compression functionality */
4435 +static struct __dump_compress dump_gzip_compression = {
4436 +       .compress_type = DUMP_COMPRESS_GZIP,
4437 +       .compress_func = dump_compress_gzip,
4438 +       .compress_name = "GZIP",
4439 +};
4440 +
4441 +/*
4442 + * Name: dump_compress_gzip_init()
4443 + * Func: Initialize gzip as a compression mechanism.
4444 + */
4445 +static int __init
4446 +dump_compress_gzip_init(void)
4447 +{
4448 +       struct page *pg;
4449 +
4450 +       deflate_workspace = vmalloc(zlib_deflate_workspacesize());
4451 +       if (!deflate_workspace) {
4452 +               printk("dump_compress_gzip_init(): Failed to "
4453 +                       "alloc %d bytes for deflate workspace\n",
4454 +                       zlib_deflate_workspacesize());
4455 +               return -ENOMEM;
4456 +       }
4457 +       /*
4458 +        * Need to find pages (workspace) that are used for compression.
4459 +        * Even though zlib_deflate_workspacesize() is 64 pages (approximately)
4460 +        * depends on the arch, we used only 2 pages. Hence, get the physical
4461 +        * addresses for these 2 pages and used them to not to compress those
4462 +        * pages.
4463 +        */
4464 +       pg = vmalloc_to_page(deflate_workspace);
4465 +       workspace_paddr[0] = page_to_pfn(pg) << PAGE_SHIFT;
4466 +       pg = vmalloc_to_page(deflate_workspace + DUMP_PAGE_SIZE);
4467 +       workspace_paddr[1] = page_to_pfn(pg) << PAGE_SHIFT;
4468 +
4469 +       /* Eliminate the possibility of real data getting a compression
4470 +        * failure.
4471 +        */
4472 +
4473 +       if (!(safety_buffer = (void *)__get_free_pages(GFP_KERNEL, 
4474 +                                       get_order(DUMP_PAGE_SIZE))))
4475 +               return -ENOMEM;
4476 +
4477 +       printk("dump gzip safety buffer: %p, %d\n", safety_buffer,
4478 +                       (int)DUMP_PAGE_SIZE);
4479 +
4480 +       dump_register_compression(&dump_gzip_compression);
4481 +       return 0;
4482 +}
4483 +
4484 +/*
4485 + * Name: dump_compress_gzip_cleanup()
4486 + * Func: Remove gzip as a compression mechanism.
4487 + */
4488 +static void __exit
4489 +dump_compress_gzip_cleanup(void)
4490 +{
4491 +       vfree(deflate_workspace);
4492 +       if (safety_buffer) {
4493 +               free_pages((unsigned long)safety_buffer, 
4494 +                               get_order(DUMP_PAGE_SIZE));
4495 +               safety_buffer = NULL;
4496 +       }
4497 +
4498 +       dump_unregister_compression(DUMP_COMPRESS_GZIP);
4499 +}
4500 +
4501 +/* module initialization */
4502 +module_init(dump_compress_gzip_init);
4503 +module_exit(dump_compress_gzip_cleanup);
4504 +
4505 +MODULE_LICENSE("GPL");
4506 +MODULE_AUTHOR("LKCD Development Team <lkcd-devel@lists.sourceforge.net>");
4507 +MODULE_DESCRIPTION("Gzip compression module for crash dump driver");
4508 Index: linux-2.6.10-base/drivers/dump/dump_ppc64.c
4509 ===================================================================
4510 --- linux-2.6.10-base.orig/drivers/dump/dump_ppc64.c    2003-09-02 06:26:13.000000000 +0800
4511 +++ linux-2.6.10-base/drivers/dump/dump_ppc64.c 2005-05-17 18:52:39.935055360 +0800
4512 @@ -0,0 +1,410 @@
4513 +/*
4514 + * Architecture specific (ppc64) functions for Linux crash dumps.
4515 + *
4516 + * Created by: Matt Robinson (yakker@sgi.com)
4517 + *
4518 + * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
4519 + * 
4520 + * 2.3 kernel modifications by: Matt D. Robinson (yakker@turbolinux.com)
4521 + * Copyright 2000 TurboLinux, Inc.  All rights reserved.
4522 + * Copyright 2003, 2004 IBM Corporation
4523 + * 
4524 + * This code is released under version 2 of the GNU GPL.
4525 + */
4526 +
4527 +/*
4528 + * The hooks for dumping the kernel virtual memory to disk are in this
4529 + * file.  Any time a modification is made to the virtual memory mechanism,
4530 + * these routines must be changed to use the new mechanisms.
4531 + */
4532 +#include <linux/types.h>
4533 +#include <linux/fs.h>
4534 +#include <linux/dump.h>
4535 +#include <linux/mm.h>
4536 +#include <linux/vmalloc.h>
4537 +#include <linux/delay.h>
4538 +#include <linux/syscalls.h> 
4539 +#include <asm/hardirq.h>
4540 +#include "dump_methods.h"
4541 +#include <linux/irq.h>
4542 +#include <asm/machdep.h>
4543 +#include <asm/uaccess.h>
4544 +#include <asm/irq.h>
4545 +#include <asm/page.h>
4546 +#if defined(CONFIG_KDB) && !defined(CONFIG_DUMP_MODULE)
4547 +#include <linux/kdb.h>
4548 +#endif
4549 +
4550 +extern cpumask_t irq_affinity[];
4551 +
4552 +static cpumask_t saved_affinity[NR_IRQS];
4553 +
4554 +static __s32         saved_irq_count;   /* saved preempt_count() flags */
4555 +
4556 +static int alloc_dha_stack(void)
4557 +{
4558 +        int i;
4559 +        void *ptr;
4560 +
4561 +        if (dump_header_asm.dha_stack[0])
4562 +                return 0;
4563 +
4564 +        ptr = (void *)vmalloc(THREAD_SIZE * num_possible_cpus());
4565 +        if (!ptr) {
4566 +                return -ENOMEM;
4567 +        }
4568 +
4569 +        for (i = 0; i < num_possible_cpus(); i++) {
4570 +                dump_header_asm.dha_stack[i] = 
4571 +                       (uint64_t)((unsigned long)ptr + (i * THREAD_SIZE));
4572 +       }
4573 +       return 0;
4574 +}
4575 +
4576 +static int free_dha_stack(void)
4577 +{
4578 +        if (dump_header_asm.dha_stack[0]) {
4579 +                vfree((void*)dump_header_asm.dha_stack[0]);
4580 +               dump_header_asm.dha_stack[0] = 0;
4581 +       }
4582 +        return 0;
4583 +}
4584 +#ifdef CONFIG_SMP
4585 +static int dump_expect_ipi[NR_CPUS];
4586 +static atomic_t waiting_for_dump_ipi;
4587 +
4588 +extern void stop_this_cpu(void *);
4589 +static int
4590 +dump_ipi_handler(struct pt_regs *regs) 
4591 +{
4592 +       int cpu = smp_processor_id();
4593 +
4594 +       if (!dump_expect_ipi[cpu])
4595 +               return 0;
4596 +       dump_save_this_cpu(regs);
4597 +       atomic_dec(&waiting_for_dump_ipi);
4598 +
4599 + level_changed:
4600 +       switch (dump_silence_level) {
4601 +       case DUMP_HARD_SPIN_CPUS:       /* Spin until dump is complete */
4602 +               while (dump_oncpu) {
4603 +                       barrier();      /* paranoia */
4604 +                       if (dump_silence_level != DUMP_HARD_SPIN_CPUS)
4605 +                               goto level_changed;
4606 +                       cpu_relax();    /* kill time nicely */
4607 +               }
4608 +               break;
4609 +
4610 +       case DUMP_HALT_CPUS:            /* Execute halt */
4611 +               stop_this_cpu(NULL);
4612 +               break;
4613 +       
4614 +       case DUMP_SOFT_SPIN_CPUS:
4615 +               /* Mark the task so it spins in schedule */
4616 +               set_tsk_thread_flag(current, TIF_NEED_RESCHED);
4617 +               break;
4618 +       }
4619 +
4620 +       return 1;
4621 +}
4622 +
4623 +/* save registers on other processors
4624 + * If the other cpus don't respond we simply do not get their states.
4625 + */
4626 +void 
4627 +__dump_save_other_cpus(void)
4628 +{
4629 +       int i, cpu = smp_processor_id();
4630 +       int other_cpus = num_online_cpus()-1;
4631 +       
4632 +       if (other_cpus > 0) {
4633 +               atomic_set(&waiting_for_dump_ipi, other_cpus);
4634 +               for (i = 0; i < NR_CPUS; i++)
4635 +                       dump_expect_ipi[i] = (i != cpu && cpu_online(i));
4636 +
4637 +               printk(KERN_ALERT "sending IPI to other cpus...\n");
4638 +               dump_send_ipi(dump_ipi_handler);
4639 +               /*
4640 +                * may be we dont need to wait for IPI to be processed.
4641 +                * just write out the header at the end of dumping, if
4642 +                * this IPI is not processed until then, there probably
4643 +                * is a problem and we just fail to capture state of
4644 +                * other cpus.
4645 +                * However, we will wait 10 secs for other CPUs to respond. 
4646 +                * If not, proceed the dump process even though we failed
4647 +                * to capture other CPU states. 
4648 +                */
4649 +               i = 10000; /* wait max of 10 seconds */
4650 +               while ((atomic_read(&waiting_for_dump_ipi) > 0) && (--i > 0)) {
4651 +                       barrier();
4652 +                       mdelay(1);
4653 +               } 
4654 +               printk(KERN_ALERT "done waiting: %d cpus not responding\n",
4655 +                      atomic_read(&waiting_for_dump_ipi));
4656 +               dump_send_ipi(NULL);    /* clear handler */
4657 +       }
4658 +}
4659 +
4660 +/*
4661 + * Restore old irq affinities.
4662 + */
4663 +static void
4664 +__dump_reset_irq_affinity(void)
4665 +{
4666 +       int i;
4667 +       irq_desc_t *irq_d;
4668 +
4669 +       memcpy(irq_affinity, saved_affinity, NR_IRQS * sizeof(unsigned long));
4670 +
4671 +       for_each_irq(i) {
4672 +               irq_d = get_irq_desc(i);
4673 +               if (irq_d->handler == NULL) {
4674 +                       continue;
4675 +               }
4676 +               if (irq_d->handler->set_affinity != NULL) {
4677 +                       irq_d->handler->set_affinity(i, saved_affinity[i]);
4678 +               }
4679 +       }
4680 +}
4681 +
4682 +/*
4683 + * Routine to save the old irq affinities and change affinities of all irqs to
4684 + * the dumping cpu.
4685 + *
4686 + * NB: Need to be expanded to multiple nodes.
4687 + */
4688 +static void
4689 +__dump_set_irq_affinity(void)
4690 +{
4691 +       int i;
4692 +       cpumask_t cpu = CPU_MASK_NONE;
4693 +       irq_desc_t *irq_d;
4694 +
4695 +       cpu_set(smp_processor_id(), cpu);
4696 +
4697 +       memcpy(saved_affinity, irq_affinity, NR_IRQS * sizeof(unsigned long));
4698 +
4699 +       for_each_irq(i) {
4700 +               irq_d = get_irq_desc(i);
4701 +               if (irq_d->handler == NULL) {
4702 +                       continue;
4703 +               }
4704 +               irq_affinity[i] = cpu;
4705 +               if (irq_d->handler->set_affinity != NULL) {
4706 +                       irq_d->handler->set_affinity(i, irq_affinity[i]);
4707 +               }
4708 +       }
4709 +}
4710 +#else /* !CONFIG_SMP */
4711 +#define __dump_save_other_cpus() do { } while (0)
4712 +#define __dump_set_irq_affinity()      do { } while (0)
4713 +#define __dump_reset_irq_affinity()    do { } while (0)
4714 +#endif /* !CONFIG_SMP */
4715 +
4716 +void
4717 +__dump_save_regs(struct pt_regs *dest_regs, const struct pt_regs *regs)
4718 +{
4719 +       if (regs) {
4720 +               memcpy(dest_regs, regs, sizeof(struct pt_regs));
4721 +       } 
4722 +}
4723 +
4724 +void
4725 +__dump_save_context(int cpu, const struct pt_regs *regs, 
4726 +       struct task_struct *tsk)
4727 +{
4728 +       dump_header_asm.dha_smp_current_task[cpu] = (unsigned long)tsk;
4729 +       __dump_save_regs(&dump_header_asm.dha_smp_regs[cpu], regs);
4730 +
4731 +       /* take a snapshot of the stack */
4732 +       /* doing this enables us to tolerate slight drifts on this cpu */
4733 +
4734 +       if (dump_header_asm.dha_stack[cpu]) {
4735 +               memcpy((void *)dump_header_asm.dha_stack[cpu],
4736 +                               STACK_START_POSITION(tsk),
4737 +                               THREAD_SIZE);
4738 +       }
4739 +       dump_header_asm.dha_stack_ptr[cpu] = (unsigned long)(tsk->thread_info);
4740 +}
4741 +
4742 +/*
4743 + * Name: __dump_configure_header()
4744 + * Func: Configure the dump header with all proper values.
4745 + */
4746 +int
4747 +__dump_configure_header(const struct pt_regs *regs)
4748 +{
4749 +       return (0);
4750 +}
4751 +
4752 +#if defined(CONFIG_KDB) && !defined(CONFIG_DUMP_MODULE)
4753 +int
4754 +kdb_sysdump(int argc, const char **argv, const char **envp, struct pt_regs *regs)
4755 +{
4756 +       kdb_printf("Dumping to disk...\n");
4757 +       dump("dump from kdb", regs);
4758 +       kdb_printf("Dump Complete\n");
4759 +       return 0;
4760 +}
4761 +#endif
4762 +
4763 +/*
4764 + * Name: __dump_init()
4765 + * Func: Initialize the dumping routine process.  This is in case
4766 + *       it's necessary in the future.
4767 + */
4768 +void
4769 +__dump_init(uint64_t local_memory_start)
4770 +{
4771 +#if defined(FIXME) && defined(CONFIG_KDB) && !defined(CONFIG_DUMP_MODULE)
4772 +       /* This won't currently work because interrupts are off in kdb
4773 +        * and the dump process doesn't understand how to recover.
4774 +        */
4775 +       /* ToDo: add a command to query/set dump configuration */
4776 +       kdb_register_repeat("sysdump", kdb_sysdump, "", "use lkcd to dump the system to disk (if configured)", 0, KDB_REPEAT_NONE);
4777 +#endif
4778 +
4779 +       /* return */
4780 +       return;
4781 +}
4782 +
4783 +/*
4784 + * Name: __dump_open()
4785 + * Func: Open the dump device (architecture specific).  This is in
4786 + *       case it's necessary in the future.
4787 + */
4788 +void
4789 +__dump_open(void)
4790 +{
4791 +       alloc_dha_stack();
4792 +}
4793 +
4794 +
4795 +/*
4796 + * Name: __dump_cleanup()
4797 + * Func: Free any architecture specific data structures. This is called
4798 + *       when the dump module is being removed.
4799 + */
4800 +void
4801 +__dump_cleanup(void)
4802 +{
4803 +       free_dha_stack();
4804 +}
4805 +
4806 +/*
4807 + * Kludge - dump from interrupt context is unreliable (Fixme)
4808 + *
4809 + * We do this so that softirqs initiated for dump i/o
4810 + * get processed and we don't hang while waiting for i/o
4811 + * to complete or in any irq synchronization attempt.
4812 + *
4813 + * This is not quite legal of course, as it has the side
4814 + * effect of making all interrupts & softirqs triggered
4815 + * while dump is in progress complete before currently
4816 + * pending softirqs and the currently executing interrupt
4817 + * code.
4818 + */
4819 +static inline void
4820 +irq_bh_save(void)
4821 +{
4822 +       saved_irq_count = irq_count();
4823 +       preempt_count() &= ~(HARDIRQ_MASK|SOFTIRQ_MASK);
4824 +}
4825 +
4826 +static inline void
4827 +irq_bh_restore(void)
4828 +{
4829 +       preempt_count() |= saved_irq_count;
4830 +}
4831 +
4832 +/*
4833 + * Name: __dump_irq_enable
4834 + * Func: Reset system so interrupts are enabled.
4835 + * This is used for dump methods that require interrupts
4836 + * Eventually, all methods will have interrupts disabled
4837 + * and this code can be removed.
4838 + *
4839 + * Change irq affinities
4840 + * Re-enable interrupts
4841 + */
4842 +int
4843 +__dump_irq_enable(void)
4844 +{
4845 +       __dump_set_irq_affinity();
4846 +       irq_bh_save();
4847 +       local_irq_enable();
4848 +       return 0;
4849 +}
4850 +
4851 +/*
4852 + * Name: __dump_irq_restore
4853 + * Func: Resume the system state in an architecture-specific way.
4854 + */
4855 +void
4856 +__dump_irq_restore(void)
4857 +{
4858 +       local_irq_disable();
4859 +       __dump_reset_irq_affinity();
4860 +       irq_bh_restore(); 
4861 +}
4862 +
4863 +#if 0
4864 +/* Cheap progress hack.  It estimates pages to write and
4865 + * assumes all pages will go -- so it may get way off.
4866 + * As the progress is not displayed for other architectures, not used at this 
4867 + * moment.
4868 + */
4869 +void
4870 +__dump_progress_add_page(void)
4871 +{
4872 +       unsigned long total_pages = nr_free_pages() + nr_inactive_pages + nr_active_pages;
4873 +       unsigned int percent = (dump_header.dh_num_dump_pages * 100) / total_pages;
4874 +       char buf[30];
4875 +
4876 +       if (percent > last_percent && percent <= 100) {
4877 +               sprintf(buf, "Dump %3d%%     ", percent);
4878 +               ppc64_dump_msg(0x2, buf);
4879 +               last_percent = percent;
4880 +       }
4881 +
4882 +}
4883 +#endif
4884 +
4885 +extern int dump_page_is_ram(unsigned long);
4886 +/*
4887 + * Name: __dump_page_valid()
4888 + * Func: Check if page is valid to dump.
4889 + */
4890 +int
4891 +__dump_page_valid(unsigned long index)
4892 +{
4893 +       if (!pfn_valid(index))
4894 +               return 0;
4895 +
4896 +       return dump_page_is_ram(index);
4897 +}
4898 +
4899 +/*
4900 + * Name: manual_handle_crashdump()
4901 + * Func: Interface for the lkcd dump command. Calls dump_execute()
4902 + */
4903 +int
4904 +manual_handle_crashdump(void)
4905 +{
4906 +       struct pt_regs regs;
4907 +
4908 +       get_current_regs(&regs);
4909 +       dump_execute("manual", &regs);
4910 +       return 0;
4911 +}
4912 +
4913 +/*
4914 + * Name: __dump_clean_irq_state()
4915 + * Func: Clean up from the previous IRQ handling state. Such as oops from 
4916 + *       interrupt handler or bottom half.
4917 + */
4918 +void
4919 +__dump_clean_irq_state(void)
4920 +{
4921 +    return;
4922 +}
4923 Index: linux-2.6.10-base/drivers/dump/dump_i386.c
4924 ===================================================================
4925 --- linux-2.6.10-base.orig/drivers/dump/dump_i386.c     2003-09-02 06:26:13.000000000 +0800
4926 +++ linux-2.6.10-base/drivers/dump/dump_i386.c  2005-05-17 18:52:39.936055208 +0800
4927 @@ -0,0 +1,372 @@
4928 +/*
4929 + * Architecture specific (i386) functions for Linux crash dumps.
4930 + *
4931 + * Created by: Matt Robinson (yakker@sgi.com)
4932 + *
4933 + * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
4934 + *
4935 + * 2.3 kernel modifications by: Matt D. Robinson (yakker@turbolinux.com)
4936 + * Copyright 2000 TurboLinux, Inc.  All rights reserved.
4937 + * 
4938 + * This code is released under version 2 of the GNU GPL.
4939 + */
4940 +
4941 +/*
4942 + * The hooks for dumping the kernel virtual memory to disk are in this
4943 + * file.  Any time a modification is made to the virtual memory mechanism,
4944 + * these routines must be changed to use the new mechanisms.
4945 + */
4946 +#include <linux/init.h>
4947 +#include <linux/types.h>
4948 +#include <linux/kernel.h>
4949 +#include <linux/smp.h>
4950 +#include <linux/fs.h>
4951 +#include <linux/vmalloc.h>
4952 +#include <linux/mm.h>
4953 +#include <linux/dump.h>
4954 +#include "dump_methods.h"
4955 +#include <linux/irq.h>
4956 +
4957 +#include <asm/processor.h>
4958 +#include <asm/e820.h>
4959 +#include <asm/hardirq.h>
4960 +#include <asm/nmi.h>
4961 +
4962 +static __s32        saved_irq_count;   /* saved preempt_count() flags */
4963 +
4964 +static int
4965 +alloc_dha_stack(void)
4966 +{
4967 +       int i;
4968 +       void *ptr;
4969 +       
4970 +       if (dump_header_asm.dha_stack[0])
4971 +               return 0;
4972 +
4973 +       ptr = vmalloc(THREAD_SIZE * num_online_cpus());
4974 +       if (!ptr) {
4975 +               printk("vmalloc for dha_stacks failed\n");
4976 +               return -ENOMEM;
4977 +       }
4978 +
4979 +       for (i = 0; i < num_online_cpus(); i++) {
4980 +               dump_header_asm.dha_stack[i] = (u32)((unsigned long)ptr +
4981 +                               (i * THREAD_SIZE));
4982 +       }
4983 +       return 0;
4984 +}
4985 +
4986 +static int
4987 +free_dha_stack(void) 
4988 +{
4989 +       if (dump_header_asm.dha_stack[0]) {
4990 +               vfree((void *)dump_header_asm.dha_stack[0]);    
4991 +               dump_header_asm.dha_stack[0] = 0;
4992 +       }
4993 +       return 0;
4994 +}
4995 +
4996 +
4997 +void 
4998 +__dump_save_regs(struct pt_regs *dest_regs, const struct pt_regs *regs)
4999 +{
5000 +       *dest_regs = *regs;
5001 +
5002 +       /* In case of panic dumps, we collects regs on entry to panic.
5003 +        * so, we shouldn't 'fix' ssesp here again. But it is hard to
5004 +        * tell just looking at regs whether ssesp need fixing. We make
5005 +        * this decision by looking at xss in regs. If we have better
5006 +        * means to determine that ssesp are valid (by some flag which
5007 +        * tells that we are here due to panic dump), then we can use
5008 +        * that instead of this kludge.
5009 +        */
5010 +       if (!user_mode(regs)) {
5011 +               if ((0xffff & regs->xss) == __KERNEL_DS) 
5012 +                       /* already fixed up */
5013 +                       return;
5014 +               dest_regs->esp = (unsigned long)&(regs->esp);
5015 +               __asm__ __volatile__ ("movw %%ss, %%ax;"
5016 +                       :"=a"(dest_regs->xss));
5017 +       }
5018 +}
5019 +
5020 +void
5021 +__dump_save_context(int cpu, const struct pt_regs *regs, 
5022 +       struct task_struct *tsk)
5023 +{
5024 +       dump_header_asm.dha_smp_current_task[cpu] = (unsigned long)tsk;
5025 +       __dump_save_regs(&dump_header_asm.dha_smp_regs[cpu], regs);
5026 +
5027 +       /* take a snapshot of the stack */
5028 +       /* doing this enables us to tolerate slight drifts on this cpu */
5029 +
5030 +       if (dump_header_asm.dha_stack[cpu]) {
5031 +               memcpy((void *)dump_header_asm.dha_stack[cpu],
5032 +                               STACK_START_POSITION(tsk),
5033 +                               THREAD_SIZE);
5034 +       }
5035 +       dump_header_asm.dha_stack_ptr[cpu] = (unsigned long)(tsk->thread_info);
5036 +}
5037 +
5038 +#ifdef CONFIG_SMP
5039 +extern cpumask_t irq_affinity[];
5040 +extern irq_desc_t irq_desc[];
5041 +extern void dump_send_ipi(void);
5042 +
5043 +static int dump_expect_ipi[NR_CPUS];
5044 +static atomic_t waiting_for_dump_ipi;
5045 +static cpumask_t saved_affinity[NR_IRQS];
5046 +
5047 +extern void stop_this_cpu(void *); /* exported by i386 kernel */
5048 +
5049 +static int
5050 +dump_nmi_callback(struct pt_regs *regs, int cpu) 
5051 +{
5052 +       if (!dump_expect_ipi[cpu])
5053 +               return 0;
5054 +
5055 +       dump_expect_ipi[cpu] = 0;
5056 +       
5057 +       dump_save_this_cpu(regs);
5058 +       atomic_dec(&waiting_for_dump_ipi);
5059 +
5060 + level_changed:
5061 +       switch (dump_silence_level) {
5062 +       case DUMP_HARD_SPIN_CPUS:       /* Spin until dump is complete */
5063 +               while (dump_oncpu) {
5064 +                       barrier();      /* paranoia */
5065 +                       if (dump_silence_level != DUMP_HARD_SPIN_CPUS)
5066 +                               goto level_changed;
5067 +
5068 +                       cpu_relax();    /* kill time nicely */
5069 +               }
5070 +               break;
5071 +
5072 +       case DUMP_HALT_CPUS:            /* Execute halt */
5073 +               stop_this_cpu(NULL);
5074 +               break;
5075 +               
5076 +       case DUMP_SOFT_SPIN_CPUS:
5077 +               /* Mark the task so it spins in schedule */
5078 +               set_tsk_thread_flag(current, TIF_NEED_RESCHED);
5079 +               break;
5080 +       }
5081 +
5082 +       return 1;
5083 +}
5084 +
5085 +/* save registers on other processors */
5086 +void 
5087 +__dump_save_other_cpus(void)
5088 +{
5089 +       int i, cpu = smp_processor_id();
5090 +       int other_cpus = num_online_cpus()-1;
5091 +       
5092 +       if (other_cpus > 0) {
5093 +               atomic_set(&waiting_for_dump_ipi, other_cpus);
5094 +
5095 +               for (i = 0; i < NR_CPUS; i++) {
5096 +                       dump_expect_ipi[i] = (i != cpu && cpu_online(i));
5097 +               }
5098 +
5099 +               /* short circuit normal NMI handling temporarily */
5100 +               set_nmi_callback(dump_nmi_callback);
5101 +               wmb();
5102 +
5103 +               dump_send_ipi();
5104 +               /* may be we dont need to wait for NMI to be processed. 
5105 +                  just write out the header at the end of dumping, if
5106 +                  this IPI is not processed until then, there probably
5107 +                  is a problem and we just fail to capture state of 
5108 +                  other cpus. */
5109 +               while(atomic_read(&waiting_for_dump_ipi) > 0) {
5110 +                       cpu_relax();
5111 +               }
5112 +
5113 +               unset_nmi_callback();
5114 +       }
5115 +}
5116 +
5117 +/*
5118 + * Routine to save the old irq affinities and change affinities of all irqs to
5119 + * the dumping cpu.
5120 + */
5121 +static void 
5122 +set_irq_affinity(void)
5123 +{
5124 +       int i;
5125 +       cpumask_t cpu = CPU_MASK_NONE;
5126 +
5127 +       cpu_set(smp_processor_id(), cpu);
5128 +       memcpy(saved_affinity, irq_affinity, NR_IRQS * sizeof(unsigned long));
5129 +       for (i = 0; i < NR_IRQS; i++) {
5130 +               if (irq_desc[i].handler == NULL)
5131 +                       continue;
5132 +               irq_affinity[i] = cpu;
5133 +               if (irq_desc[i].handler->set_affinity != NULL)
5134 +                       irq_desc[i].handler->set_affinity(i, irq_affinity[i]);
5135 +       }
5136 +}
5137 +
5138 +/*
5139 + * Restore old irq affinities.
5140 + */
5141 +static void 
5142 +reset_irq_affinity(void)
5143 +{
5144 +       int i;
5145 +
5146 +       memcpy(irq_affinity, saved_affinity, NR_IRQS * sizeof(unsigned long));
5147 +       for (i = 0; i < NR_IRQS; i++) {
5148 +               if (irq_desc[i].handler == NULL)
5149 +                       continue;
5150 +               if (irq_desc[i].handler->set_affinity != NULL)
5151 +                       irq_desc[i].handler->set_affinity(i, saved_affinity[i]);
5152 +       }
5153 +}
5154 +
5155 +#else /* !CONFIG_SMP */
5156 +#define set_irq_affinity()     do { } while (0)
5157 +#define reset_irq_affinity()   do { } while (0)
5158 +#define save_other_cpu_states() do { } while (0)
5159 +#endif /* !CONFIG_SMP */
5160 +
5161 +/* 
5162 + * Kludge - dump from interrupt context is unreliable (Fixme)
5163 + *
5164 + * We do this so that softirqs initiated for dump i/o 
5165 + * get processed and we don't hang while waiting for i/o
5166 + * to complete or in any irq synchronization attempt.
5167 + *
5168 + * This is not quite legal of course, as it has the side 
5169 + * effect of making all interrupts & softirqs triggered 
5170 + * while dump is in progress complete before currently 
5171 + * pending softirqs and the currently executing interrupt 
5172 + * code. 
5173 + */
5174 +static inline void
5175 +irq_bh_save(void)
5176 +{
5177 +       saved_irq_count = irq_count();
5178 +       preempt_count() &= ~(HARDIRQ_MASK|SOFTIRQ_MASK);
5179 +}
5180 +
5181 +static inline void
5182 +irq_bh_restore(void)
5183 +{
5184 +       preempt_count() |= saved_irq_count;
5185 +}
5186 +
5187 +/*
5188 + * Name: __dump_irq_enable
5189 + * Func: Reset system so interrupts are enabled.
5190 + *      This is used for dump methods that require interrupts
5191 + *      Eventually, all methods will have interrupts disabled
5192 + *      and this code can be removed.
5193 + *
5194 + *     Change irq affinities
5195 + *     Re-enable interrupts
5196 + */
5197 +int
5198 +__dump_irq_enable(void)
5199 +{
5200 +       set_irq_affinity();
5201 +       irq_bh_save();
5202 +       local_irq_enable();
5203 +       return 0;
5204 +}
5205 +
5206 +/*
5207 + * Name: __dump_irq_restore
5208 + * Func: Resume the system state in an architecture-specific way.
5209 +
5210 + */
5211 +void 
5212 +__dump_irq_restore(void)
5213 +{
5214 +       local_irq_disable();
5215 +       reset_irq_affinity();
5216 +       irq_bh_restore();
5217 +}
5218 +
5219 +/*
5220 + * Name: __dump_configure_header()
5221 + * Func: Meant to fill in arch specific header fields except per-cpu state
5222 + * already captured via __dump_save_context for all CPUs.
5223 + */
5224 +int
5225 +__dump_configure_header(const struct pt_regs *regs)
5226 +{
5227 +       return (0);
5228 +}
5229 +
5230 +/*
5231 + * Name: __dump_init()
5232 + * Func: Initialize the dumping routine process.
5233 + */
5234 +void
5235 +__dump_init(uint64_t local_memory_start)
5236 +{
5237 +       return;
5238 +}
5239 +
5240 +/*
5241 + * Name: __dump_open()
5242 + * Func: Open the dump device (architecture specific).
5243 + */
5244 +void
5245 +__dump_open(void)
5246 +{
5247 +       alloc_dha_stack();
5248 +}
5249 +
5250 +/*
5251 + * Name: __dump_cleanup()
5252 + * Func: Free any architecture specific data structures. This is called
5253 + *       when the dump module is being removed.
5254 + */
5255 +void
5256 +__dump_cleanup(void)
5257 +{
5258 +       free_dha_stack();
5259 +}
5260 +
5261 +extern int pfn_is_ram(unsigned long);
5262 +
5263 +/*
5264 + * Name: __dump_page_valid()
5265 + * Func: Check if page is valid to dump.
5266 + */ 
5267 +int 
5268 +__dump_page_valid(unsigned long index)
5269 +{
5270 +       if (!pfn_valid(index))
5271 +               return 0;
5272 +
5273 +       return pfn_is_ram(index);
5274 +}
5275 +
5276 +/* 
5277 + * Name: manual_handle_crashdump()
5278 + * Func: Interface for the lkcd dump command. Calls dump_execute()
5279 + */
5280 +int
5281 +manual_handle_crashdump(void) {
5282 +
5283 +       struct pt_regs regs;
5284 +       
5285 +       get_current_regs(&regs);
5286 +       dump_execute("manual", &regs);
5287 +       return 0;
5288 +}
5289 +
5290 +/*
5291 + * Name: __dump_clean_irq_state()
5292 + * Func: Clean up from the previous IRQ handling state. Such as oops from 
5293 + *       interrupt handler or bottom half.
5294 + */
5295 +void
5296 +__dump_clean_irq_state(void)
5297 +{
5298 +    return;
5299 +}
5300 Index: linux-2.6.10-base/drivers/dump/dump_filters.c
5301 ===================================================================
5302 --- linux-2.6.10-base.orig/drivers/dump/dump_filters.c  2003-09-02 06:26:13.000000000 +0800
5303 +++ linux-2.6.10-base/drivers/dump/dump_filters.c       2005-05-17 18:52:39.936055208 +0800
5304 @@ -0,0 +1,143 @@
5305 +/*
5306 + * Default filters to select data to dump for various passes.
5307 + *
5308 + * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
5309 + *     Split and rewrote default dump selection logic to generic dump 
5310 + *     method interfaces 
5311 + * Derived from a portion of dump_base.c created by 
5312 + *     Matt Robinson <yakker@sourceforge.net>)
5313 + *
5314 + * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
5315 + * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
5316 + * Copyright (C) 2002 International Business Machines Corp. 
5317 + *
5318 + * Used during single-stage dumping and during stage 1 of the 2-stage scheme
5319 + * (Stage 2 of the 2-stage scheme uses the fully transparent filters
5320 + * i.e. passthru filters in dump_overlay.c)
5321 + *
5322 + * Future: Custom selective dump may involve a different set of filters.
5323 + *
5324 + * This code is released under version 2 of the GNU GPL.
5325 + */
5326 +
5327 +#include <linux/kernel.h>
5328 +#include <linux/bootmem.h>
5329 +#include <linux/mm.h>
5330 +#include <linux/slab.h>
5331 +#include <linux/dump.h>
5332 +#include "dump_methods.h"
5333 +
5334 +#define DUMP_PFN_SAFETY_MARGIN  1024  /* 4 MB */
5335 +static unsigned long bootmap_pages;
5336 +
5337 +/* Copied from mm/bootmem.c - FIXME */
5338 +/* return the number of _pages_ that will be allocated for the boot bitmap */
5339 +void dump_calc_bootmap_pages (void)
5340 +{
5341 +       unsigned long mapsize;
5342 +       unsigned long pages = num_physpages;
5343 +
5344 +       mapsize = (pages+7)/8;
5345 +       mapsize = (mapsize + ~PAGE_MASK) & PAGE_MASK;
5346 +       mapsize >>= PAGE_SHIFT;
5347 +       bootmap_pages = mapsize + DUMP_PFN_SAFETY_MARGIN + 1;
5348 +}
5349 +
5350 +
5351 +/* temporary */
5352 +extern unsigned long min_low_pfn;
5353 +
5354 +
5355 +int dump_low_page(struct page *p)
5356 +{
5357 +       return ((page_to_pfn(p) >= min_low_pfn) &&
5358 +               (page_to_pfn(p) < (min_low_pfn + bootmap_pages)));
5359 +}
5360 +
5361 +static inline int kernel_page(struct page *p)
5362 +{
5363 +       /* FIXME: Need to exclude hugetlb pages. Clue: reserved but inuse */
5364 +       return (PageReserved(p) && !PageInuse(p)) || (!PageLRU(p) && PageInuse(p));
5365 +}
5366 +
5367 +static inline int user_page(struct page *p)
5368 +{
5369 +       return PageInuse(p) && (!PageReserved(p) && PageLRU(p));
5370 +}
5371 +
5372 +static inline int unreferenced_page(struct page *p)
5373 +{
5374 +       return !PageInuse(p) && !PageReserved(p);
5375 +}
5376 +
5377 +
5378 +/* loc marks the beginning of a range of pages */
5379 +int dump_filter_kernpages(int pass, unsigned long loc, unsigned long sz)
5380 +{
5381 +       struct page *page = (struct page *)loc;
5382 +       /* if any of the pages is a kernel page, select this set */     
5383 +       while (sz) {
5384 +               if (dump_low_page(page) || kernel_page(page))
5385 +                       return 1;
5386 +               sz -= PAGE_SIZE;
5387 +               page++;
5388 +       }       
5389 +       return 0;
5390 +}
5391 +
5392 +
5393 +/* loc marks the beginning of a range of pages */
5394 +int dump_filter_userpages(int pass, unsigned long loc, unsigned long sz)
5395 +{
5396 +       struct page *page = (struct page *)loc;
5397 +       int ret = 0;
5398 +       /* select if the set has any user page, and no kernel pages  */ 
5399 +       while (sz) {
5400 +               if (user_page(page) && !dump_low_page(page)) {
5401 +                       ret = 1;
5402 +               } else if (kernel_page(page) || dump_low_page(page)) {
5403 +                       return 0;
5404 +               }
5405 +               page++;
5406 +               sz -= PAGE_SIZE;
5407 +       }       
5408 +       return ret;
5409 +}
5410 +
5411 +
5412 +
5413 +/* loc marks the beginning of a range of pages */
5414 +int dump_filter_unusedpages(int pass, unsigned long loc, unsigned long sz)
5415 +{
5416 +       struct page *page = (struct page *)loc;
5417 +
5418 +       /* select if the set does not have any used pages  */   
5419 +       while (sz) {
5420 +               if (!unreferenced_page(page) || dump_low_page(page)) {
5421 +                       return 0;
5422 +               }
5423 +               page++;
5424 +               sz -= PAGE_SIZE;
5425 +       }       
5426 +       return 1;
5427 +}
5428 +
5429 +/* dummy: last (non-existent) pass */
5430 +int dump_filter_none(int pass, unsigned long loc, unsigned long sz)
5431 +{
5432 +       return 0;
5433 +}
5434 +
5435 +/* TBD: resolve level bitmask ? */
5436 +struct dump_data_filter dump_filter_table[] = {
5437 +       { .name = "kern", .selector = dump_filter_kernpages, 
5438 +               .level_mask = DUMP_MASK_KERN},
5439 +       { .name = "user", .selector = dump_filter_userpages, 
5440 +               .level_mask = DUMP_MASK_USED},
5441 +       { .name = "unused", .selector = dump_filter_unusedpages, 
5442 +               .level_mask = DUMP_MASK_UNUSED},
5443 +       { .name = "none", .selector = dump_filter_none, 
5444 +               .level_mask = DUMP_MASK_REST},
5445 +       { .name = "", .selector = NULL, .level_mask = 0}
5446 +};
5447 +
5448 Index: linux-2.6.10-base/drivers/dump/dump_memdev.c
5449 ===================================================================
5450 --- linux-2.6.10-base.orig/drivers/dump/dump_memdev.c   2003-09-02 06:26:13.000000000 +0800
5451 +++ linux-2.6.10-base/drivers/dump/dump_memdev.c        2005-05-17 18:52:39.937055056 +0800
5452 @@ -0,0 +1,655 @@
5453 +/*
5454 + * Implements the dump driver interface for saving a dump in available
5455 + * memory areas. The saved pages may be written out to persistent storage  
5456 + * after a soft reboot.
5457 + *
5458 + * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
5459 + *
5460 + * Copyright (C) 2002 International Business Machines Corp. 
5461 + *
5462 + * This code is released under version 2 of the GNU GPL.
5463 + *
5464 + * The approach of tracking pages containing saved dump using map pages 
5465 + * allocated as needed has been derived from the Mission Critical Linux 
5466 + * mcore dump implementation. 
5467 + *
5468 + * Credits and a big thanks for letting the lkcd project make use of 
5469 + * the excellent piece of work and also helping with clarifications 
5470 + * and tips along the way are due to:
5471 + *     Dave Winchell <winchell@mclx.com> (primary author of mcore)
5472 + *     Jeff Moyer <moyer@mclx.com>
5473 + *     Josh Huber <huber@mclx.com>
5474 + *
5475 + * For those familiar with the mcore code, the main differences worth
5476 + * noting here (besides the dump device abstraction) result from enabling 
5477 + * "high" memory pages (pages not permanently mapped in the kernel 
5478 + * address space) to be used for saving dump data (because of which a 
5479 + * simple virtual address based linked list cannot be used anymore for 
5480 + * managing free pages), an added level of indirection for faster 
5481 + * lookups during the post-boot stage, and the idea of pages being 
5482 + * made available as they get freed up while dump to memory progresses 
5483 + * rather than one time before starting the dump. The last point enables 
5484 + * a full memory snapshot to be saved starting with an initial set of 
5485 + * bootstrap pages given a good compression ratio. (See dump_overlay.c)
5486 + *
5487 + */
5488 +
5489 +/*
5490 + * -----------------MEMORY LAYOUT ------------------
5491 + * The memory space consists of a set of discontiguous pages, and
5492 + * discontiguous map pages as well, rooted in a chain of indirect
5493 + * map pages (also discontiguous). Except for the indirect maps 
5494 + * (which must be preallocated in advance), the rest of the pages 
5495 + * could be in high memory.
5496 + *
5497 + * root
5498 + *  |    ---------    --------        --------
5499 + *  -->  | .  . +|--->|  .  +|------->| . .  |       indirect 
5500 + *       --|--|---    ---|----        --|-|---      maps
5501 + *         |  |          |                     | |     
5502 + *    ------  ------   -------     ------ -------
5503 + *    | .  |  | .  |   | .  . |    | .  | |  . . |   maps 
5504 + *    --|---  --|---   --|--|--    --|--- ---|-|--
5505 + *     page    page    page page   page   page page  data
5506 + *                                                   pages
5507 + *
5508 + * Writes to the dump device happen sequentially in append mode.
5509 + * The main reason for the existence of the indirect map is
5510 + * to enable a quick way to lookup a specific logical offset in
5511 + * the saved data post-soft-boot, e.g. to writeout pages
5512 + * with more critical data first, even though such pages
5513 + * would have been compressed and copied last, being the lowest
5514 + * ranked candidates for reuse due to their criticality.
5515 + * (See dump_overlay.c)
5516 + */
5517 +#include <linux/mm.h>
5518 +#include <linux/highmem.h>
5519 +#include <linux/bootmem.h>
5520 +#include <linux/dump.h>
5521 +#include "dump_methods.h"
5522 +
5523 +#define DUMP_MAP_SZ (PAGE_SIZE / sizeof(unsigned long)) /* direct map size */
5524 +#define DUMP_IND_MAP_SZ        DUMP_MAP_SZ - 1  /* indirect map size */
5525 +#define DUMP_NR_BOOTSTRAP      64  /* no of bootstrap pages */
5526 +
5527 +extern int dump_low_page(struct page *);
5528 +
5529 +/* check if the next entry crosses a page boundary */
5530 +static inline int is_last_map_entry(unsigned long *map)
5531 +{
5532 +       unsigned long addr = (unsigned long)(map + 1);
5533 +
5534 +       return (!(addr & (PAGE_SIZE - 1)));
5535 +}
5536 +
5537 +/* Todo: should have some validation checks */
5538 +/* The last entry in the indirect map points to the next indirect map */
5539 +/* Indirect maps are referred to directly by virtual address */
5540 +static inline unsigned long *next_indirect_map(unsigned long *map)
5541 +{
5542 +       return (unsigned long *)map[DUMP_IND_MAP_SZ];
5543 +}
5544 +
5545 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
5546 +/* Called during early bootup - fixme: make this __init */
5547 +void dump_early_reserve_map(struct dump_memdev *dev)
5548 +{
5549 +       unsigned long *map1, *map2;
5550 +       loff_t off = 0, last = dev->last_used_offset >> PAGE_SHIFT;
5551 +       int i, j;
5552 +       
5553 +       printk("Reserve bootmap space holding previous dump of %lld pages\n",
5554 +                       last);
5555 +       map1= (unsigned long *)dev->indirect_map_root;
5556 +
5557 +       while (map1 && (off < last)) {
5558 +#ifdef CONFIG_X86_64
5559 +               reserve_bootmem_node(NODE_DATA(0), virt_to_phys((void *)map1),
5560 +                                PAGE_SIZE);
5561 +#else
5562 +               reserve_bootmem(virt_to_phys((void *)map1), PAGE_SIZE);
5563 +#endif
5564 +               for (i=0;  (i < DUMP_MAP_SZ - 1) && map1[i] && (off < last); 
5565 +                       i++, off += DUMP_MAP_SZ) {
5566 +                       pr_debug("indirect map[%d] = 0x%lx\n", i, map1[i]);
5567 +                       if (map1[i] >= max_low_pfn)
5568 +                               continue;
5569 +#ifdef CONFIG_X86_64
5570 +                       reserve_bootmem_node(NODE_DATA(0), 
5571 +                                       map1[i] << PAGE_SHIFT, PAGE_SIZE);
5572 +#else
5573 +                       reserve_bootmem(map1[i] << PAGE_SHIFT, PAGE_SIZE);
5574 +#endif
5575 +                       map2 = pfn_to_kaddr(map1[i]);
5576 +                       for (j = 0 ; (j < DUMP_MAP_SZ) && map2[j] && 
5577 +                               (off + j < last); j++) {
5578 +                               pr_debug("\t map[%d][%d] = 0x%lx\n", i, j, 
5579 +                                       map2[j]);
5580 +                               if (map2[j] < max_low_pfn) {
5581 +#ifdef CONFIG_X86_64
5582 +                                       reserve_bootmem_node(NODE_DATA(0),
5583 +                                               map2[j] << PAGE_SHIFT,
5584 +                                               PAGE_SIZE);
5585 +#else
5586 +                                       reserve_bootmem(map2[j] << PAGE_SHIFT,
5587 +                                               PAGE_SIZE);
5588 +#endif
5589 +                               }
5590 +                       }
5591 +               }
5592 +               map1 = next_indirect_map(map1);
5593 +       }
5594 +       dev->nr_free = 0; /* these pages don't belong to this boot */
5595 +}
5596 +#endif
5597 +
5598 +/* mark dump pages so that they aren't used by this kernel */
5599 +void dump_mark_map(struct dump_memdev *dev)
5600 +{
5601 +       unsigned long *map1, *map2;
5602 +       loff_t off = 0, last = dev->last_used_offset >> PAGE_SHIFT;
5603 +       struct page *page;
5604 +       int i, j;
5605 +       
5606 +       printk("Dump: marking pages in use by previous dump\n");
5607 +       map1= (unsigned long *)dev->indirect_map_root;
5608 +
5609 +       while (map1 && (off < last)) {
5610 +               page = virt_to_page(map1);      
5611 +               set_page_count(page, 1);
5612 +               for (i=0;  (i < DUMP_MAP_SZ - 1) && map1[i] && (off < last); 
5613 +                       i++, off += DUMP_MAP_SZ) {
5614 +                       pr_debug("indirect map[%d] = 0x%lx\n", i, map1[i]);
5615 +                       page = pfn_to_page(map1[i]);
5616 +                       set_page_count(page, 1);
5617 +                       map2 = kmap_atomic(page, KM_DUMP);
5618 +                       for (j = 0 ; (j < DUMP_MAP_SZ) && map2[j] && 
5619 +                               (off + j < last); j++) {
5620 +                               pr_debug("\t map[%d][%d] = 0x%lx\n", i, j, 
5621 +                                       map2[j]);
5622 +                               page = pfn_to_page(map2[j]);
5623 +                               set_page_count(page, 1);
5624 +                       }
5625 +               }
5626 +               map1 = next_indirect_map(map1);
5627 +       }
5628 +}
5629 +       
5630 +
5631 +/* 
5632 + * Given a logical offset into the mem device lookup the 
5633 + * corresponding page 
5634 + *     loc is specified in units of pages 
5635 + * Note: affects curr_map (even in the case where lookup fails)
5636 + */
5637 +struct page *dump_mem_lookup(struct dump_memdev *dump_mdev, unsigned long loc)
5638 +{
5639 +       unsigned long *map;
5640 +       unsigned long i, index = loc / DUMP_MAP_SZ;
5641 +       struct page *page = NULL;
5642 +       unsigned long curr_pfn, curr_map, *curr_map_ptr = NULL;
5643 +
5644 +       map = (unsigned long *)dump_mdev->indirect_map_root;
5645 +       if (!map) 
5646 +               return NULL;
5647 +       if (loc > dump_mdev->last_offset >> PAGE_SHIFT)
5648 +               return NULL;
5649 +
5650 +       /* 
5651 +        * first locate the right indirect map 
5652 +        * in the chain of indirect maps 
5653 +        */
5654 +       for (i = 0; i + DUMP_IND_MAP_SZ < index ; i += DUMP_IND_MAP_SZ) {
5655 +               if (!(map = next_indirect_map(map))) 
5656 +                       return NULL;
5657 +       }
5658 +       /* then the right direct map */
5659 +       /* map entries are referred to by page index */
5660 +       if ((curr_map = map[index - i])) {
5661 +               page = pfn_to_page(curr_map);
5662 +               /* update the current traversal index */
5663 +               /* dump_mdev->curr_map = &map[index - i];*/
5664 +               curr_map_ptr = &map[index - i];
5665 +       }
5666 +
5667 +       if (page)
5668 +               map = kmap_atomic(page, KM_DUMP);
5669 +       else 
5670 +               return NULL;
5671 +
5672 +       /* and finally the right entry therein */
5673 +       /* data pages are referred to by page index */
5674 +       i = index * DUMP_MAP_SZ;
5675 +       if ((curr_pfn = map[loc - i])) {
5676 +               page = pfn_to_page(curr_pfn);
5677 +               dump_mdev->curr_map = curr_map_ptr;
5678 +               dump_mdev->curr_map_offset = loc - i;
5679 +               dump_mdev->ddev.curr_offset = loc << PAGE_SHIFT;
5680 +       } else {
5681 +               page = NULL;
5682 +       }
5683 +       kunmap_atomic(map, KM_DUMP);
5684 +
5685 +       return page;
5686 +}
5687 +                       
5688 +/* 
5689 + * Retrieves a pointer to the next page in the dump device 
5690 + * Used during the lookup pass post-soft-reboot 
5691 + */
5692 +struct page *dump_mem_next_page(struct dump_memdev *dev)
5693 +{
5694 +       unsigned long i; 
5695 +       unsigned long *map;     
5696 +       struct page *page = NULL;
5697 +
5698 +       if (dev->ddev.curr_offset + PAGE_SIZE >= dev->last_offset) {
5699 +               return NULL;
5700 +       }
5701 +
5702 +       if ((i = (unsigned long)(++dev->curr_map_offset)) >= DUMP_MAP_SZ) {
5703 +               /* move to next map */  
5704 +               if (is_last_map_entry(++dev->curr_map)) {
5705 +                       /* move to the next indirect map page */
5706 +                       printk("dump_mem_next_page: go to next indirect map\n");
5707 +                       dev->curr_map = (unsigned long *)*dev->curr_map;
5708 +                       if (!dev->curr_map)
5709 +                               return NULL;
5710 +               }
5711 +               i = dev->curr_map_offset = 0;
5712 +               pr_debug("dump_mem_next_page: next map 0x%lx, entry 0x%lx\n",
5713 +                               dev->curr_map, *dev->curr_map);
5714 +
5715 +       };
5716 +       
5717 +       if (*dev->curr_map) {
5718 +               map = kmap_atomic(pfn_to_page(*dev->curr_map), KM_DUMP);
5719 +               if (map[i])
5720 +                       page = pfn_to_page(map[i]);
5721 +               kunmap_atomic(map, KM_DUMP);
5722 +               dev->ddev.curr_offset += PAGE_SIZE;
5723 +       };
5724 +
5725 +       return page;
5726 +}
5727 +
5728 +/* Copied from dump_filters.c */
5729 +static inline int kernel_page(struct page *p)
5730 +{
5731 +       /* FIXME: Need to exclude hugetlb pages. Clue: reserved but inuse */
5732 +       return (PageReserved(p) && !PageInuse(p)) || (!PageLRU(p) && PageInuse(p));
5733 +}
5734 +
5735 +static inline int user_page(struct page *p)
5736 +{
5737 +       return PageInuse(p) && (!PageReserved(p) && PageLRU(p));
5738 +}
5739 +
5740 +int dump_reused_by_boot(struct page *page)
5741 +{
5742 +       /* Todo
5743 +        * Checks:
5744 +        * if PageReserved 
5745 +        * if < __end + bootmem_bootmap_pages for this boot + allowance 
5746 +        * if overwritten by initrd (how to check ?)
5747 +        * Also, add more checks in early boot code
5748 +        * e.g. bootmem bootmap alloc verify not overwriting dump, and if
5749 +        * so then realloc or move the dump pages out accordingly.
5750 +        */
5751 +
5752 +       /* Temporary proof of concept hack, avoid overwriting kern pages */
5753 +
5754 +       return (kernel_page(page) || dump_low_page(page) || user_page(page));
5755 +}
5756 +
5757 +
5758 +/* Uses the free page passed in to expand available space */
5759 +int dump_mem_add_space(struct dump_memdev *dev, struct page *page)
5760 +{
5761 +       struct page *map_page;
5762 +       unsigned long *map;     
5763 +       unsigned long i; 
5764 +
5765 +       if (!dev->curr_map)
5766 +               return -ENOMEM; /* must've exhausted indirect map */
5767 +
5768 +       if (!*dev->curr_map || dev->curr_map_offset >= DUMP_MAP_SZ) {
5769 +               /* add map space */
5770 +               *dev->curr_map = page_to_pfn(page);
5771 +               dev->curr_map_offset = 0;
5772 +               return 0;
5773 +       }
5774 +
5775 +       /* add data space */
5776 +       i = dev->curr_map_offset;
5777 +       map_page = pfn_to_page(*dev->curr_map);
5778 +       map = (unsigned long *)kmap_atomic(map_page, KM_DUMP);
5779 +       map[i] = page_to_pfn(page);
5780 +       kunmap_atomic(map, KM_DUMP);
5781 +       dev->curr_map_offset = ++i;
5782 +       dev->last_offset += PAGE_SIZE;
5783 +       if (i >= DUMP_MAP_SZ) {
5784 +               /* move to next map */
5785 +               if (is_last_map_entry(++dev->curr_map)) {
5786 +                       /* move to the next indirect map page */
5787 +                       pr_debug("dump_mem_add_space: using next"
5788 +                       "indirect map\n");
5789 +                       dev->curr_map = (unsigned long *)*dev->curr_map;
5790 +               }
5791 +       }               
5792 +       return 0;
5793 +}
5794 +
5795 +
5796 +/* Caution: making a dest page invalidates existing contents of the page */
5797 +int dump_check_and_free_page(struct dump_memdev *dev, struct page *page)
5798 +{
5799 +       int err = 0;
5800 +
5801 +       /* 
5802 +        * the page can be used as a destination only if we are sure
5803 +        * it won't get overwritten by the soft-boot, and is not
5804 +        * critical for us right now.
5805 +        */
5806 +       if (dump_reused_by_boot(page))
5807 +               return 0;
5808 +
5809 +       if ((err = dump_mem_add_space(dev, page))) {
5810 +               printk("Warning: Unable to extend memdev space. Err %d\n",
5811 +               err);
5812 +               return 0;
5813 +       }
5814 +
5815 +       dev->nr_free++;
5816 +       return 1;
5817 +}
5818 +
5819 +
5820 +/* Set up the initial maps and bootstrap space  */
5821 +/* Must be called only after any previous dump is written out */
5822 +int dump_mem_open(struct dump_dev *dev, unsigned long devid)
5823 +{
5824 +       struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
5825 +       unsigned long nr_maps, *map, *prev_map = &dump_mdev->indirect_map_root;
5826 +       void *addr;
5827 +       struct page *page;
5828 +       unsigned long i = 0;
5829 +       int err = 0;
5830 +
5831 +       /* Todo: sanity check for unwritten previous dump */
5832 +
5833 +       /* allocate pages for indirect map (non highmem area) */
5834 +       nr_maps = num_physpages / DUMP_MAP_SZ; /* maps to cover entire mem */
5835 +       for (i = 0; i < nr_maps; i += DUMP_IND_MAP_SZ) {
5836 +               if (!(map = (unsigned long *)dump_alloc_mem(PAGE_SIZE))) {
5837 +                       printk("Unable to alloc indirect map %ld\n", 
5838 +                               i / DUMP_IND_MAP_SZ);
5839 +                       return -ENOMEM;
5840 +               }
5841 +               clear_page(map);
5842 +               *prev_map = (unsigned long)map;
5843 +               prev_map = &map[DUMP_IND_MAP_SZ];
5844 +       };
5845 +               
5846 +       dump_mdev->curr_map = (unsigned long *)dump_mdev->indirect_map_root;
5847 +       dump_mdev->curr_map_offset = 0; 
5848 +
5849 +       /* 
5850 +        * allocate a few bootstrap pages: at least 1 map and 1 data page
5851 +        * plus enough to save the dump header
5852 +        */
5853 +       i = 0;
5854 +       do {
5855 +               if (!(addr = dump_alloc_mem(PAGE_SIZE))) {
5856 +                       printk("Unable to alloc bootstrap page %ld\n", i);
5857 +                       return -ENOMEM;
5858 +               }
5859 +
5860 +               page = virt_to_page(addr);
5861 +               if (dump_low_page(page)) {
5862 +                       dump_free_mem(addr);
5863 +                       continue;
5864 +               }
5865 +
5866 +               if (dump_mem_add_space(dump_mdev, page)) {
5867 +                       printk("Warning: Unable to extend memdev "
5868 +                                       "space. Err %d\n", err);
5869 +                       dump_free_mem(addr);
5870 +                       continue;
5871 +               }
5872 +               i++;
5873 +       } while (i < DUMP_NR_BOOTSTRAP);
5874 +
5875 +       printk("dump memdev init: %ld maps, %ld bootstrap pgs, %ld free pgs\n",
5876 +               nr_maps, i, dump_mdev->last_offset >> PAGE_SHIFT);
5877 +       
5878 +       dump_mdev->last_bs_offset = dump_mdev->last_offset;
5879 +
5880 +       return 0;
5881 +}
5882 +
5883 +/* Releases all pre-alloc'd pages */
5884 +int dump_mem_release(struct dump_dev *dev)
5885 +{
5886 +       struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
5887 +       struct page *page, *map_page;
5888 +       unsigned long *map, *prev_map;
5889 +       void *addr;
5890 +       int i;
5891 +
5892 +       if (!dump_mdev->nr_free)
5893 +               return 0;
5894 +
5895 +       pr_debug("dump_mem_release\n");
5896 +       page = dump_mem_lookup(dump_mdev, 0);
5897 +       for (i = 0; page && (i < DUMP_NR_BOOTSTRAP - 1); i++) {
5898 +               if (PageHighMem(page))
5899 +                       break;
5900 +               addr = page_address(page);
5901 +               if (!addr) {
5902 +                       printk("page_address(%p) = NULL\n", page);
5903 +                       break;
5904 +               }
5905 +               pr_debug("Freeing page at 0x%lx\n", addr); 
5906 +               dump_free_mem(addr);
5907 +               if (dump_mdev->curr_map_offset >= DUMP_MAP_SZ - 1) {
5908 +                       map_page = pfn_to_page(*dump_mdev->curr_map);
5909 +                       if (PageHighMem(map_page))
5910 +                               break;
5911 +                       page = dump_mem_next_page(dump_mdev);
5912 +                       addr = page_address(map_page);
5913 +                       if (!addr) {
5914 +                               printk("page_address(%p) = NULL\n", 
5915 +                                       map_page);
5916 +                               break;
5917 +                       }
5918 +                       pr_debug("Freeing map page at 0x%lx\n", addr);
5919 +                       dump_free_mem(addr);
5920 +                       i++;
5921 +               } else {
5922 +                       page = dump_mem_next_page(dump_mdev);
5923 +               }
5924 +       }
5925 +
5926 +       /* now for the last used bootstrap page used as a map page */
5927 +       if ((i < DUMP_NR_BOOTSTRAP) && (*dump_mdev->curr_map)) {
5928 +               map_page = pfn_to_page(*dump_mdev->curr_map);
5929 +               if ((map_page) && !PageHighMem(map_page)) {
5930 +                       addr = page_address(map_page);
5931 +                       if (!addr) {
5932 +                               printk("page_address(%p) = NULL\n", map_page);
5933 +                       } else {
5934 +                               pr_debug("Freeing map page at 0x%lx\n", addr);
5935 +                               dump_free_mem(addr);
5936 +                               i++;
5937 +                       }
5938 +               }
5939 +       }
5940 +
5941 +       printk("Freed %d bootstrap pages\n", i);
5942 +
5943 +       /* free the indirect maps */
5944 +       map = (unsigned long *)dump_mdev->indirect_map_root;
5945 +
5946 +       i = 0;
5947 +       while (map) {
5948 +               prev_map = map;
5949 +               map = next_indirect_map(map);
5950 +               dump_free_mem(prev_map);
5951 +               i++;
5952 +       }
5953 +
5954 +       printk("Freed %d indirect map(s)\n", i);
5955 +
5956 +       /* Reset the indirect map */
5957 +       dump_mdev->indirect_map_root = 0;
5958 +       dump_mdev->curr_map = 0;
5959 +
5960 +       /* Reset the free list */
5961 +       dump_mdev->nr_free = 0;
5962 +
5963 +       dump_mdev->last_offset = dump_mdev->ddev.curr_offset = 0;
5964 +       dump_mdev->last_used_offset = 0;
5965 +       dump_mdev->curr_map = NULL;
5966 +       dump_mdev->curr_map_offset = 0;
5967 +       return 0;
5968 +}
5969 +
5970 +/*
5971 + * Long term:
5972 + * It is critical for this to be very strict. Cannot afford
5973 + * to have anything running and accessing memory while we overwrite 
5974 + * memory (potential risk of data corruption).
5975 + * If in doubt (e.g if a cpu is hung and not responding) just give
5976 + * up and refuse to proceed with this scheme.
5977 + *
5978 + * Note: I/O will only happen after soft-boot/switchover, so we can 
5979 + * safely disable interrupts and force stop other CPUs if this is
5980 + * going to be a disruptive dump, no matter what they
5981 + * are in the middle of.
5982 + */
5983 +/* 
5984 + * ATM Most of this is already taken care of in the nmi handler 
5985 + * We may halt the cpus rightaway if we know this is going to be disruptive 
5986 + * For now, since we've limited ourselves to overwriting free pages we
5987 + * aren't doing much here. Eventually, we'd have to wait to make sure other
5988 + * cpus aren't using memory we could be overwriting
5989 + */
5990 +int dump_mem_silence(struct dump_dev *dev)
5991 +{
5992 +       struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
5993 +
5994 +       if (dump_mdev->last_offset > dump_mdev->last_bs_offset) {
5995 +               /* prefer to run lkcd config & start with a clean slate */
5996 +               return -EEXIST;
5997 +       }
5998 +       return 0;
5999 +}
6000 +
6001 +extern int dump_overlay_resume(void);
6002 +
6003 +/* Trigger the next stage of dumping */
6004 +int dump_mem_resume(struct dump_dev *dev)
6005 +{
6006 +       dump_overlay_resume(); 
6007 +       return 0;
6008 +}
6009 +
6010 +/* 
6011 + * Allocate mem dev pages as required and copy buffer contents into it.
6012 + * Fails if the no free pages are available
6013 + * Keeping it simple and limited for starters (can modify this over time)
6014 + *  Does not handle holes or a sparse layout
6015 + *  Data must be in multiples of PAGE_SIZE
6016 + */
6017 +int dump_mem_write(struct dump_dev *dev, void *buf, unsigned long len)
6018 +{
6019 +       struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
6020 +       struct page *page;
6021 +       unsigned long n = 0;
6022 +       void *addr;
6023 +       unsigned long *saved_curr_map, saved_map_offset;
6024 +       int ret = 0;
6025 +
6026 +       pr_debug("dump_mem_write: offset 0x%llx, size %ld\n", 
6027 +               dev->curr_offset, len);
6028 +
6029 +       if (dev->curr_offset + len > dump_mdev->last_offset)  {
6030 +               printk("Out of space to write\n");
6031 +               return -ENOSPC;
6032 +       }
6033 +       
6034 +       if ((len & (PAGE_SIZE - 1)) || (dev->curr_offset & (PAGE_SIZE - 1)))
6035 +               return -EINVAL; /* not aligned in units of page size */
6036 +
6037 +       saved_curr_map = dump_mdev->curr_map;
6038 +       saved_map_offset = dump_mdev->curr_map_offset;
6039 +       page = dump_mem_lookup(dump_mdev, dev->curr_offset >> PAGE_SHIFT);
6040 +
6041 +       for (n = len; (n > 0) && page; n -= PAGE_SIZE, buf += PAGE_SIZE ) {
6042 +               addr = kmap_atomic(page, KM_DUMP);
6043 +               /* memset(addr, 'x', PAGE_SIZE); */
6044 +               memcpy(addr, buf, PAGE_SIZE);
6045 +               kunmap_atomic(addr, KM_DUMP);
6046 +               /* dev->curr_offset += PAGE_SIZE; */
6047 +               page = dump_mem_next_page(dump_mdev);
6048 +       }
6049 +
6050 +       dump_mdev->curr_map = saved_curr_map;
6051 +       dump_mdev->curr_map_offset = saved_map_offset;
6052 +
6053 +       if (dump_mdev->last_used_offset < dev->curr_offset)
6054 +               dump_mdev->last_used_offset = dev->curr_offset;
6055 +
6056 +       return (len - n) ? (len - n) : ret ;
6057 +}
6058 +
6059 +/* dummy - always ready */
6060 +int dump_mem_ready(struct dump_dev *dev, void *buf)
6061 +{
6062 +       return 0;
6063 +}
6064 +
6065 +/* 
6066 + * Should check for availability of space to write upto the offset 
6067 + * affects only the curr_offset; last_offset untouched 
6068 + * Keep it simple: Only allow multiples of PAGE_SIZE for now 
6069 + */
6070 +int dump_mem_seek(struct dump_dev *dev, loff_t offset)
6071 +{
6072 +       struct dump_memdev *dump_mdev = DUMP_MDEV(dev);
6073 +
6074 +       if (offset & (PAGE_SIZE - 1))
6075 +               return -EINVAL; /* allow page size units only for now */
6076 +       
6077 +       /* Are we exceeding available space ? */
6078 +       if (offset > dump_mdev->last_offset) {
6079 +               printk("dump_mem_seek failed for offset 0x%llx\n",
6080 +                       offset);
6081 +               return -ENOSPC; 
6082 +       }
6083 +
6084 +       dump_mdev->ddev.curr_offset = offset;
6085 +       return 0;
6086 +}
6087 +
6088 +struct dump_dev_ops dump_memdev_ops = {
6089 +       .open           = dump_mem_open,
6090 +       .release        = dump_mem_release,
6091 +       .silence        = dump_mem_silence,
6092 +       .resume         = dump_mem_resume,
6093 +       .seek           = dump_mem_seek,
6094 +       .write          = dump_mem_write,
6095 +       .read           = NULL, /* not implemented at the moment */
6096 +       .ready          = dump_mem_ready
6097 +};
6098 +
6099 +static struct dump_memdev default_dump_memdev = {
6100 +       .ddev = {.type_name = "memdev", .ops = &dump_memdev_ops,
6101 +                .device_id = 0x14}
6102 +       /* assume the rest of the fields are zeroed by default */
6103 +};     
6104 +       
6105 +/* may be overwritten if a previous dump exists */
6106 +struct dump_memdev *dump_memdev = &default_dump_memdev;
6107 +
6108 Index: linux-2.6.10-base/drivers/dump/dump_blockdev.c
6109 ===================================================================
6110 --- linux-2.6.10-base.orig/drivers/dump/dump_blockdev.c 2003-09-02 06:26:13.000000000 +0800
6111 +++ linux-2.6.10-base/drivers/dump/dump_blockdev.c      2005-05-17 18:52:39.938054904 +0800
6112 @@ -0,0 +1,469 @@
6113 +/*
6114 + * Implements the dump driver interface for saving a dump to 
6115 + * a block device through the kernel's generic low level block i/o
6116 + * routines.
6117 + *
6118 + * Started: June 2002 - Mohamed Abbas <mohamed.abbas@intel.com>
6119 + *     Moved original lkcd kiobuf dump i/o code from dump_base.c
6120 + *     to use generic dump device interfaces
6121 + *
6122 + * Sept 2002 - Bharata B. Rao <bharata@in.ibm.com>
6123 + *     Convert dump i/o to directly use bio instead of kiobuf for 2.5
6124 + *
6125 + * Oct 2002  - Suparna Bhattacharya <suparna@in.ibm.com>
6126 + *     Rework to new dumpdev.h structures, implement open/close/
6127 + *     silence, misc fixes (blocknr removal, bio_add_page usage)  
6128 + *
6129 + * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
6130 + * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
6131 + * Copyright (C) 2002 International Business Machines Corp. 
6132 + *
6133 + * This code is released under version 2 of the GNU GPL.
6134 + */
6135 +
6136 +#include <linux/types.h>
6137 +#include <linux/proc_fs.h>
6138 +#include <linux/module.h>
6139 +#include <linux/init.h>
6140 +#include <linux/blkdev.h>
6141 +#include <linux/bio.h>
6142 +#include <asm/hardirq.h>
6143 +#include <linux/dump.h>
6144 +#include "dump_methods.h"
6145 +
6146 +extern void *dump_page_buf;
6147 +
6148 +/* The end_io callback for dump i/o completion */
6149 +static int
6150 +dump_bio_end_io(struct bio *bio, unsigned int bytes_done, int error)
6151 +{
6152 +       struct dump_blockdev *dump_bdev;
6153 +
6154 +       if (bio->bi_size) {
6155 +               /* some bytes still left to transfer */
6156 +               return 1; /* not complete */
6157 +       }
6158 +
6159 +       dump_bdev = (struct dump_blockdev *)bio->bi_private;
6160 +       if (error) {
6161 +               printk("IO error while writing the dump, aborting\n");
6162 +       }
6163 +
6164 +       dump_bdev->err = error;
6165 +
6166 +       /* no wakeup needed, since caller polls for completion */
6167 +       return 0;
6168 +}
6169 +
6170 +/* Check if the dump bio is already mapped to the specified buffer */
6171 +static int
6172 +dump_block_map_valid(struct dump_blockdev *dev, struct page *page, 
6173 +       int len) 
6174 +{
6175 +       struct bio *bio = dev->bio;
6176 +       unsigned long bsize = 0;
6177 +
6178 +       if (!bio->bi_vcnt)
6179 +               return 0; /* first time, not mapped */
6180 +
6181 +
6182 +       if ((bio_page(bio) != page) || (len > bio->bi_vcnt << PAGE_SHIFT))
6183 +               return 0; /* buffer not mapped */
6184 +
6185 +       bsize = bdev_hardsect_size(bio->bi_bdev);
6186 +       if ((len & (PAGE_SIZE - 1)) || (len & bsize))
6187 +               return 0; /* alignment checks needed */
6188 +
6189 +       /* quick check to decide if we need to redo bio_add_page */
6190 +       if (bdev_get_queue(bio->bi_bdev)->merge_bvec_fn)
6191 +               return 0; /* device may have other restrictions */
6192 +
6193 +       return 1; /* already mapped */
6194 +}
6195 +
6196 +/* 
6197 + * Set up the dump bio for i/o from the specified buffer 
6198 + * Return value indicates whether the full buffer could be mapped or not
6199 + */
6200 +static int
6201 +dump_block_map(struct dump_blockdev *dev, void *buf, int len)
6202 +{
6203 +       struct page *page = virt_to_page(buf);
6204 +       struct bio *bio = dev->bio;
6205 +       unsigned long bsize = 0;
6206 +
6207 +       bio->bi_bdev = dev->bdev;
6208 +       bio->bi_sector = (dev->start_offset + dev->ddev.curr_offset) >> 9;
6209 +       bio->bi_idx = 0; /* reset index to the beginning */
6210 +
6211 +       if (dump_block_map_valid(dev, page, len)) {
6212 +               /* already mapped and usable rightaway */
6213 +               bio->bi_size = len; /* reset size to the whole bio */
6214 +               bio->bi_vcnt = (len + PAGE_SIZE - 1) / PAGE_SIZE; /* Set the proper vector cnt */
6215 +       } else {
6216 +               /* need to map the bio */
6217 +               bio->bi_size = 0;
6218 +               bio->bi_vcnt = 0;
6219 +               bsize = bdev_hardsect_size(bio->bi_bdev);
6220 +
6221 +               /* first a few sanity checks */
6222 +               if (len < bsize) {
6223 +                       printk("map: len less than hardsect size \n");
6224 +                       return -EINVAL;
6225 +               }
6226 +
6227 +               if ((unsigned long)buf & bsize) {
6228 +                       printk("map: not aligned \n");
6229 +                       return -EINVAL;
6230 +               }
6231 +
6232 +               /* assume contig. page aligned low mem buffer( no vmalloc) */
6233 +               if ((page_address(page) != buf) || (len & (PAGE_SIZE - 1))) {
6234 +                       printk("map: invalid buffer alignment!\n");
6235 +                       return -EINVAL; 
6236 +               }
6237 +               /* finally we can go ahead and map it */
6238 +               while (bio->bi_size < len)
6239 +                       if (bio_add_page(bio, page++, PAGE_SIZE, 0) == 0) {
6240 +                               break;
6241 +                       }
6242 +
6243 +               bio->bi_end_io = dump_bio_end_io;
6244 +               bio->bi_private = dev;
6245 +       }
6246 +
6247 +       if (bio->bi_size != len) {
6248 +               printk("map: bio size = %d not enough for len = %d!\n",
6249 +                       bio->bi_size, len);
6250 +               return -E2BIG;
6251 +       }
6252 +       return 0;
6253 +}
6254 +
6255 +static void
6256 +dump_free_bio(struct bio *bio)
6257 +{
6258 +       if (bio)
6259 +               kfree(bio->bi_io_vec);
6260 +       kfree(bio);
6261 +}
6262 +
6263 +/*
6264 + * Prepares the dump device so we can take a dump later. 
6265 + * The caller is expected to have filled up the dev_id field in the 
6266 + * block dump dev structure.
6267 + *
6268 + * At dump time when dump_block_write() is invoked it will be too 
6269 + * late to recover, so as far as possible make sure obvious errors 
6270 + * get caught right here and reported back to the caller.
6271 + */
6272 +static int
6273 +dump_block_open(struct dump_dev *dev, unsigned long arg)
6274 +{
6275 +       struct dump_blockdev *dump_bdev = DUMP_BDEV(dev);
6276 +       struct block_device *bdev;
6277 +       int retval = 0;
6278 +       struct bio_vec *bvec;
6279 +
6280 +       /* make sure this is a valid block device */
6281 +       if (!arg) {
6282 +               retval = -EINVAL;
6283 +               goto err;
6284 +       }
6285 +
6286 +       /* Convert it to the new dev_t format */
6287 +       arg = MKDEV((arg >> OLDMINORBITS), (arg & OLDMINORMASK));
6288 +       
6289 +       /* get a corresponding block_dev struct for this */
6290 +       bdev = bdget((dev_t)arg);
6291 +       if (!bdev) {
6292 +               retval = -ENODEV;
6293 +               goto err;
6294 +       }
6295 +
6296 +       /* get the block device opened */
6297 +       if ((retval = blkdev_get(bdev, O_RDWR | O_LARGEFILE, 0))) {
6298 +               goto err1;
6299 +       }
6300 +
6301 +       if ((dump_bdev->bio = kmalloc(sizeof(struct bio), GFP_KERNEL)) 
6302 +               == NULL) {
6303 +               printk("Cannot allocate bio\n");
6304 +               retval = -ENOMEM;
6305 +               goto err2;
6306 +       }
6307 +
6308 +       bio_init(dump_bdev->bio);
6309 +
6310 +       if ((bvec = kmalloc(sizeof(struct bio_vec) * 
6311 +               (DUMP_BUFFER_SIZE >> PAGE_SHIFT), GFP_KERNEL)) == NULL) {
6312 +               retval = -ENOMEM;
6313 +               goto err3;
6314 +       }
6315 +
6316 +       /* assign the new dump dev structure */
6317 +       dump_bdev->dev_id = (dev_t)arg;
6318 +       dump_bdev->bdev = bdev;
6319 +
6320 +       /* make a note of the limit */
6321 +       dump_bdev->limit = bdev->bd_inode->i_size;
6322 +       
6323 +       /* now make sure we can map the dump buffer */
6324 +       dump_bdev->bio->bi_io_vec = bvec;
6325 +       dump_bdev->bio->bi_max_vecs = DUMP_BUFFER_SIZE >> PAGE_SHIFT;
6326 +
6327 +       retval = dump_block_map(dump_bdev, dump_config.dumper->dump_buf, 
6328 +               DUMP_BUFFER_SIZE);
6329 +               
6330 +       if (retval) {
6331 +               printk("open: dump_block_map failed, ret %d\n", retval);
6332 +               goto err3;
6333 +       }
6334 +
6335 +       printk("Block device (%d,%d) successfully configured for dumping\n",
6336 +              MAJOR(dump_bdev->dev_id),
6337 +              MINOR(dump_bdev->dev_id));
6338 +
6339 +
6340 +       /* after opening the block device, return */
6341 +       return retval;
6342 +
6343 +err3:  dump_free_bio(dump_bdev->bio);
6344 +       dump_bdev->bio = NULL;
6345 +err2:  if (bdev) blkdev_put(bdev);
6346 +               goto err;
6347 +err1:  if (bdev) bdput(bdev);
6348 +       dump_bdev->bdev = NULL;
6349 +err:   return retval;
6350 +}
6351 +
6352 +/*
6353 + * Close the dump device and release associated resources
6354 + * Invoked when unconfiguring the dump device.
6355 + */
6356 +static int
6357 +dump_block_release(struct dump_dev *dev)
6358 +{
6359 +       struct dump_blockdev *dump_bdev = DUMP_BDEV(dev);
6360 +
6361 +       /* release earlier bdev if present */
6362 +       if (dump_bdev->bdev) {
6363 +               blkdev_put(dump_bdev->bdev);
6364 +               dump_bdev->bdev = NULL;
6365 +       }
6366 +
6367 +       dump_free_bio(dump_bdev->bio);
6368 +       dump_bdev->bio = NULL;
6369 +
6370 +       return 0;
6371 +}
6372 +
6373 +
6374 +/*
6375 + * Prepare the dump device for use (silence any ongoing activity
6376 + * and quiesce state) when the system crashes.
6377 + */
6378 +static int
6379 +dump_block_silence(struct dump_dev *dev)
6380 +{
6381 +       struct dump_blockdev *dump_bdev = DUMP_BDEV(dev);
6382 +       struct request_queue *q = bdev_get_queue(dump_bdev->bdev);
6383 +       int ret;
6384 +
6385 +       /* If we can't get request queue lock, refuse to take the dump */
6386 +       if (!spin_trylock(q->queue_lock))
6387 +               return -EBUSY;
6388 +
6389 +       ret = elv_queue_empty(q);
6390 +       spin_unlock(q->queue_lock);
6391 +
6392 +       /* For now we assume we have the device to ourselves */
6393 +       /* Just a quick sanity check */
6394 +       if (!ret) {
6395 +               /* Warn the user and move on */
6396 +               printk(KERN_ALERT "Warning: Non-empty request queue\n");
6397 +               printk(KERN_ALERT "I/O requests in flight at dump time\n");
6398 +       }
6399 +
6400 +       /* 
6401 +        * Move to a softer level of silencing where no spin_lock_irqs 
6402 +        * are held on other cpus
6403 +        */
6404 +       dump_silence_level = DUMP_SOFT_SPIN_CPUS;       
6405 +
6406 +       ret = __dump_irq_enable();
6407 +       if (ret) {
6408 +               return ret;
6409 +       }
6410 +
6411 +       printk("Dumping to block device (%d,%d) on CPU %d ...\n",
6412 +              MAJOR(dump_bdev->dev_id), MINOR(dump_bdev->dev_id),
6413 +              smp_processor_id());
6414 +       
6415 +       return 0;
6416 +}
6417 +
6418 +/*
6419 + * Invoked when dumping is done. This is the time to put things back 
6420 + * (i.e. undo the effects of dump_block_silence) so the device is 
6421 + * available for normal use.
6422 + */
6423 +static int
6424 +dump_block_resume(struct dump_dev *dev)
6425 +{
6426 +       __dump_irq_restore();
6427 +       return 0;
6428 +}
6429 +
6430 +
6431 +/*
6432 + * Seek to the specified offset in the dump device.
6433 + * Makes sure this is a valid offset, otherwise returns an error.
6434 + */
6435 +static int
6436 +dump_block_seek(struct dump_dev *dev, loff_t off)
6437 +{
6438 +       struct dump_blockdev *dump_bdev = DUMP_BDEV(dev);
6439 +       loff_t offset = off + dump_bdev->start_offset;
6440 +       
6441 +       if (offset & ( PAGE_SIZE - 1)) {
6442 +               printk("seek: non-page aligned\n");
6443 +               return -EINVAL;
6444 +       }
6445 +
6446 +       if (offset & (bdev_hardsect_size(dump_bdev->bdev) - 1)) {
6447 +               printk("seek: not sector aligned \n");
6448 +               return -EINVAL;
6449 +       }
6450 +
6451 +       if (offset > dump_bdev->limit) {
6452 +               printk("seek: not enough space left on device!\n");
6453 +               return -ENOSPC; 
6454 +       }
6455 +       dev->curr_offset = off;
6456 +       return 0;
6457 +}
6458 +
6459 +/*
6460 + * Write out a buffer after checking the device limitations, 
6461 + * sector sizes, etc. Assumes the buffer is in directly mapped 
6462 + * kernel address space (not vmalloc'ed).
6463 + *
6464 + * Returns: number of bytes written or -ERRNO. 
6465 + */
6466 +static int
6467 +dump_block_write(struct dump_dev *dev, void *buf, 
6468 +       unsigned long len)
6469 +{
6470 +       struct dump_blockdev *dump_bdev = DUMP_BDEV(dev);
6471 +       loff_t offset = dev->curr_offset + dump_bdev->start_offset;
6472 +       int retval = -ENOSPC;
6473 +
6474 +       if (offset >= dump_bdev->limit) {
6475 +               printk("write: not enough space left on device!\n");
6476 +               goto out;
6477 +       }
6478 +
6479 +       /* don't write more blocks than our max limit */
6480 +       if (offset + len > dump_bdev->limit) 
6481 +               len = dump_bdev->limit - offset;
6482 +
6483 +
6484 +       retval = dump_block_map(dump_bdev, buf, len);
6485 +       if (retval){
6486 +               printk("write: dump_block_map failed! err %d\n", retval);
6487 +               goto out;
6488 +       }
6489 +
6490 +       /*
6491 +        * Write out the data to disk.
6492 +        * Assumes the entire buffer mapped to a single bio, which we can
6493 +        * submit and wait for io completion. In the future, may consider
6494 +        * increasing the dump buffer size and submitting multiple bio s 
6495 +        * for better throughput.
6496 +        */
6497 +       dump_bdev->err = -EAGAIN;
6498 +       submit_bio(WRITE, dump_bdev->bio);
6499 +
6500 +       dump_bdev->ddev.curr_offset += len;
6501 +       retval = len;
6502 + out:
6503 +       return retval;
6504 +}
6505 +
6506 +/*
6507 + * Name: dump_block_ready()
6508 + * Func: check if the last dump i/o is over and ready for next request
6509 + */
6510 +static int
6511 +dump_block_ready(struct dump_dev *dev, void *buf)
6512 +{
6513 +       struct dump_blockdev *dump_bdev = DUMP_BDEV(dev);
6514 +       request_queue_t *q = bdev_get_queue(dump_bdev->bio->bi_bdev);
6515 +
6516 +       /* check for io completion */
6517 +       if (dump_bdev->err == -EAGAIN) {
6518 +               q->unplug_fn(q);
6519 +               return -EAGAIN;
6520 +       }
6521 +
6522 +       if (dump_bdev->err) {
6523 +               printk("dump i/o err\n");
6524 +               return dump_bdev->err;
6525 +       }
6526 +
6527 +       return 0;
6528 +}
6529 +
6530 +
6531 +struct dump_dev_ops dump_blockdev_ops = {
6532 +       .open           = dump_block_open,
6533 +       .release        = dump_block_release,
6534 +       .silence        = dump_block_silence,
6535 +       .resume         = dump_block_resume,
6536 +       .seek           = dump_block_seek,
6537 +       .write          = dump_block_write,
6538 +       /* .read not implemented */
6539 +       .ready          = dump_block_ready
6540 +};
6541 +
6542 +static struct dump_blockdev default_dump_blockdev = {
6543 +       .ddev = {.type_name = "blockdev", .ops = &dump_blockdev_ops, 
6544 +                       .curr_offset = 0},
6545 +       /* 
6546 +        * leave enough room for the longest swap header possibly written 
6547 +        * written by mkswap (likely the largest page size supported by
6548 +        * the arch
6549 +        */
6550 +       .start_offset   = DUMP_HEADER_OFFSET,
6551 +       .err            = 0
6552 +       /* assume the rest of the fields are zeroed by default */
6553 +};     
6554 +       
6555 +struct dump_blockdev *dump_blockdev = &default_dump_blockdev;
6556 +
6557 +static int __init
6558 +dump_blockdev_init(void)
6559 +{
6560 +       if (dump_register_device(&dump_blockdev->ddev) < 0) {
6561 +               printk("block device driver registration failed\n");
6562 +               return -1;
6563 +       }
6564 +               
6565 +       printk("block device driver for LKCD registered\n");
6566 +       return 0;
6567 +}
6568 +
6569 +static void __exit
6570 +dump_blockdev_cleanup(void)
6571 +{
6572 +       dump_unregister_device(&dump_blockdev->ddev);
6573 +       printk("block device driver for LKCD unregistered\n");
6574 +}
6575 +
6576 +MODULE_AUTHOR("LKCD Development Team <lkcd-devel@lists.sourceforge.net>");
6577 +MODULE_DESCRIPTION("Block Dump Driver for Linux Kernel Crash Dump (LKCD)");
6578 +MODULE_LICENSE("GPL");
6579 +
6580 +module_init(dump_blockdev_init);
6581 +module_exit(dump_blockdev_cleanup);
6582 Index: linux-2.6.10-base/drivers/dump/Makefile
6583 ===================================================================
6584 --- linux-2.6.10-base.orig/drivers/dump/Makefile        2003-09-02 06:26:13.000000000 +0800
6585 +++ linux-2.6.10-base/drivers/dump/Makefile     2005-05-17 18:52:39.938054904 +0800
6586 @@ -0,0 +1,22 @@
6587 +#
6588 +# Makefile for the dump device drivers.
6589 +#
6590 +
6591 +dump-y                                 := dump_setup.o dump_fmt.o dump_filters.o dump_scheme.o dump_execute.o
6592 +ifeq ($(CONFIG_X86_64),)
6593 +ifeq ($(CONFIG_X86),y)
6594 +dump-$(CONFIG_X86)                     += dump_i386.o
6595 +endif
6596 +endif
6597 +dump-$(CONFIG_ARM)                     += dump_arm.o
6598 +dump-$(CONFIG_PPC64)                    += dump_ppc64.o
6599 +dump-$(CONFIG_X86_64)                  += dump_x8664.o
6600 +dump-$(CONFIG_IA64)                    += dump_ia64.o
6601 +dump-$(CONFIG_CRASH_DUMP_MEMDEV)       += dump_memdev.o dump_overlay.o
6602 +dump-objs                              += $(dump-y)
6603 +
6604 +obj-$(CONFIG_CRASH_DUMP)               += dump.o 
6605 +obj-$(CONFIG_CRASH_DUMP_BLOCKDEV)      += dump_blockdev.o
6606 +obj-$(CONFIG_CRASH_DUMP_NETDEV)        += dump_netdev.o
6607 +obj-$(CONFIG_CRASH_DUMP_COMPRESS_RLE)  += dump_rle.o
6608 +obj-$(CONFIG_CRASH_DUMP_COMPRESS_GZIP) += dump_gzip.o
6609 Index: linux-2.6.10-base/drivers/dump/dump_scheme.c
6610 ===================================================================
6611 --- linux-2.6.10-base.orig/drivers/dump/dump_scheme.c   2003-09-02 06:26:13.000000000 +0800
6612 +++ linux-2.6.10-base/drivers/dump/dump_scheme.c        2005-05-17 18:52:39.939054752 +0800
6613 @@ -0,0 +1,430 @@
6614 +/* 
6615 + * Default single stage dump scheme methods
6616 + *
6617 + * Previously a part of dump_base.c
6618 + *
6619 + * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
6620 + *     Split and rewrote LKCD dump scheme to generic dump method 
6621 + *     interfaces 
6622 + * Derived from original code created by
6623 + *     Matt Robinson <yakker@sourceforge.net>)
6624 + *
6625 + * Contributions from SGI, IBM, HP, MCL, and others.
6626 + *
6627 + * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
6628 + * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
6629 + * Copyright (C) 2002 International Business Machines Corp. 
6630 + *
6631 + * This code is released under version 2 of the GNU GPL.
6632 + */
6633 +
6634 +/*
6635 + * Implements the default dump scheme, i.e. single-stage gathering and 
6636 + * saving of dump data directly to the target device, which operates in
6637 + * a push mode, where the dumping system decides what data it saves
6638 + * taking into account pre-specified dump config options.
6639 + *
6640 + * Aside: The 2-stage dump scheme, where there is a soft-reset between
6641 + * the gathering and saving phases, also reuses some of these
6642 + * default routines (see dump_overlay.c) 
6643 + */ 
6644 +#include <linux/types.h>
6645 +#include <linux/kernel.h>
6646 +#include <linux/mm.h>
6647 +#include <linux/slab.h>
6648 +#include <linux/delay.h>
6649 +#include <linux/reboot.h>
6650 +#include <linux/nmi.h>
6651 +#include <linux/dump.h>
6652 +#include "dump_methods.h"
6653 +
6654 +extern int panic_timeout;  /* time before reboot */
6655 +
6656 +extern void dump_speedo(int);
6657 +
6658 +/* Default sequencer used during single stage dumping */
6659 +/* Also invoked during stage 2 of soft-boot based dumping */
6660 +int dump_generic_sequencer(void)
6661 +{
6662 +       struct dump_data_filter *filter = dump_config.dumper->filter;
6663 +       int pass = 0, err = 0, save = 0;
6664 +       int (*action)(unsigned long, unsigned long);
6665 +
6666 +       /* 
6667 +        * We want to save the more critical data areas first in 
6668 +        * case we run out of space, encounter i/o failures, or get
6669 +        * interrupted otherwise and have to give up midway
6670 +        * So, run through the passes in increasing order 
6671 +        */
6672 +       for (;filter->selector; filter++, pass++)
6673 +       {
6674 +               /* Assumes passes are exclusive (even across dumpers) */
6675 +               /* Requires care when coding the selection functions */
6676 +               if ((save = filter->level_mask & dump_config.level))
6677 +                       action = dump_save_data;
6678 +               else
6679 +                       action = dump_skip_data;
6680 +
6681 +               if ((err = dump_iterator(pass, action, filter)) < 0)
6682 +                       break;
6683 +
6684 +               printk("\n %d dump pages %s of %d each in pass %d\n", 
6685 +               err, save ? "saved" : "skipped", (int)DUMP_PAGE_SIZE, pass);
6686 +
6687 +       }
6688 +
6689 +       return (err < 0) ? err : 0;
6690 +}
6691 +
6692 +static inline struct page *dump_get_page(loff_t loc)
6693 +{
6694 +
6695 +       unsigned long page_index = loc >> PAGE_SHIFT;
6696 +
6697 +       /* todo: complete this  to account for ia64/discontig mem */
6698 +       /* todo: and to check for validity, ram page, no i/o mem etc */
6699 +       /* need to use pfn/physaddr equiv of kern_addr_valid */
6700 +
6701 +       /* Important:
6702 +        *   On ARM/XScale system, the physical address starts from 
6703 +        *   PHYS_OFFSET, and it maybe the situation that PHYS_OFFSET != 0. 
6704 +        *   For example on Intel's PXA250, PHYS_OFFSET = 0xa0000000. And the 
6705 +        *   page index starts from PHYS_PFN_OFFSET. When configuring
6706 +        *   filter, filter->start is assigned to 0 in dump_generic_configure.
6707 +        *   Here we want to adjust it by adding PHYS_PFN_OFFSET to it!
6708 +        */
6709 +#ifdef CONFIG_ARM
6710 +       page_index += PHYS_PFN_OFFSET;
6711 +#endif
6712 +       if (__dump_page_valid(page_index))
6713 +               return pfn_to_page(page_index);
6714 +       else
6715 +               return NULL;
6716 +
6717 +}
6718 +
6719 +/* Default iterator: for singlestage and stage 1 of soft-boot dumping */
6720 +/* Iterates over range of physical memory pages in DUMP_PAGE_SIZE increments */
6721 +int dump_page_iterator(int pass, int (*action)(unsigned long, unsigned long), 
6722 +       struct dump_data_filter *filter)
6723 +{
6724 +       /* Todo : fix unit, type */
6725 +       loff_t loc, start, end;
6726 +       int i, count = 0, err = 0;
6727 +       struct page *page;
6728 +
6729 +       /* Todo: Add membanks code */
6730 +       /* TBD: Check if we need to address DUMP_PAGE_SIZE < PAGE_SIZE */       
6731 +
6732 +       for (i = 0; i < filter->num_mbanks; i++) {
6733 +               start = filter->start[i];
6734 +               end = filter->end[i];
6735 +               for (loc = start; loc < end; loc += DUMP_PAGE_SIZE) {
6736 +                       dump_config.dumper->curr_loc = loc;
6737 +                       page = dump_get_page(loc);
6738 +                       if (page && filter->selector(pass, 
6739 +                               (unsigned long) page, DUMP_PAGE_SIZE)) { 
6740 +                               if ((err = action((unsigned long)page, 
6741 +                                       DUMP_PAGE_SIZE))) {
6742 +                                       printk("dump_page_iterator: err %d for "
6743 +                                               "loc 0x%llx, in pass %d\n", 
6744 +                                               err, loc, pass);
6745 +                                       return err ? err : count;
6746 +                               } else
6747 +                                       count++;
6748 +                       }
6749 +               }
6750 +       }
6751 +
6752 +       return err ? err : count;
6753 +}
6754 +
6755 +/* 
6756 + * Base function that saves the selected block of data in the dump 
6757 + * Action taken when iterator decides that data needs to be saved 
6758 + */
6759 +int dump_generic_save_data(unsigned long loc, unsigned long sz)
6760 +{
6761 +       void *buf;
6762 +       void *dump_buf = dump_config.dumper->dump_buf;
6763 +       int left, bytes, ret;
6764 +
6765 +       if ((ret = dump_add_data(loc, sz))) {
6766 +               return ret;
6767 +       }
6768 +       buf = dump_config.dumper->curr_buf;
6769 +
6770 +       /* If we've filled up the buffer write it out */
6771 +       if ((left = buf - dump_buf) >= DUMP_BUFFER_SIZE) {
6772 +               bytes = dump_write_buffer(dump_buf, DUMP_BUFFER_SIZE);
6773 +               if (bytes < DUMP_BUFFER_SIZE) {
6774 +                       printk("dump_write_buffer failed %d\n", bytes);
6775 +                       return bytes ? -ENOSPC : bytes;
6776 +               }
6777 +
6778 +               left -= bytes;
6779 +               
6780 +               /* -- A few chores to do from time to time -- */
6781 +               dump_config.dumper->count++;
6782 +
6783 +               if (!(dump_config.dumper->count & 0x3f)) {
6784 +                       /* Update the header every one in a while */
6785 +                       memset((void *)dump_buf, 'b', DUMP_BUFFER_SIZE);
6786 +                       if ((ret = dump_update_header()) < 0) {
6787 +                               /* issue warning */
6788 +                               return ret;
6789 +                       }
6790 +                       printk(".");
6791 +
6792 +                       touch_nmi_watchdog();
6793 +               } else if (!(dump_config.dumper->count & 0x7)) {
6794 +                       /* Show progress so the user knows we aren't hung */
6795 +                       dump_speedo(dump_config.dumper->count >> 3); 
6796 +               }
6797 +               /* Todo: Touch/Refresh watchdog */
6798 +
6799 +               /* --- Done with periodic chores -- */
6800 +
6801 +               /* 
6802 +                * extra bit of copying to simplify verification  
6803 +                * in the second kernel boot based scheme
6804 +                */
6805 +               memcpy(dump_buf - DUMP_PAGE_SIZE, dump_buf + 
6806 +                       DUMP_BUFFER_SIZE - DUMP_PAGE_SIZE, DUMP_PAGE_SIZE);
6807 +
6808 +               /* now adjust the leftover bits back to the top of the page */
6809 +               /* this case would not arise during stage 2 (passthru) */
6810 +               memset(dump_buf, 'z', DUMP_BUFFER_SIZE);
6811 +               if (left) {
6812 +                       memcpy(dump_buf, dump_buf + DUMP_BUFFER_SIZE, left);
6813 +               }
6814 +               buf -= DUMP_BUFFER_SIZE;
6815 +               dump_config.dumper->curr_buf = buf;
6816 +       }
6817 +                               
6818 +       return 0;
6819 +}
6820 +
6821 +int dump_generic_skip_data(unsigned long loc, unsigned long sz)
6822 +{
6823 +       /* dummy by default */
6824 +       return 0;
6825 +}
6826 +
6827 +/* 
6828 + * Common low level routine to write a buffer to current dump device 
6829 + * Expects checks for space etc to have been taken care of by the caller 
6830 + * Operates serially at the moment for simplicity. 
6831 + * TBD/Todo: Consider batching for improved throughput
6832 + */
6833 +int dump_ll_write(void *buf, unsigned long len)
6834 +{
6835 +       long transferred = 0, last_transfer = 0;
6836 +       int ret = 0;
6837 +
6838 +       /* make sure device is ready */
6839 +       while ((ret = dump_dev_ready(NULL)) == -EAGAIN);
6840 +       if  (ret < 0) {
6841 +               printk("dump_dev_ready failed !err %d\n", ret);
6842 +               return ret;
6843 +       }
6844 +
6845 +       while (len) {
6846 +               if ((last_transfer = dump_dev_write(buf, len)) <= 0)  {
6847 +                       ret = last_transfer;
6848 +                       printk("dump_dev_write failed !err %d\n", 
6849 +                       ret);
6850 +                       break;
6851 +               }
6852 +               /* wait till complete */
6853 +               while ((ret = dump_dev_ready(buf)) == -EAGAIN)
6854 +                       cpu_relax();
6855 +
6856 +               if  (ret < 0) {
6857 +                       printk("i/o failed !err %d\n", ret);
6858 +                       break;
6859 +               }
6860 +
6861 +               len -= last_transfer;
6862 +               buf += last_transfer;
6863 +               transferred += last_transfer;
6864 +       }
6865 +       return (ret < 0) ? ret : transferred;
6866 +}
6867 +
6868 +/* default writeout routine for single dump device */
6869 +/* writes out the dump data ensuring enough space is left for the end marker */
6870 +int dump_generic_write_buffer(void *buf, unsigned long len)
6871 +{
6872 +       long written = 0;
6873 +       int err = 0;
6874 +
6875 +       /* check for space */
6876 +       if ((err = dump_dev_seek(dump_config.dumper->curr_offset + len + 
6877 +                       2*DUMP_BUFFER_SIZE)) < 0) {
6878 +               printk("dump_write_buffer: insuff space after offset 0x%llx\n",
6879 +                       dump_config.dumper->curr_offset);
6880 +               return err;
6881 +       }
6882 +       /* alignment check would happen as a side effect of this */
6883 +       if ((err = dump_dev_seek(dump_config.dumper->curr_offset)) < 0)
6884 +               return err; 
6885 +
6886 +       written = dump_ll_write(buf, len);
6887 +
6888 +       /* all or none */
6889 +
6890 +       if (written < len)
6891 +               written = written ? -ENOSPC : written;
6892 +       else
6893 +               dump_config.dumper->curr_offset += len;
6894 +
6895 +       return written;
6896 +}
6897 +
6898 +int dump_generic_configure(unsigned long devid)
6899 +{
6900 +       struct dump_dev *dev = dump_config.dumper->dev;
6901 +       struct dump_data_filter *filter;
6902 +       void *buf;
6903 +       int ret = 0;
6904 +
6905 +       /* Allocate the dump buffer and initialize dumper state */
6906 +       /* Assume that we get aligned addresses */
6907 +       if (!(buf = dump_alloc_mem(DUMP_BUFFER_SIZE + 3 * DUMP_PAGE_SIZE)))
6908 +               return -ENOMEM;
6909 +
6910 +       if ((unsigned long)buf & (PAGE_SIZE - 1)) {
6911 +               /* sanity check for page aligned address */
6912 +               dump_free_mem(buf);
6913 +               return -ENOMEM; /* fixme: better error code */
6914 +       }
6915 +
6916 +       /* Initialize the rest of the fields */
6917 +       dump_config.dumper->dump_buf = buf + DUMP_PAGE_SIZE;
6918 +       dumper_reset();
6919 +
6920 +       /* Open the dump device */
6921 +       if (!dev)
6922 +               return -ENODEV;
6923 +
6924 +       if ((ret = dev->ops->open(dev, devid))) {
6925 +              return ret;
6926 +       }
6927 +
6928 +       /* Initialise the memory ranges in the dump filter */
6929 +       for (filter = dump_config.dumper->filter ;filter->selector; filter++) {
6930 +               if (!filter->start[0] && !filter->end[0]) {
6931 +                       pg_data_t *pgdat;
6932 +                       int i = 0;
6933 +                       for_each_pgdat(pgdat) {
6934 +                               filter->start[i] = 
6935 +                                       (loff_t)pgdat->node_start_pfn << PAGE_SHIFT;
6936 +                               filter->end[i] =
6937 +                                       (loff_t)(pgdat->node_start_pfn + pgdat->node_spanned_pages) << PAGE_SHIFT;
6938 +                               i++;
6939 +                       }
6940 +                       filter->num_mbanks = i;
6941 +               }
6942 +       }
6943 +
6944 +       return 0;
6945 +}
6946 +
6947 +int dump_generic_unconfigure(void)
6948 +{
6949 +       struct dump_dev *dev = dump_config.dumper->dev;
6950 +       void *buf = dump_config.dumper->dump_buf;
6951 +       int ret = 0;
6952 +
6953 +       pr_debug("Generic unconfigure\n");
6954 +       /* Close the dump device */
6955 +       if (dev && (ret = dev->ops->release(dev)))
6956 +               return ret;
6957 +
6958 +       printk("Closed dump device\n");
6959 +       
6960 +       if (buf)
6961 +               dump_free_mem((buf - DUMP_PAGE_SIZE));
6962 +
6963 +       dump_config.dumper->curr_buf = dump_config.dumper->dump_buf = NULL;
6964 +       pr_debug("Released dump buffer\n");
6965 +
6966 +       return 0;
6967 +}
6968 +
6969 +#ifdef CONFIG_DISCONTIGMEM
6970 +
6971 +void dump_reconfigure_mbanks(void) 
6972 +{
6973 +        pg_data_t *pgdat;
6974 +        loff_t start, end, loc, loc_end;
6975 +        int i=0;
6976 +        struct dump_data_filter *filter = dump_config.dumper->filter;
6977 +
6978 +        for_each_pgdat(pgdat) {
6979 +
6980 +                start = (loff_t)(pgdat->node_start_pfn << PAGE_SHIFT);
6981 +                end = ((loff_t)(pgdat->node_start_pfn + pgdat->node_spanned_pages) << PAGE_SHIFT);
6982 +               for(loc = start; loc < end; loc += (DUMP_PAGE_SIZE)) {
6983 +
6984 +                        if(!(__dump_page_valid(loc >> PAGE_SHIFT)))
6985 +                                continue;
6986 +
6987 +                        /* We found a valid page. This is the start */
6988 +                        filter->start[i] = loc;
6989 +
6990 +                        /* Now loop here till you find the end */
6991 +                        for(loc_end = loc; loc_end < end; loc_end += (DUMP_PAGE_SIZE)) {
6992 +                                
6993 +                               if(__dump_page_valid(loc_end >> PAGE_SHIFT)) {
6994 +                                /* This page could very well be the last page */
6995 +                                        filter->end[i] = loc_end;
6996 +                                        continue;
6997 +                                }
6998 +                                break;
6999 +                        }
7000 +                        i++;
7001 +                        loc = loc_end;
7002 +                }
7003 +        }
7004 +        filter->num_mbanks = i;
7005 +
7006 +        /* Propagate memory bank information to other filters */
7007 +        for (filter = dump_config.dumper->filter, filter++ ;filter->selector; filter++) {
7008 +                for(i = 0; i < dump_config.dumper->filter->num_mbanks; i++) {
7009 +                        filter->start[i] = dump_config.dumper->filter->start[i];
7010 +                        filter->end[i] = dump_config.dumper->filter->end[i];
7011 +                        filter->num_mbanks = dump_config.dumper->filter->num_mbanks;
7012 +                }
7013 +        }
7014 +}
7015 +#endif
7016 +
7017 +/* Set up the default dump scheme */
7018 +
7019 +struct dump_scheme_ops dump_scheme_singlestage_ops = {
7020 +       .configure      = dump_generic_configure,
7021 +       .unconfigure    = dump_generic_unconfigure,
7022 +       .sequencer      = dump_generic_sequencer,
7023 +       .iterator       = dump_page_iterator,
7024 +       .save_data      = dump_generic_save_data,
7025 +       .skip_data      = dump_generic_skip_data,
7026 +       .write_buffer   = dump_generic_write_buffer,
7027 +};
7028 +
7029 +struct dump_scheme dump_scheme_singlestage = {
7030 +       .name           = "single-stage",
7031 +       .ops            = &dump_scheme_singlestage_ops
7032 +};
7033 +
7034 +/* The single stage dumper comprising all these */
7035 +struct dumper dumper_singlestage = {
7036 +       .name           = "single-stage",
7037 +       .scheme         = &dump_scheme_singlestage,
7038 +       .fmt            = &dump_fmt_lcrash,
7039 +       .compress       = &dump_none_compression,
7040 +       .filter         = dump_filter_table,
7041 +       .dev            = NULL,
7042 +};             
7043 +
7044 Index: linux-2.6.10-base/drivers/Makefile
7045 ===================================================================
7046 --- linux-2.6.10-base.orig/drivers/Makefile     2004-12-25 05:36:00.000000000 +0800
7047 +++ linux-2.6.10-base/drivers/Makefile  2005-05-17 18:52:39.939054752 +0800
7048 @@ -60,3 +60,4 @@
7049  obj-$(CONFIG_CPU_FREQ)         += cpufreq/
7050  obj-$(CONFIG_MMC)              += mmc/
7051  obj-y                          += firmware/
7052 +obj-$(CONFIG_CRASH_DUMP)       += dump/
7053 Index: linux-2.6.10-base/drivers/block/ll_rw_blk.c
7054 ===================================================================
7055 --- linux-2.6.10-base.orig/drivers/block/ll_rw_blk.c    2005-05-17 18:52:39.600106280 +0800
7056 +++ linux-2.6.10-base/drivers/block/ll_rw_blk.c 2005-05-17 18:52:39.940054600 +0800
7057 @@ -28,6 +28,7 @@
7058  #include <linux/slab.h>
7059  #include <linux/swap.h>
7060  #include <linux/writeback.h>
7061 +#include <linux/dump.h>
7062  
7063  /*
7064   * for max sense size
7065 @@ -2624,13 +2625,15 @@
7066   * bi_sector for remaps as it sees fit.  So the values of these fields
7067   * should NOT be depended on after the call to generic_make_request.
7068   */
7069 +extern unsigned long dump_oncpu;
7070  void generic_make_request(struct bio *bio)
7071  {
7072         request_queue_t *q;
7073         sector_t maxsector;
7074         int ret, nr_sectors = bio_sectors(bio);
7075  
7076 -       might_sleep();
7077 +       if (likely(!dump_oncpu))
7078 +           might_sleep();
7079         /* Test device or partition size, when known. */
7080         maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
7081         if (maxsector) {
7082 Index: linux-2.6.10-base/mm/bootmem.c
7083 ===================================================================
7084 --- linux-2.6.10-base.orig/mm/bootmem.c 2004-12-25 05:34:30.000000000 +0800
7085 +++ linux-2.6.10-base/mm/bootmem.c      2005-05-17 18:52:39.941054448 +0800
7086 @@ -26,6 +26,7 @@
7087   */
7088  unsigned long max_low_pfn;
7089  unsigned long min_low_pfn;
7090 +EXPORT_SYMBOL(min_low_pfn);
7091  unsigned long max_pfn;
7092  
7093  EXPORT_SYMBOL(max_pfn);                /* This is exported so
7094 @@ -284,6 +285,7 @@
7095                                 if (j + 16 < BITS_PER_LONG)
7096                                         prefetchw(page + j + 16);
7097                                 __ClearPageReserved(page + j);
7098 +                               set_page_count(page + j, 1);
7099                         }
7100                         __free_pages(page, ffs(BITS_PER_LONG)-1);
7101                         i += BITS_PER_LONG;
7102 Index: linux-2.6.10-base/mm/page_alloc.c
7103 ===================================================================
7104 --- linux-2.6.10-base.orig/mm/page_alloc.c      2005-04-06 23:38:35.000000000 +0800
7105 +++ linux-2.6.10-base/mm/page_alloc.c   2005-05-17 18:52:39.942054296 +0800
7106 @@ -47,6 +47,11 @@
7107  EXPORT_SYMBOL(totalram_pages);
7108  EXPORT_SYMBOL(nr_swap_pages);
7109  
7110 +#ifdef CONFIG_CRASH_DUMP_MODULE
7111 +/* This symbol has to be exported to use 'for_each_pgdat' macro by modules. */
7112 +EXPORT_SYMBOL(pgdat_list);
7113 +#endif
7114 +
7115  /*
7116   * Used by page_zone() to look up the address of the struct zone whose
7117   * id is encoded in the upper bits of page->flags
7118 @@ -281,8 +286,11 @@
7119         arch_free_page(page, order);
7120  
7121         mod_page_state(pgfree, 1 << order);
7122 -       for (i = 0 ; i < (1 << order) ; ++i)
7123 +       for (i = 0 ; i < (1 << order) ; ++i){
7124 +               if (unlikely(i))
7125 +                   __put_page(page + i); 
7126                 free_pages_check(__FUNCTION__, page + i);
7127 +       }
7128         list_add(&page->lru, &list);
7129         kernel_map_pages(page, 1<<order, 0);
7130         free_pages_bulk(page_zone(page), 1, &list, order);
7131 @@ -322,44 +330,34 @@
7132         return page;
7133  }
7134  
7135 -static inline void set_page_refs(struct page *page, int order)
7136 -{
7137 -#ifdef CONFIG_MMU
7138 -       set_page_count(page, 1);
7139 -#else
7140 -       int i;
7141 -
7142 -       /*
7143 -        * We need to reference all the pages for this order, otherwise if
7144 -        * anyone accesses one of the pages with (get/put) it will be freed.
7145 -        */
7146 -       for (i = 0; i < (1 << order); i++)
7147 -               set_page_count(page+i, 1);
7148 -#endif /* CONFIG_MMU */
7149 -}
7150 -
7151  /*
7152   * This page is about to be returned from the page allocator
7153   */
7154 -static void prep_new_page(struct page *page, int order)
7155 +static void prep_new_page(struct page *_page, int order)
7156  {
7157 -       if (page->mapping || page_mapped(page) ||
7158 -           (page->flags & (
7159 -                       1 << PG_private |
7160 -                       1 << PG_locked  |
7161 -                       1 << PG_lru     |
7162 -                       1 << PG_active  |
7163 -                       1 << PG_dirty   |
7164 -                       1 << PG_reclaim |
7165 -                       1 << PG_swapcache |
7166 -                       1 << PG_writeback )))
7167 +        int i;
7168 +
7169 +       for(i = 0; i < (1 << order); i++){
7170 +           struct page *page = _page + i;
7171 +
7172 +           if (page->mapping || page_mapped(page) ||
7173 +                   (page->flags & (
7174 +                                   1 << PG_private     |
7175 +                                   1 << PG_locked      |
7176 +                                   1 << PG_lru |
7177 +                                   1 << PG_active      |
7178 +                                   1 << PG_dirty       |
7179 +                                   1 << PG_reclaim     |
7180 +                                   1 << PG_swapcache |
7181 +                                   1 << PG_writeback )))
7182                 bad_page(__FUNCTION__, page);
7183  
7184 -       page->flags &= ~(1 << PG_uptodate | 1 << PG_error |
7185 -                       1 << PG_referenced | 1 << PG_arch_1 |
7186 -                       1 << PG_checked | 1 << PG_mappedtodisk);
7187 -       page->private = 0;
7188 -       set_page_refs(page, order);
7189 +           page->flags &= ~(1 << PG_uptodate | 1 << PG_error |
7190 +                   1 << PG_referenced | 1 << PG_arch_1 |
7191 +                   1 << PG_checked | 1 << PG_mappedtodisk);
7192 +           page->private = 0;
7193 +           set_page_count(page, 1);
7194 +       }
7195  }
7196  
7197  /* 
7198 Index: linux-2.6.10-base/arch/ia64/Kconfig.debug
7199 ===================================================================
7200 --- linux-2.6.10-base.orig/arch/ia64/Kconfig.debug      2004-12-25 05:34:32.000000000 +0800
7201 +++ linux-2.6.10-base/arch/ia64/Kconfig.debug   2005-05-17 18:52:39.942054296 +0800
7202 @@ -2,6 +2,65 @@
7203  
7204  source "lib/Kconfig.debug"
7205  
7206 +config CRASH_DUMP
7207 +       tristate "Crash dump support (EXPERIMENTAL)"
7208 +       depends on EXPERIMENTAL
7209 +       default n
7210 +       ---help---
7211 +         Say Y here to enable saving an image of system memory when a panic
7212 +         or other error occurs. Dumps can also be forced with the SysRq+d
7213 +         key if MAGIC_SYSRQ is enabled.
7214 +
7215 +config KERNTYPES
7216 +        bool
7217 +        depends on CRASH_DUMP
7218 +        default y
7219 +
7220 +config CRASH_DUMP_BLOCKDEV
7221 +       tristate "Crash dump block device driver"
7222 +       depends on CRASH_DUMP
7223 +       help
7224 +         Say Y to allow saving crash dumps directly to a disk device.
7225 +
7226 +config CRASH_DUMP_NETDEV
7227 +       tristate "Crash dump network device driver"
7228 +       depends on CRASH_DUMP
7229 +       help
7230 +        Say Y to allow saving crash dumps over a network device.
7231 +
7232 +config CRASH_DUMP_MEMDEV
7233 +       bool "Crash dump staged memory driver"
7234 +       depends on CRASH_DUMP
7235 +       help
7236 +         Say Y to allow intermediate saving crash dumps in spare
7237 +         memory pages which would then be written out to disk
7238 +         later.
7239 +
7240 +config CRASH_DUMP_SOFTBOOT
7241 +       bool "Save crash dump across a soft reboot"
7242 +       depends on CRASH_DUMP_MEMDEV
7243 +       help
7244 +         Say Y to allow a crash dump to be preserved in memory
7245 +         pages across a soft reboot and written out to disk
7246 +         thereafter. For this to work, CRASH_DUMP must be
7247 +         configured as part of the kernel (not as a module).
7248 +
7249 +config CRASH_DUMP_COMPRESS_RLE
7250 +       tristate "Crash dump RLE compression"
7251 +       depends on CRASH_DUMP
7252 +       help
7253 +         Say Y to allow saving dumps with Run Length Encoding compression.
7254 +
7255 +config CRASH_DUMP_COMPRESS_GZIP
7256 +       tristate "Crash dump GZIP compression"
7257 +       select ZLIB_INFLATE
7258 +       select ZLIB_DEFLATE
7259 +       depends on CRASH_DUMP
7260 +       help
7261 +         Say Y to allow saving dumps with Gnu Zip compression.
7262 +
7263 +
7264 +
7265  choice
7266         prompt "Physical memory granularity"
7267         default IA64_GRANULE_64MB
7268 Index: linux-2.6.10-base/arch/ia64/kernel/irq.c
7269 ===================================================================
7270 --- linux-2.6.10-base.orig/arch/ia64/kernel/irq.c       2004-12-25 05:35:27.000000000 +0800
7271 +++ linux-2.6.10-base/arch/ia64/kernel/irq.c    2005-05-17 18:52:39.943054144 +0800
7272 @@ -933,7 +933,11 @@
7273  
7274  static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
7275  
7276 +#if defined(CONFIG_CRASH_DUMP) || defined (CONFIG_CRASH_DUMP_MODULE)
7277 +cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
7278 +#else
7279  static cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
7280 +#endif
7281  
7282  static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
7283  
7284 Index: linux-2.6.10-base/arch/ia64/kernel/smp.c
7285 ===================================================================
7286 --- linux-2.6.10-base.orig/arch/ia64/kernel/smp.c       2004-12-25 05:35:40.000000000 +0800
7287 +++ linux-2.6.10-base/arch/ia64/kernel/smp.c    2005-05-17 18:52:39.943054144 +0800
7288 @@ -31,6 +31,10 @@
7289  #include <linux/efi.h>
7290  #include <linux/bitops.h>
7291  
7292 +#if defined(CONFIG_CRASH_DUMP) || defined(CONFIG_CRASH_DUMP_MODULE)
7293 +#include <linux/dump.h>
7294 +#endif
7295 +
7296  #include <asm/atomic.h>
7297  #include <asm/current.h>
7298  #include <asm/delay.h>
7299 @@ -67,6 +71,11 @@
7300  #define IPI_CALL_FUNC          0
7301  #define IPI_CPU_STOP           1
7302  
7303 +#if defined(CONFIG_CRASH_DUMP) || defined(CONFIG_CRASH_DUMP_MODULE)
7304 +#define IPI_DUMP_INTERRUPT      4
7305 +       int (*dump_ipi_function_ptr)(struct pt_regs *) = NULL;
7306 +#endif
7307 +
7308  /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
7309  static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
7310  
7311 @@ -84,7 +93,9 @@
7312         spin_unlock_irq(&call_lock);
7313  }
7314  
7315 -static void
7316 +
7317 +/*changed static void stop_this_cpu -> void stop_this_cpu */
7318 +void
7319  stop_this_cpu (void)
7320  {
7321         /*
7322 @@ -155,6 +166,15 @@
7323                               case IPI_CPU_STOP:
7324                                 stop_this_cpu();
7325                                 break;
7326 +#if defined(CONFIG_CRASH_DUMP) || defined(CONFIG_CRASH_DUMP_MODULE)
7327 +                       case IPI_DUMP_INTERRUPT:
7328 +                        if( dump_ipi_function_ptr != NULL ) {
7329 +                                if (!dump_ipi_function_ptr(regs)) {
7330 +                                         printk(KERN_ERR "(*dump_ipi_function_ptr)(): rejected IPI_DUMP_INTERRUPT\n");
7331 +                                }
7332 +                        }
7333 +                        break;
7334 +#endif
7335  
7336                               default:
7337                                 printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
7338 @@ -369,9 +389,17 @@
7339  {
7340         send_IPI_allbutself(IPI_CPU_STOP);
7341  }
7342 +EXPORT_SYMBOL(smp_send_stop);
7343  
7344  int __init
7345  setup_profiling_timer (unsigned int multiplier)
7346  {
7347         return -EINVAL;
7348  }
7349 +
7350 +#if defined(CONFIG_CRASH_DUMP) || defined(CONFIG_CRASH_DUMP_MODULE)
7351 +void dump_send_ipi(void)
7352 +{
7353 +        send_IPI_allbutself(IPI_DUMP_INTERRUPT);
7354 +}
7355 +#endif
7356 Index: linux-2.6.10-base/arch/ia64/kernel/traps.c
7357 ===================================================================
7358 --- linux-2.6.10-base.orig/arch/ia64/kernel/traps.c     2004-12-25 05:35:39.000000000 +0800
7359 +++ linux-2.6.10-base/arch/ia64/kernel/traps.c  2005-05-17 18:52:39.944053992 +0800
7360 @@ -21,6 +21,8 @@
7361  #include <asm/intrinsics.h>
7362  #include <asm/processor.h>
7363  #include <asm/uaccess.h>
7364 +#include <asm/nmi.h>
7365 +#include <linux/dump.h>
7366  
7367  extern spinlock_t timerlist_lock;
7368  
7369 @@ -89,6 +91,7 @@
7370                 printk("%s[%d]: %s %ld [%d]\n",
7371                         current->comm, current->pid, str, err, ++die_counter);
7372                 show_regs(regs);
7373 +               dump((char *)str, regs);
7374         } else
7375                 printk(KERN_ERR "Recursive die() failure, output suppressed\n");
7376  
7377 Index: linux-2.6.10-base/arch/ia64/kernel/ia64_ksyms.c
7378 ===================================================================
7379 --- linux-2.6.10-base.orig/arch/ia64/kernel/ia64_ksyms.c        2005-04-06 23:38:35.000000000 +0800
7380 +++ linux-2.6.10-base/arch/ia64/kernel/ia64_ksyms.c     2005-05-17 18:52:39.944053992 +0800
7381 @@ -7,7 +7,6 @@
7382  
7383  #include <linux/config.h>
7384  #include <linux/module.h>
7385 -
7386  #include <linux/string.h>
7387  EXPORT_SYMBOL(memset);
7388  EXPORT_SYMBOL(memchr);
7389 @@ -28,6 +27,9 @@
7390  EXPORT_SYMBOL(strstr);
7391  EXPORT_SYMBOL(strpbrk);
7392  
7393 +#include <linux/syscalls.h>
7394 +EXPORT_SYMBOL(sys_ioctl);
7395 +
7396  #include <asm/checksum.h>
7397  EXPORT_SYMBOL(ip_fast_csum);           /* hand-coded assembly */
7398  
7399 @@ -125,3 +127,21 @@
7400  #  endif
7401  # endif
7402  #endif
7403 +
7404 +#include <asm/hw_irq.h>
7405 +
7406 +#ifdef CONFIG_CRASH_DUMP_MODULE
7407 +#ifdef CONFIG_SMP
7408 +extern irq_desc_t _irq_desc[NR_IRQS];
7409 +extern cpumask_t irq_affinity[NR_IRQS];
7410 +extern void stop_this_cpu(void *);
7411 +extern int (*dump_ipi_function_ptr)(struct pt_regs *);
7412 +extern void dump_send_ipi(void);
7413 +EXPORT_SYMBOL(_irq_desc);
7414 +EXPORT_SYMBOL(irq_affinity);
7415 +EXPORT_SYMBOL(stop_this_cpu);
7416 +EXPORT_SYMBOL(dump_send_ipi);
7417 +EXPORT_SYMBOL(dump_ipi_function_ptr);
7418 +#endif
7419 +#endif
7420 +
7421 Index: linux-2.6.10-base/arch/i386/mm/init.c
7422 ===================================================================
7423 --- linux-2.6.10-base.orig/arch/i386/mm/init.c  2005-05-17 18:52:39.860066760 +0800
7424 +++ linux-2.6.10-base/arch/i386/mm/init.c       2005-05-17 18:52:39.944053992 +0800
7425 @@ -244,6 +244,13 @@
7426     return 0;
7427  }
7428  
7429 +/* To enable modules to check if a page is in RAM */
7430 +int pfn_is_ram(unsigned long pfn)
7431 +{
7432 +       return (page_is_ram(pfn));
7433 +}
7434 +
7435 +
7436  #ifdef CONFIG_HIGHMEM
7437  pte_t *kmap_pte;
7438  pgprot_t kmap_prot;
7439 Index: linux-2.6.10-base/arch/i386/Kconfig.debug
7440 ===================================================================
7441 --- linux-2.6.10-base.orig/arch/i386/Kconfig.debug      2005-05-17 18:52:38.692244296 +0800
7442 +++ linux-2.6.10-base/arch/i386/Kconfig.debug   2005-05-17 18:52:39.945053840 +0800
7443 @@ -2,6 +2,63 @@
7444  
7445  source "lib/Kconfig.debug"
7446  
7447 +config CRASH_DUMP
7448 +       tristate "Crash dump support (EXPERIMENTAL)"
7449 +       depends on EXPERIMENTAL
7450 +       default n
7451 +       ---help---
7452 +         Say Y here to enable saving an image of system memory when a panic
7453 +         or other error occurs. Dumps can also be forced with the SysRq+d
7454 +         key if MAGIC_SYSRQ is enabled.
7455 +
7456 +config KERNTYPES
7457 +       bool
7458 +       depends on CRASH_DUMP
7459 +       default y
7460 +
7461 +config CRASH_DUMP_BLOCKDEV
7462 +       tristate "Crash dump block device driver"
7463 +       depends on CRASH_DUMP
7464 +       help
7465 +         Say Y to allow saving crash dumps directly to a disk device.
7466 +
7467 +config CRASH_DUMP_NETDEV
7468 +       tristate "Crash dump network device driver"
7469 +       depends on CRASH_DUMP
7470 +       help
7471 +         Say Y to allow saving crash dumps over a network device.
7472 +
7473 +config CRASH_DUMP_MEMDEV
7474 +       bool "Crash dump staged memory driver"
7475 +       depends on CRASH_DUMP
7476 +       help
7477 +         Say Y to allow intermediate saving crash dumps in spare 
7478 +         memory pages which would then be written out to disk
7479 +         later.
7480 +
7481 +config CRASH_DUMP_SOFTBOOT
7482 +       bool "Save crash dump across a soft reboot"
7483 +       depends on CRASH_DUMP_MEMDEV
7484 +       help
7485 +         Say Y to allow a crash dump to be preserved in memory
7486 +         pages across a soft reboot and written out to disk
7487 +         thereafter. For this to work, CRASH_DUMP must be 
7488 +         configured as part of the kernel (not as a module).
7489 +
7490 +config CRASH_DUMP_COMPRESS_RLE
7491 +       tristate "Crash dump RLE compression"
7492 +       depends on CRASH_DUMP
7493 +       help
7494 +         Say Y to allow saving dumps with Run Length Encoding compression.
7495 +
7496 +config CRASH_DUMP_COMPRESS_GZIP
7497 +       tristate "Crash dump GZIP compression"
7498 +       select ZLIB_INFLATE
7499 +       select ZLIB_DEFLATE
7500 +       depends on CRASH_DUMP
7501 +       help
7502 +         Say Y to allow saving dumps with Gnu Zip compression.
7503 +
7504  config EARLY_PRINTK
7505         bool "Early printk" if EMBEDDED
7506         default y
7507 @@ -15,8 +72,8 @@
7508           with klogd/syslogd or the X server. You should normally N here,
7509           unless you want to debug such a crash.
7510  
7511 -config DEBUG_STACKOVERFLOW
7512 -       bool "Check for stack overflows"
7513 +config DEBUG_STACKOVERFLOW 
7514 +       bool "Check for stack overflows" 
7515         depends on DEBUG_KERNEL
7516  
7517  config KPROBES
7518 Index: linux-2.6.10-base/arch/i386/kernel/smp.c
7519 ===================================================================
7520 --- linux-2.6.10-base.orig/arch/i386/kernel/smp.c       2005-05-17 18:52:39.858067064 +0800
7521 +++ linux-2.6.10-base/arch/i386/kernel/smp.c    2005-05-17 18:52:39.945053840 +0800
7522 @@ -19,6 +19,7 @@
7523  #include <linux/mc146818rtc.h>
7524  #include <linux/cache.h>
7525  #include <linux/interrupt.h>
7526 +#include <linux/dump.h>
7527  
7528  #include <asm/mtrr.h>
7529  #include <asm/tlbflush.h>
7530 @@ -143,6 +144,13 @@
7531          */
7532         cfg = __prepare_ICR(shortcut, vector);
7533  
7534 +       if (vector == DUMP_VECTOR) {
7535 +               /*
7536 +                * Setup DUMP IPI to be delivered as an NMI
7537 +                */
7538 +               cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
7539 +       }
7540 +
7541         /*
7542          * Send the IPI. The write to APIC_ICR fires this off.
7543          */
7544 @@ -220,6 +228,13 @@
7545                          * program the ICR 
7546                          */
7547                         cfg = __prepare_ICR(0, vector);
7548 +
7549 +                       if (vector == DUMP_VECTOR) {
7550 +                               /*
7551 +                                * Setup DUMP IPI to be delivered as an NMI
7552 +                                */
7553 +                               cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
7554 +                       }       
7555                         
7556                         /*
7557                          * Send the IPI. The write to APIC_ICR fires this off.
7558 @@ -506,6 +521,11 @@
7559  
7560  static struct call_data_struct * call_data;
7561  
7562 +void dump_send_ipi(void)
7563 +{
7564 +       send_IPI_allbutself(DUMP_VECTOR);
7565 +}
7566 +
7567  /*
7568   * this function sends a 'generic call function' IPI to all other CPUs
7569   * in the system.
7570 @@ -561,7 +581,7 @@
7571         return 0;
7572  }
7573  
7574 -static void stop_this_cpu (void * dummy)
7575 +void stop_this_cpu (void * dummy)
7576  {
7577         /*
7578          * Remove this CPU:
7579 @@ -622,4 +642,3 @@
7580                 atomic_inc(&call_data->finished);
7581         }
7582  }
7583 -
7584 Index: linux-2.6.10-base/arch/i386/kernel/traps.c
7585 ===================================================================
7586 --- linux-2.6.10-base.orig/arch/i386/kernel/traps.c     2005-05-17 18:52:39.859066912 +0800
7587 +++ linux-2.6.10-base/arch/i386/kernel/traps.c  2005-05-17 18:52:39.946053688 +0800
7588 @@ -27,6 +27,7 @@
7589  #include <linux/ptrace.h>
7590  #include <linux/utsname.h>
7591  #include <linux/kprobes.h>
7592 +#include <linux/dump.h>
7593  
7594  #ifdef CONFIG_EISA
7595  #include <linux/ioport.h>
7596 @@ -382,6 +383,7 @@
7597         bust_spinlocks(0);
7598         die.lock_owner = -1;
7599         spin_unlock_irq(&die.lock);
7600 +       dump((char *)str, regs);
7601         if (in_interrupt())
7602                 panic("Fatal exception in interrupt");
7603  
7604 @@ -654,6 +656,7 @@
7605         printk(" on CPU%d, eip %08lx, registers:\n",
7606                 smp_processor_id(), regs->eip);
7607         show_registers(regs);
7608 +       dump((char *)msg, regs);
7609         printk("console shuts up ...\n");
7610         console_silent();
7611         spin_unlock(&nmi_print_lock);
7612 Index: linux-2.6.10-base/arch/i386/kernel/setup.c
7613 ===================================================================
7614 --- linux-2.6.10-base.orig/arch/i386/kernel/setup.c     2004-12-25 05:34:45.000000000 +0800
7615 +++ linux-2.6.10-base/arch/i386/kernel/setup.c  2005-05-17 18:52:39.947053536 +0800
7616 @@ -662,6 +662,10 @@
7617   */
7618  #define LOWMEMSIZE()   (0x9f000)
7619  
7620 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
7621 +unsigned long crashdump_addr = 0xdeadbeef;
7622 +#endif
7623 +
7624  static void __init parse_cmdline_early (char ** cmdline_p)
7625  {
7626         char c = ' ', *to = command_line, *from = saved_command_line;
7627 @@ -823,6 +827,11 @@
7628                 if (c == ' ' && !memcmp(from, "vmalloc=", 8))
7629                         __VMALLOC_RESERVE = memparse(from+8, &from);
7630  
7631 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
7632 +               if (c == ' ' && !memcmp(from, "crashdump=", 10))
7633 +                   crashdump_addr = memparse(from+10, &from); 
7634 +#endif
7635 +
7636                 c = *(from++);
7637                 if (!c)
7638                         break;
7639 @@ -1288,6 +1297,10 @@
7640  
7641  static char * __init machine_specific_memory_setup(void);
7642  
7643 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
7644 +extern void crashdump_reserve(void);
7645 +#endif
7646 +
7647  /*
7648   * Determine if we were loaded by an EFI loader.  If so, then we have also been
7649   * passed the efi memmap, systab, etc., so we should use these data structures
7650 @@ -1393,6 +1406,10 @@
7651  #endif
7652  
7653  
7654 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
7655 +       crashdump_reserve(); /* Preserve crash dump state from prev boot */
7656 +#endif
7657 +
7658         dmi_scan_machine();
7659  
7660  #ifdef CONFIG_X86_GENERICARCH
7661 Index: linux-2.6.10-base/arch/i386/kernel/i386_ksyms.c
7662 ===================================================================
7663 --- linux-2.6.10-base.orig/arch/i386/kernel/i386_ksyms.c        2004-12-25 05:35:40.000000000 +0800
7664 +++ linux-2.6.10-base/arch/i386/kernel/i386_ksyms.c     2005-05-17 18:52:39.947053536 +0800
7665 @@ -16,6 +16,7 @@
7666  #include <linux/tty.h>
7667  #include <linux/highmem.h>
7668  #include <linux/time.h>
7669 +#include <linux/nmi.h>
7670  
7671  #include <asm/semaphore.h>
7672  #include <asm/processor.h>
7673 @@ -31,6 +32,7 @@
7674  #include <asm/tlbflush.h>
7675  #include <asm/nmi.h>
7676  #include <asm/ist.h>
7677 +#include <asm/e820.h>
7678  #include <asm/kdebug.h>
7679  
7680  extern void dump_thread(struct pt_regs *, struct user *);
7681 @@ -192,3 +194,20 @@
7682  #endif
7683  
7684  EXPORT_SYMBOL(csum_partial);
7685 +
7686 +#ifdef CONFIG_CRASH_DUMP_MODULE
7687 +#ifdef CONFIG_SMP
7688 +extern irq_desc_t irq_desc[NR_IRQS];
7689 +extern cpumask_t irq_affinity[NR_IRQS];
7690 +extern void stop_this_cpu(void *);
7691 +EXPORT_SYMBOL(irq_desc);
7692 +EXPORT_SYMBOL(irq_affinity);
7693 +EXPORT_SYMBOL(stop_this_cpu);
7694 +EXPORT_SYMBOL(dump_send_ipi);
7695 +#endif
7696 +extern int pfn_is_ram(unsigned long);
7697 +EXPORT_SYMBOL(pfn_is_ram);
7698 +#ifdef ARCH_HAS_NMI_WATCHDOG
7699 +EXPORT_SYMBOL(touch_nmi_watchdog);
7700 +#endif
7701 +#endif
7702 Index: linux-2.6.10-base/arch/ppc64/Kconfig.debug
7703 ===================================================================
7704 --- linux-2.6.10-base.orig/arch/ppc64/Kconfig.debug     2004-12-25 05:35:27.000000000 +0800
7705 +++ linux-2.6.10-base/arch/ppc64/Kconfig.debug  2005-05-17 18:52:39.947053536 +0800
7706 @@ -2,6 +2,64 @@
7707  
7708  source "lib/Kconfig.debug"
7709  
7710 +config KERNTYPES
7711 +       bool
7712 +       depends on CRASH_DUMP
7713 +       default y
7714 +
7715 +config CRASH_DUMP
7716 +       tristate "Crash dump support"
7717 +       default n
7718 +       ---help---
7719 +          Say Y here to enable saving an image of system memory when a panic
7720 +          or other error occurs. Dumps can also be forced with the SysRq+d
7721 +          key if MAGIC_SYSRQ is enabled.
7722 +
7723 +config CRASH_DUMP_BLOCKDEV
7724 +       tristate "Crash dump block device driver"
7725 +       depends on CRASH_DUMP
7726 +       help
7727 +         Say Y to allow saving crash dumps directly to a disk device.
7728 +       
7729 +config CRASH_DUMP_NETDEV
7730 +       tristate "Crash dump network device driver"
7731 +       depends on CRASH_DUMP
7732 +       help
7733 +         Say Y to allow saving crash dumps over a network device.
7734 +
7735 +config CRASH_DUMP_MEMDEV
7736 +       bool "Crash dump staged memory driver"
7737 +       depends on CRASH_DUMP
7738 +       help
7739 +         Say Y to allow intermediate saving crash dumps in spare
7740 +         memory pages which would then be written out to disk
7741 +         later. Need 'kexec' support for this to work.
7742 +            **** Not supported at present ****
7743 +
7744 +config CRASH_DUMP_SOFTBOOT
7745 +       bool "Save crash dump across a soft reboot"
7746 +       help
7747 +         Say Y to allow a crash dump to be preserved in memory
7748 +         pages across a soft reboot and written out to disk
7749 +         thereafter. For this to work, CRASH_DUMP must be
7750 +         configured as part of the kernel (not as a module).
7751 +         Need 'kexec' support to use this option.
7752 +           **** Not supported at present ****
7753 +
7754 +config CRASH_DUMP_COMPRESS_RLE
7755 +       tristate "Crash dump RLE compression"
7756 +       depends on CRASH_DUMP
7757 +       help
7758 +         Say Y to allow saving dumps with Run Length Encoding compression.
7759 +
7760 +config CRASH_DUMP_COMPRESS_GZIP
7761 +       tristate "Crash dump GZIP compression"
7762 +       select ZLIB_INFLATE
7763 +       select ZLIB_DEFLATE
7764 +       depends on CRASH_DUMP
7765 +       help
7766 +         Say Y to allow saving dumps with Gnu Zip compression.
7767 +
7768  config DEBUG_STACKOVERFLOW
7769         bool "Check for stack overflows"
7770         depends on DEBUG_KERNEL
7771 Index: linux-2.6.10-base/arch/ppc64/kernel/smp.c
7772 ===================================================================
7773 --- linux-2.6.10-base.orig/arch/ppc64/kernel/smp.c      2004-12-25 05:35:23.000000000 +0800
7774 +++ linux-2.6.10-base/arch/ppc64/kernel/smp.c   2005-05-17 18:52:39.948053384 +0800
7775 @@ -30,6 +30,7 @@
7776  #include <linux/spinlock.h>
7777  #include <linux/cache.h>
7778  #include <linux/err.h>
7779 +#include <linux/dump.h>
7780  #include <linux/sysdev.h>
7781  #include <linux/cpu.h>
7782  
7783 @@ -71,6 +72,7 @@
7784  struct smp_ops_t *smp_ops;
7785  
7786  static volatile unsigned int cpu_callin_map[NR_CPUS];
7787 +static int (*dump_ipi_function_ptr)(struct pt_regs *) = NULL;
7788  
7789  extern unsigned char stab_array[];
7790  
7791 @@ -177,9 +179,16 @@
7792                 /* spare */
7793                 break;
7794  #endif
7795 -#ifdef CONFIG_DEBUGGER
7796 +#if defined(CONFIG_DEBUGGER) || defined(CONFIG_CRASH_DUMP) \
7797 +       || defined(CONFIG_CRASH_DUMP_MODULE)
7798         case PPC_MSG_DEBUGGER_BREAK:
7799 -               debugger_ipi(regs);
7800 +               if (dump_ipi_function_ptr) {
7801 +                       dump_ipi_function_ptr(regs);
7802 +               }
7803 +#ifdef CONFIG_DEBUGGER
7804 +               else
7805 +                       debugger_ipi(regs);
7806 +#endif
7807                 break;
7808  #endif
7809         default:
7810 @@ -201,7 +210,16 @@
7811  }
7812  #endif
7813  
7814 -static void stop_this_cpu(void *dummy)
7815 +void dump_send_ipi(int (*dump_ipi_callback)(struct pt_regs *))
7816 +{
7817 +       dump_ipi_function_ptr = dump_ipi_callback;
7818 +       if (dump_ipi_callback) {
7819 +               mb();
7820 +               smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK);
7821 +       }
7822 +}
7823 +
7824 +void stop_this_cpu(void *dummy)
7825  {
7826         local_irq_disable();
7827         while (1)
7828 Index: linux-2.6.10-base/arch/ppc64/kernel/traps.c
7829 ===================================================================
7830 --- linux-2.6.10-base.orig/arch/ppc64/kernel/traps.c    2004-12-25 05:34:47.000000000 +0800
7831 +++ linux-2.6.10-base/arch/ppc64/kernel/traps.c 2005-05-17 18:52:39.948053384 +0800
7832 @@ -29,6 +29,7 @@
7833  #include <linux/interrupt.h>
7834  #include <linux/init.h>
7835  #include <linux/module.h>
7836 +#include <linux/dump.h>
7837  
7838  #include <asm/pgtable.h>
7839  #include <asm/uaccess.h>
7840 @@ -116,6 +117,7 @@
7841         if (nl)
7842                 printk("\n");
7843         show_regs(regs);
7844 +       dump((char *)str, regs);
7845         bust_spinlocks(0);
7846         spin_unlock_irq(&die_lock);
7847  
7848 Index: linux-2.6.10-base/arch/ppc64/kernel/ppc_ksyms.c
7849 ===================================================================
7850 --- linux-2.6.10-base.orig/arch/ppc64/kernel/ppc_ksyms.c        2004-12-25 05:34:26.000000000 +0800
7851 +++ linux-2.6.10-base/arch/ppc64/kernel/ppc_ksyms.c     2005-05-17 18:52:39.948053384 +0800
7852 @@ -159,6 +159,17 @@
7853  EXPORT_SYMBOL(get_wchan);
7854  EXPORT_SYMBOL(console_drivers);
7855  
7856 +#ifdef CONFIG_CRASH_DUMP_MODULE
7857 +extern int dump_page_is_ram(unsigned long);
7858 +EXPORT_SYMBOL(dump_page_is_ram);
7859 +#ifdef CONFIG_SMP
7860 +EXPORT_SYMBOL(irq_affinity);
7861 +extern void stop_this_cpu(void *);
7862 +EXPORT_SYMBOL(stop_this_cpu);
7863 +EXPORT_SYMBOL(dump_send_ipi);
7864 +#endif
7865 +#endif
7866 +
7867  EXPORT_SYMBOL(tb_ticks_per_usec);
7868  EXPORT_SYMBOL(paca);
7869  EXPORT_SYMBOL(cur_cpu_spec);
7870 Index: linux-2.6.10-base/arch/ppc64/kernel/lmb.c
7871 ===================================================================
7872 --- linux-2.6.10-base.orig/arch/ppc64/kernel/lmb.c      2004-12-25 05:34:58.000000000 +0800
7873 +++ linux-2.6.10-base/arch/ppc64/kernel/lmb.c   2005-05-17 18:52:39.949053232 +0800
7874 @@ -344,3 +344,31 @@
7875  
7876         return pa;
7877  }
7878 +
7879 +
7880 +/*
7881 + * This is the copy of page_is_ram (mm/init.c). The difference is 
7882 + * it identifies all memory holes.
7883 + */
7884 +int dump_page_is_ram(unsigned long pfn)
7885 +{
7886 +        int i;
7887 +       unsigned long paddr = (pfn << PAGE_SHIFT);
7888 +
7889 +       for (i=0; i < lmb.memory.cnt ;i++) {
7890 +               unsigned long base;
7891 +
7892 +#ifdef CONFIG_MSCHUNKS
7893 +               base = lmb.memory.region[i].physbase;
7894 +#else
7895 +               base = lmb.memory.region[i].base;
7896 +#endif
7897 +               if ((paddr >= base) &&
7898 +                       (paddr < (base + lmb.memory.region[i].size))) {
7899 +                       return 1;
7900 +               }
7901 +       }
7902 +
7903 +       return 0;
7904 +}
7905 +
7906 Index: linux-2.6.10-base/arch/ppc64/kernel/xics.c
7907 ===================================================================
7908 --- linux-2.6.10-base.orig/arch/ppc64/kernel/xics.c     2004-12-25 05:34:58.000000000 +0800
7909 +++ linux-2.6.10-base/arch/ppc64/kernel/xics.c  2005-05-17 18:52:39.949053232 +0800
7910 @@ -421,7 +421,8 @@
7911                         smp_message_recv(PPC_MSG_MIGRATE_TASK, regs);
7912                 }
7913  #endif
7914 -#ifdef CONFIG_DEBUGGER
7915 +#if defined(CONFIG_DEBUGGER) || defined(CONFIG_CRASH_DUMP) \
7916 +       || defined(CONFIG_CRASH_DUMP_MODULE)
7917                 if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
7918                                        &xics_ipi_message[cpu].value)) {
7919                         mb();
7920 Index: linux-2.6.10-base/arch/s390/boot/install.sh
7921 ===================================================================
7922 --- linux-2.6.10-base.orig/arch/s390/boot/install.sh    2004-12-25 05:35:01.000000000 +0800
7923 +++ linux-2.6.10-base/arch/s390/boot/install.sh 2005-05-17 18:52:39.949053232 +0800
7924 @@ -16,7 +16,8 @@
7925  #   $1 - kernel version
7926  #   $2 - kernel image file
7927  #   $3 - kernel map file
7928 -#   $4 - default install path (blank if root directory)
7929 +#   $4 - kernel type file
7930 +#   $5 - default install path (blank if root directory)
7931  #
7932  
7933  # User may have a custom install script
7934 @@ -26,13 +27,13 @@
7935  
7936  # Default install - same as make zlilo
7937  
7938 -if [ -f $4/vmlinuz ]; then
7939 -       mv $4/vmlinuz $4/vmlinuz.old
7940 +if [ -f $5/vmlinuz ]; then
7941 +       mv $5/vmlinuz $5/vmlinuz.old
7942  fi
7943  
7944 -if [ -f $4/System.map ]; then
7945 -       mv $4/System.map $4/System.old
7946 +if [ -f $5/System.map ]; then
7947 +       mv $5/System.map $5/System.old
7948  fi
7949  
7950 -cat $2 > $4/vmlinuz
7951 -cp $3 $4/System.map
7952 +cat $2 > $5/vmlinuz
7953 +cp $3 $5/System.map
7954 Index: linux-2.6.10-base/arch/s390/boot/Makefile
7955 ===================================================================
7956 --- linux-2.6.10-base.orig/arch/s390/boot/Makefile      2004-12-25 05:35:49.000000000 +0800
7957 +++ linux-2.6.10-base/arch/s390/boot/Makefile   2005-05-17 18:52:39.950053080 +0800
7958 @@ -15,4 +15,4 @@
7959  
7960  install: $(CONFIGURE) $(obj)/image
7961         sh -x  $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/image \
7962 -             System.map Kerntypes "$(INSTALL_PATH)"
7963 +             System.map init/Kerntypes "$(INSTALL_PATH)"
7964 Index: linux-2.6.10-base/arch/s390/Kconfig.debug
7965 ===================================================================
7966 --- linux-2.6.10-base.orig/arch/s390/Kconfig.debug      2004-12-25 05:34:31.000000000 +0800
7967 +++ linux-2.6.10-base/arch/s390/Kconfig.debug   2005-05-17 18:52:39.950053080 +0800
7968 @@ -2,4 +2,13 @@
7969  
7970  source "lib/Kconfig.debug"
7971  
7972 +config KERNTYPES
7973 +       bool "Kerntypes debugging information"
7974 +       default y
7975 +       ---help---
7976 +         Say Y here to save additional kernel debugging information in the
7977 +         file init/kerntypes.o. This information is used by crash analysis
7978 +         tools such as lcrash to assign structures to kernel addresses.
7979 +
7980 +
7981  endmenu
7982 Index: linux-2.6.10-base/arch/x86_64/mm/init.c
7983 ===================================================================
7984 --- linux-2.6.10-base.orig/arch/x86_64/mm/init.c        2005-04-06 23:38:35.000000000 +0800
7985 +++ linux-2.6.10-base/arch/x86_64/mm/init.c     2005-05-17 18:52:39.950053080 +0800
7986 @@ -378,7 +378,7 @@
7987         __flush_tlb_all();
7988  } 
7989  
7990 -static inline int page_is_ram (unsigned long pagenr)
7991 +inline int page_is_ram (unsigned long pagenr)
7992  {
7993         int i;
7994  
7995 Index: linux-2.6.10-base/arch/x86_64/Kconfig.debug
7996 ===================================================================
7997 --- linux-2.6.10-base.orig/arch/x86_64/Kconfig.debug    2004-12-25 05:34:01.000000000 +0800
7998 +++ linux-2.6.10-base/arch/x86_64/Kconfig.debug 2005-05-17 18:52:39.951052928 +0800
7999 @@ -2,6 +2,66 @@
8000  
8001  source "lib/Kconfig.debug"
8002  
8003 +config CRASH_DUMP
8004 +       tristate "Crash dump support (EXPERIMENTAL)"
8005 +       depends on EXPERIMENTAL
8006 +       default n
8007 +       ---help---
8008 +         Say Y here to enable saving an image of system memory when a panic
8009 +         or other error occurs. Dumps can also be forced with the SysRq+d
8010 +         key if MAGIC_SYSRQ is enabled.
8011 +
8012 +config KERNTYPES
8013 +       bool
8014 +       depends on CRASH_DUMP
8015 +       default y
8016 +
8017 +config CRASH_DUMP_BLOCKDEV
8018 +       tristate "Crash dump block device driver"
8019 +       depends on CRASH_DUMP
8020 +       help
8021 +         Say Y to allow saving crash dumps directly to a disk device.
8022 +
8023 +config CRASH_DUMP_NETDEV
8024 +       tristate "Crash dump network device driver"
8025 +       depends on CRASH_DUMP
8026 +       help
8027 +         Say Y to allow saving crash dumps over a network device.
8028 +
8029 +config CRASH_DUMP_MEMDEV
8030 +       bool "Crash dump staged memory driver"
8031 +       depends on CRASH_DUMP
8032 +       help
8033 +         Say Y to allow intermediate saving crash dumps in spare
8034 +         memory pages which would then be written out to disk
8035 +         later.
8036 +
8037 +config CRASH_DUMP_SOFTBOOT
8038 +       bool "Save crash dump across a soft reboot"
8039 +       depends on CRASH_DUMP_MEMDEV
8040 +       help
8041 +         Say Y to allow a crash dump to be preserved in memory
8042 +        lkcd-kernpages across a soft reboot and written out to disk
8043 +         thereafter. For this to work, CRASH_DUMP must be
8044 +         configured as part of the kernel (not as a module).
8045 +
8046 +config CRASH_DUMP_COMPRESS_RLE
8047 +       tristate "Crash dump RLE compression"
8048 +       depends on CRASH_DUMP
8049 +       help
8050 +         Say Y to allow saving dumps with Run Length Encoding compression.
8051 +
8052 +
8053 +config CRASH_DUMP_COMPRESS_GZIP
8054 +       tristate "Crash dump GZIP compression"
8055 +       select ZLIB_INFLATE
8056 +       select ZLIB_DEFLATE
8057 +       depends on CRASH_DUMP
8058 +       help
8059 +         Say Y to allow saving dumps with Gnu Zip compression.
8060 +
8061 +
8062 +
8063  # !SMP for now because the context switch early causes GPF in segment reloading
8064  # and the GS base checking does the wrong thing then, causing a hang.
8065  config CHECKING
8066 Index: linux-2.6.10-base/arch/x86_64/kernel/smp.c
8067 ===================================================================
8068 --- linux-2.6.10-base.orig/arch/x86_64/kernel/smp.c     2004-12-25 05:35:50.000000000 +0800
8069 +++ linux-2.6.10-base/arch/x86_64/kernel/smp.c  2005-05-18 15:10:46.727292816 +0800
8070 @@ -20,6 +20,7 @@
8071  #include <linux/kernel_stat.h>
8072  #include <linux/mc146818rtc.h>
8073  #include <linux/interrupt.h>
8074 +#include <linux/dump.h>
8075  
8076  #include <asm/mtrr.h>
8077  #include <asm/pgalloc.h>
8078 @@ -253,6 +254,13 @@
8079         send_IPI_allbutself(KDB_VECTOR);
8080  }
8081  
8082 +
8083 +/* void dump_send_ipi(int (*dump_ipi_handler)(struct pt_regs *)); */
8084 +void dump_send_ipi(void)
8085 +{
8086 +       send_IPI_allbutself(DUMP_VECTOR);
8087 +}
8088 +
8089  /*
8090   * this function sends a 'reschedule' IPI to another CPU.
8091   * it goes straight through and wastes no time serializing
8092 @@ -340,6 +348,18 @@
8093         return 0;
8094  }
8095  
8096 +void stop_this_cpu(void* dummy)
8097 +{
8098 +       /*
8099 +        * Remove this CPU:
8100 +        */
8101 +       cpu_clear(smp_processor_id(), cpu_online_map);
8102 +       local_irq_disable();
8103 +       disable_local_APIC();
8104 +       for (;;) 
8105 +               asm("hlt"); 
8106 +}
8107 +
8108  void smp_stop_cpu(void)
8109  {
8110         /*
8111 Index: linux-2.6.10-base/arch/x86_64/kernel/traps.c
8112 ===================================================================
8113 --- linux-2.6.10-base.orig/arch/x86_64/kernel/traps.c   2004-12-25 05:33:49.000000000 +0800
8114 +++ linux-2.6.10-base/arch/x86_64/kernel/traps.c        2005-05-17 18:52:39.952052776 +0800
8115 @@ -27,6 +27,7 @@
8116  #include <linux/spinlock.h>
8117  #include <linux/interrupt.h>
8118  #include <linux/module.h>
8119 +#include <linux/dump.h>
8120  #include <linux/moduleparam.h>
8121  
8122  #include <asm/system.h>
8123 @@ -369,6 +370,7 @@
8124         printk("\n");
8125         notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
8126         show_registers(regs);
8127 +       dump((char *)str, regs); 
8128         /* Executive summary in case the oops scrolled away */
8129         printk(KERN_ALERT "RIP ");
8130         printk_address(regs->rip); 
8131 Index: linux-2.6.10-base/arch/x86_64/kernel/pci-gart.c
8132 ===================================================================
8133 --- linux-2.6.10-base.orig/arch/x86_64/kernel/pci-gart.c        2004-12-25 05:34:32.000000000 +0800
8134 +++ linux-2.6.10-base/arch/x86_64/kernel/pci-gart.c     2005-05-17 18:52:39.952052776 +0800
8135 @@ -34,7 +34,7 @@
8136  dma_addr_t bad_dma_address;
8137  
8138  unsigned long iommu_bus_base;  /* GART remapping area (physical) */
8139 -static unsigned long iommu_size;       /* size of remapping area bytes */
8140 +unsigned long iommu_size;      /* size of remapping area bytes */
8141  static unsigned long iommu_pages;      /* .. and in pages */
8142  
8143  u32 *iommu_gatt_base;          /* Remapping table */
8144 Index: linux-2.6.10-base/arch/x86_64/kernel/setup.c
8145 ===================================================================
8146 --- linux-2.6.10-base.orig/arch/x86_64/kernel/setup.c   2004-12-25 05:33:50.000000000 +0800
8147 +++ linux-2.6.10-base/arch/x86_64/kernel/setup.c        2005-05-17 18:52:39.953052624 +0800
8148 @@ -221,6 +221,8 @@
8149         }
8150  }
8151  
8152 +unsigned long crashdump_addr = 0xdeadbeef;
8153 +
8154  static __init void parse_cmdline_early (char ** cmdline_p)
8155  {
8156         char c = ' ', *to = command_line, *from = COMMAND_LINE;
8157 @@ -311,6 +313,9 @@
8158  
8159                 if (!memcmp(from,"oops=panic", 10))
8160                         panic_on_oops = 1;
8161 +               
8162 +               if (c == ' ' && !memcmp(from, "crashdump=", 10))
8163 +                       crashdump_addr = memparse(from+10, &from);
8164  
8165         next_char:
8166                 c = *(from++);
8167 @@ -441,6 +446,10 @@
8168                 reserve_bootmem_generic(addr, PAGE_SIZE);
8169  }
8170  
8171 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
8172 +extern void crashdump_reserve(void);
8173 +#endif
8174 +
8175  void __init setup_arch(char **cmdline_p)
8176  {
8177         unsigned long low_mem_size;
8178 @@ -550,6 +559,9 @@
8179         }
8180  #endif
8181         paging_init();
8182 +#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
8183 +       crashdump_reserve(); /* Preserve crash dump state from prev boot */
8184 +#endif
8185  
8186                 check_ioapic();
8187  #ifdef CONFIG_ACPI_BOOT
8188 Index: linux-2.6.10-base/arch/x86_64/kernel/x8664_ksyms.c
8189 ===================================================================
8190 --- linux-2.6.10-base.orig/arch/x86_64/kernel/x8664_ksyms.c     2004-12-25 05:34:01.000000000 +0800
8191 +++ linux-2.6.10-base/arch/x86_64/kernel/x8664_ksyms.c  2005-05-17 18:52:39.953052624 +0800
8192 @@ -32,6 +32,7 @@
8193  #include <asm/unistd.h>
8194  #include <asm/delay.h>
8195  #include <asm/tlbflush.h>
8196 +#include <asm/e820.h>
8197  #include <asm/kdebug.h>
8198  
8199  extern spinlock_t rtc_lock;
8200 @@ -216,6 +217,20 @@
8201  extern unsigned long __supported_pte_mask;
8202  EXPORT_SYMBOL(__supported_pte_mask);
8203  
8204 +#ifdef CONFIG_CRASH_DUMP_MODULE
8205 +#ifdef CONFIG_SMP
8206 +extern irq_desc_t irq_desc[NR_IRQS];
8207 +extern cpumask_t irq_affinity[NR_IRQS];
8208 +extern void stop_this_cpu(void *);
8209 +EXPORT_SYMBOL(irq_desc);
8210 +EXPORT_SYMBOL(irq_affinity);
8211 +EXPORT_SYMBOL(dump_send_ipi);
8212 +EXPORT_SYMBOL(stop_this_cpu);
8213 +#endif
8214 +extern int page_is_ram(unsigned long);
8215 +EXPORT_SYMBOL(page_is_ram);
8216 +#endif
8217 +
8218  #ifdef CONFIG_SMP
8219  EXPORT_SYMBOL(flush_tlb_page);
8220  EXPORT_SYMBOL_GPL(flush_tlb_all);
8221 Index: linux-2.6.10-base/arch/x86_64/kernel/genapic_flat.c
8222 ===================================================================
8223 --- linux-2.6.10-base.orig/arch/x86_64/kernel/genapic_flat.c    2004-12-25 05:34:48.000000000 +0800
8224 +++ linux-2.6.10-base/arch/x86_64/kernel/genapic_flat.c 2005-05-18 15:07:54.943407936 +0800
8225 @@ -86,6 +86,13 @@
8226          */
8227         cfg = __prepare_ICR(0, vector, APIC_DEST_LOGICAL);
8228  
8229 +        if (vector == DUMP_VECTOR) {
8230 +               /*
8231 +                * Setup DUMP IPI to be delivered as an NMI
8232 +                */
8233 +                cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
8234 +        }
8235 +       
8236         /*
8237          * Send the IPI. The write to APIC_ICR fires this off.
8238          */
8239 Index: linux-2.6.10-base/scripts/mkcompile_h
8240 ===================================================================
8241 --- linux-2.6.10-base.orig/scripts/mkcompile_h  2004-12-25 05:35:50.000000000 +0800
8242 +++ linux-2.6.10-base/scripts/mkcompile_h       2005-05-17 18:52:39.953052624 +0800
8243 @@ -33,7 +33,7 @@
8244  
8245  UTS_LEN=64
8246  UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
8247 -
8248 +LINUX_COMPILE_VERSION_ID="__linux_compile_version_id__`hostname | tr -c '[0-9A-Za-z\n]' '__'`_`LANG=C date | tr -c '[0-9A-Za-z\n]' '_'`"
8249  # Generate a temporary compile.h
8250  
8251  ( echo /\* This file is auto generated, version $VERSION \*/
8252 @@ -55,6 +55,8 @@
8253    fi
8254  
8255    echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
8256 +  echo \#define LINUX_COMPILE_VERSION_ID $LINUX_COMPILE_VERSION_ID
8257 +  echo \#define LINUX_COMPILE_VERSION_ID_TYPE typedef char* "$LINUX_COMPILE_VERSION_ID""_t"
8258  ) > .tmpcompile
8259  
8260  # Only replace the real compile.h if the new one is different,
8261 Index: linux-2.6.10-base/init/main.c
8262 ===================================================================
8263 --- linux-2.6.10-base.orig/init/main.c  2005-04-06 23:38:35.000000000 +0800
8264 +++ linux-2.6.10-base/init/main.c       2005-05-17 18:52:39.954052472 +0800
8265 @@ -109,6 +109,16 @@
8266  EXPORT_SYMBOL(system_state);
8267  
8268  /*
8269 + * The kernel_magic value represents the address of _end, which allows
8270 + * namelist tools to "match" each other respectively.  That way a tool
8271 + * that looks at /dev/mem can verify that it is using the right System.map
8272 + * file -- if kernel_magic doesn't equal the namelist value of _end,
8273 + * something's wrong.
8274 + */
8275 +extern unsigned long _end;
8276 +unsigned long *kernel_magic = &_end;
8277 +
8278 +/*
8279   * Boot command-line arguments
8280   */
8281  #define MAX_INIT_ARGS 32
8282 Index: linux-2.6.10-base/init/kerntypes.c
8283 ===================================================================
8284 --- linux-2.6.10-base.orig/init/kerntypes.c     2003-09-02 06:26:13.000000000 +0800
8285 +++ linux-2.6.10-base/init/kerntypes.c  2005-05-17 18:52:39.954052472 +0800
8286 @@ -0,0 +1,40 @@
8287 +/*
8288 + * kerntypes.c
8289 + *
8290 + * Copyright (C) 2000 Tom Morano (tjm@sgi.com) and
8291 + *                    Matt D. Robinson (yakker@alacritech.com)
8292 + *
8293 + * Dummy module that includes headers for all kernel types of interest. 
8294 + * The kernel type information is used by the lcrash utility when 
8295 + * analyzing system crash dumps or the live system. Using the type 
8296 + * information for the running system, rather than kernel header files,
8297 + * makes for a more flexible and robust analysis tool.
8298 + *
8299 + * This source code is released under version 2 of the GNU GPL.
8300 + */
8301 +
8302 +#include <linux/compile.h>
8303 +#include <linux/module.h>
8304 +#include <linux/mm.h>
8305 +#include <linux/vmalloc.h>
8306 +#include <linux/config.h>
8307 +#include <linux/utsname.h>
8308 +#include <linux/kernel_stat.h>
8309 +#include <linux/dump.h>
8310 +
8311 +#include <asm/kerntypes.h>
8312 +
8313 +#ifdef LINUX_COMPILE_VERSION_ID_TYPE
8314 +/* Define version type for version validation of dump and kerntypes */
8315 +LINUX_COMPILE_VERSION_ID_TYPE;
8316 +#endif
8317 +#if defined(CONFIG_SMP) && defined(CONFIG_CRASH_DUMP)
8318 +extern struct runqueue runqueues;
8319 +struct runqueue rn;
8320 +#endif
8321 +
8322 +struct new_utsname *p;
8323 +void
8324 +kerntypes_dummy(void)
8325 +{
8326 +}
8327 Index: linux-2.6.10-base/init/version.c
8328 ===================================================================
8329 --- linux-2.6.10-base.orig/init/version.c       2004-12-25 05:34:45.000000000 +0800
8330 +++ linux-2.6.10-base/init/version.c    2005-05-17 18:52:39.954052472 +0800
8331 @@ -11,6 +11,7 @@
8332  #include <linux/uts.h>
8333  #include <linux/utsname.h>
8334  #include <linux/version.h>
8335 +#include <linux/stringify.h>
8336  
8337  #define version(a) Version_ ## a
8338  #define version_string(a) version(a)
8339 @@ -31,3 +32,6 @@
8340  const char *linux_banner = 
8341         "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
8342         LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
8343 +
8344 +const char *LINUX_COMPILE_VERSION_ID = __stringify(LINUX_COMPILE_VERSION_ID);
8345 +LINUX_COMPILE_VERSION_ID_TYPE;
8346 Index: linux-2.6.10-base/init/Makefile
8347 ===================================================================
8348 --- linux-2.6.10-base.orig/init/Makefile        2004-12-25 05:34:32.000000000 +0800
8349 +++ linux-2.6.10-base/init/Makefile     2005-05-17 18:52:39.955052320 +0800
8350 @@ -9,12 +9,20 @@
8351  mounts-$(CONFIG_BLK_DEV_INITRD)        += do_mounts_initrd.o
8352  mounts-$(CONFIG_BLK_DEV_MD)    += do_mounts_md.o
8353  
8354 +extra-$(CONFIG_KERNTYPES)      += kerntypes.o
8355 +#For IA64, compile kerntypes in dwarf-2 format.
8356 +ifeq ($(CONFIG_IA64),y)
8357 +CFLAGS_kerntypes.o             := -gdwarf-2
8358 +else
8359 +CFLAGS_kerntypes.o             := -gstabs
8360 +endif
8361 +
8362  # files to be removed upon make clean
8363  clean-files := ../include/linux/compile.h
8364  
8365  # dependencies on generated files need to be listed explicitly
8366  
8367 -$(obj)/version.o: include/linux/compile.h
8368 +$(obj)/version.o $(obj)/kerntypes.o: include/linux/compile.h
8369  
8370  # compile.h changes depending on hostname, generation number, etc,
8371  # so we regenerate it always.
8372 @@ -24,3 +32,4 @@
8373  include/linux/compile.h: FORCE
8374         @echo '  CHK     $@'
8375         @$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
8376 +
8377 Index: linux-2.6.10-base/net/Kconfig
8378 ===================================================================
8379 --- linux-2.6.10-base.orig/net/Kconfig  2005-04-06 23:38:35.000000000 +0800
8380 +++ linux-2.6.10-base/net/Kconfig       2005-05-17 18:52:39.955052320 +0800
8381 @@ -632,7 +632,7 @@
8382  endmenu
8383  
8384  config NETPOLL
8385 -       def_bool NETCONSOLE
8386 +       def_bool NETCONSOLE || CRASH_DUMP_NETDEV
8387  
8388  config NETPOLL_RX
8389         bool "Netpoll support for trapping incoming packets"
8390 Index: linux-2.6.10-base/kernel/sched.c
8391 ===================================================================
8392 --- linux-2.6.10-base.orig/kernel/sched.c       2005-05-17 18:52:39.075186080 +0800
8393 +++ linux-2.6.10-base/kernel/sched.c    2005-05-17 18:52:39.957052016 +0800
8394 @@ -54,6 +54,10 @@
8395  #define cpu_to_node_mask(cpu) (cpu_online_map)
8396  #endif
8397  
8398 +/* used to soft spin in sched while dump is in progress */
8399 +unsigned long dump_oncpu;
8400 +EXPORT_SYMBOL(dump_oncpu);
8401 +
8402  /*
8403   * Convert user-nice values [ -20 ... 0 ... 19 ]
8404   * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
8405 @@ -184,109 +188,6 @@
8406  #define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran)      \
8407                                 < (long long) (sd)->cache_hot_time)
8408  
8409 -/*
8410 - * These are the runqueue data structures:
8411 - */
8412 -
8413 -#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long))
8414 -
8415 -typedef struct runqueue runqueue_t;
8416 -
8417 -struct prio_array {
8418 -       unsigned int nr_active;
8419 -       unsigned long bitmap[BITMAP_SIZE];
8420 -       struct list_head queue[MAX_PRIO];
8421 -};
8422 -
8423 -/*
8424 - * This is the main, per-CPU runqueue data structure.
8425 - *
8426 - * Locking rule: those places that want to lock multiple runqueues
8427 - * (such as the load balancing or the thread migration code), lock
8428 - * acquire operations must be ordered by ascending &runqueue.
8429 - */
8430 -struct runqueue {
8431 -       spinlock_t lock;
8432 -
8433 -       /*
8434 -        * nr_running and cpu_load should be in the same cacheline because
8435 -        * remote CPUs use both these fields when doing load calculation.
8436 -        */
8437 -       unsigned long nr_running;
8438 -#ifdef CONFIG_SMP
8439 -       unsigned long cpu_load;
8440 -#endif
8441 -       unsigned long long nr_switches;
8442 -
8443 -       /*
8444 -        * This is part of a global counter where only the total sum
8445 -        * over all CPUs matters. A task can increase this counter on
8446 -        * one CPU and if it got migrated afterwards it may decrease
8447 -        * it on another CPU. Always updated under the runqueue lock:
8448 -        */
8449 -       unsigned long nr_uninterruptible;
8450 -
8451 -       unsigned long expired_timestamp;
8452 -       unsigned long long timestamp_last_tick;
8453 -       task_t *curr, *idle;
8454 -       struct mm_struct *prev_mm;
8455 -       prio_array_t *active, *expired, arrays[2];
8456 -       int best_expired_prio;
8457 -       atomic_t nr_iowait;
8458 -
8459 -#ifdef CONFIG_SMP
8460 -       struct sched_domain *sd;
8461 -
8462 -       /* For active balancing */
8463 -       int active_balance;
8464 -       int push_cpu;
8465 -
8466 -       task_t *migration_thread;
8467 -       struct list_head migration_queue;
8468 -#endif
8469 -
8470 -#ifdef CONFIG_SCHEDSTATS
8471 -       /* latency stats */
8472 -       struct sched_info rq_sched_info;
8473 -
8474 -       /* sys_sched_yield() stats */
8475 -       unsigned long yld_exp_empty;
8476 -       unsigned long yld_act_empty;
8477 -       unsigned long yld_both_empty;
8478 -       unsigned long yld_cnt;
8479 -
8480 -       /* schedule() stats */
8481 -       unsigned long sched_noswitch;
8482 -       unsigned long sched_switch;
8483 -       unsigned long sched_cnt;
8484 -       unsigned long sched_goidle;
8485 -
8486 -       /* pull_task() stats */
8487 -       unsigned long pt_gained[MAX_IDLE_TYPES];
8488 -       unsigned long pt_lost[MAX_IDLE_TYPES];
8489 -
8490 -       /* active_load_balance() stats */
8491 -       unsigned long alb_cnt;
8492 -       unsigned long alb_lost;
8493 -       unsigned long alb_gained;
8494 -       unsigned long alb_failed;
8495 -
8496 -       /* try_to_wake_up() stats */
8497 -       unsigned long ttwu_cnt;
8498 -       unsigned long ttwu_attempts;
8499 -       unsigned long ttwu_moved;
8500 -
8501 -       /* wake_up_new_task() stats */
8502 -       unsigned long wunt_cnt;
8503 -       unsigned long wunt_moved;
8504 -
8505 -       /* sched_migrate_task() stats */
8506 -       unsigned long smt_cnt;
8507 -
8508 -       /* sched_balance_exec() stats */
8509 -       unsigned long sbe_cnt;
8510 -#endif
8511 -};
8512  
8513  static DEFINE_PER_CPU(struct runqueue, runqueues);
8514  
8515 @@ -2535,6 +2436,15 @@
8516         unsigned long run_time;
8517         int cpu, idx;
8518  
8519 +       /*
8520 +        * If crash dump is in progress, this other cpu's
8521 +        * need to wait until it completes.
8522 +        * NB: this code is optimized away for kernels without
8523 +        * dumping enabled.
8524 +        */
8525 +       if (unlikely(dump_oncpu))
8526 +               goto dump_scheduling_disabled;
8527 +
8528         /*
8529          * Test if we are atomic.  Since do_exit() needs to call into
8530          * schedule() atomically, we ignore that path for now.
8531 @@ -2698,6 +2608,16 @@
8532         preempt_enable_no_resched();
8533         if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
8534                 goto need_resched;
8535 +
8536 +       return;
8537 +
8538 + dump_scheduling_disabled:
8539 +       /* allow scheduling only if this is the dumping cpu */
8540 +       if (dump_oncpu != smp_processor_id()+1) {
8541 +               while (dump_oncpu)
8542 +                       cpu_relax();
8543 +       }
8544 +       return;
8545  }
8546  
8547  EXPORT_SYMBOL(schedule);
8548 Index: linux-2.6.10-base/kernel/panic.c
8549 ===================================================================
8550 --- linux-2.6.10-base.orig/kernel/panic.c       2004-12-25 05:35:29.000000000 +0800
8551 +++ linux-2.6.10-base/kernel/panic.c    2005-05-17 18:52:39.957052016 +0800
8552 @@ -18,12 +18,17 @@
8553  #include <linux/sysrq.h>
8554  #include <linux/interrupt.h>
8555  #include <linux/nmi.h>
8556 +#ifdef CONFIG_KEXEC
8557 +#include <linux/kexec.h>
8558 +#endif
8559  
8560  int panic_timeout;
8561  int panic_on_oops;
8562  int tainted;
8563 +void (*dump_function_ptr)(const char *, const struct pt_regs *) = 0;
8564  
8565  EXPORT_SYMBOL(panic_timeout);
8566 +EXPORT_SYMBOL(dump_function_ptr);
8567  
8568  struct notifier_block *panic_notifier_list;
8569  
8570 @@ -71,11 +76,12 @@
8571         printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
8572         bust_spinlocks(0);
8573  
8574 +        notifier_call_chain(&panic_notifier_list, 0, buf);
8575 +       
8576  #ifdef CONFIG_SMP
8577         smp_send_stop();
8578  #endif
8579  
8580 -       notifier_call_chain(&panic_notifier_list, 0, buf);
8581  
8582         if (!panic_blink)
8583                 panic_blink = no_blink;
8584 @@ -87,6 +93,18 @@
8585                  * We can't use the "normal" timers since we just panicked..
8586                  */
8587                 printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
8588 +#ifdef CONFIG_KEXEC
8589 +{              
8590 +               struct kimage *image;
8591 +               image = xchg(&kexec_image, 0);
8592 +               if (image) {
8593 +                       printk(KERN_EMERG "by starting a new kernel ..\n");
8594 +                       mdelay(panic_timeout*1000);
8595 +                       machine_kexec(image);
8596 +               }
8597 +}
8598 +#endif
8599 +
8600                 for (i = 0; i < panic_timeout*1000; ) {
8601                         touch_nmi_watchdog();
8602                         i += panic_blink(i);
8603 Index: linux-2.6.10-base/include/linux/sysctl.h
8604 ===================================================================
8605 --- linux-2.6.10-base.orig/include/linux/sysctl.h       2005-04-06 23:38:35.000000000 +0800
8606 +++ linux-2.6.10-base/include/linux/sysctl.h    2005-05-17 18:52:39.958051864 +0800
8607 @@ -135,6 +135,7 @@
8608         KERN_HZ_TIMER=65,       /* int: hz timer on or off */
8609         KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
8610         KERN_SETUID_DUMPABLE=67, /* int: behaviour of dumps for setuid core */
8611 +       KERN_DUMP=68,           /* directory: dump parameters */
8612  };
8613  
8614  
8615 Index: linux-2.6.10-base/include/linux/dump_netdev.h
8616 ===================================================================
8617 --- linux-2.6.10-base.orig/include/linux/dump_netdev.h  2003-09-02 06:26:13.000000000 +0800
8618 +++ linux-2.6.10-base/include/linux/dump_netdev.h       2005-05-17 18:52:39.958051864 +0800
8619 @@ -0,0 +1,80 @@
8620 +/*
8621 + *  linux/drivers/net/netconsole.h
8622 + *
8623 + *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
8624 + *
8625 + *  This file contains the implementation of an IRQ-safe, crash-safe
8626 + *  kernel console implementation that outputs kernel messages to the
8627 + *  network.
8628 + *
8629 + * Modification history:
8630 + *
8631 + * 2001-09-17    started by Ingo Molnar.
8632 + */
8633 +
8634 +/****************************************************************
8635 + *      This program is free software; you can redistribute it and/or modify
8636 + *      it under the terms of the GNU General Public License as published by
8637 + *      the Free Software Foundation; either version 2, or (at your option)
8638 + *      any later version.
8639 + *
8640 + *      This program is distributed in the hope that it will be useful,
8641 + *      but WITHOUT ANY WARRANTY; without even the implied warranty of
8642 + *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8643 + *      GNU General Public License for more details.
8644 + *
8645 + *      You should have received a copy of the GNU General Public License
8646 + *      along with this program; if not, write to the Free Software
8647 + *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8648 + *
8649 + ****************************************************************/
8650 +
8651 +#define NETCONSOLE_VERSION 0x03
8652 +
8653 +enum netdump_commands {
8654 +       COMM_NONE = 0,
8655 +       COMM_SEND_MEM = 1,
8656 +       COMM_EXIT = 2,
8657 +       COMM_REBOOT = 3,
8658 +       COMM_HELLO = 4,
8659 +       COMM_GET_NR_PAGES = 5,
8660 +       COMM_GET_PAGE_SIZE = 6,
8661 +       COMM_START_NETDUMP_ACK = 7,
8662 +       COMM_GET_REGS = 8,
8663 +       COMM_GET_MAGIC = 9,
8664 +       COMM_START_WRITE_NETDUMP_ACK = 10,
8665 +};
8666 +
8667 +typedef struct netdump_req_s {
8668 +       u64 magic;
8669 +       u32 nr;
8670 +       u32 command;
8671 +       u32 from;
8672 +       u32 to;
8673 +} req_t;
8674 +
8675 +enum netdump_replies {
8676 +       REPLY_NONE = 0,
8677 +       REPLY_ERROR = 1,
8678 +       REPLY_LOG = 2,
8679 +       REPLY_MEM = 3,
8680 +       REPLY_RESERVED = 4,
8681 +       REPLY_HELLO = 5,
8682 +       REPLY_NR_PAGES = 6,
8683 +       REPLY_PAGE_SIZE = 7,
8684 +       REPLY_START_NETDUMP = 8,
8685 +       REPLY_END_NETDUMP = 9,
8686 +       REPLY_REGS = 10,
8687 +       REPLY_MAGIC = 11,
8688 +       REPLY_START_WRITE_NETDUMP = 12,
8689 +};
8690 +
8691 +typedef struct netdump_reply_s {
8692 +       u32 nr;
8693 +       u32 code;
8694 +       u32 info;
8695 +} reply_t;
8696 +
8697 +#define HEADER_LEN (1 + sizeof(reply_t))
8698 +
8699 +
8700 Index: linux-2.6.10-base/include/linux/sched.h
8701 ===================================================================
8702 --- linux-2.6.10-base.orig/include/linux/sched.h        2005-05-17 18:52:39.872064936 +0800
8703 +++ linux-2.6.10-base/include/linux/sched.h     2005-05-17 18:52:39.959051712 +0800
8704 @@ -94,6 +94,7 @@
8705  extern int nr_threads;
8706  extern int last_pid;
8707  DECLARE_PER_CPU(unsigned long, process_counts);
8708 +DECLARE_PER_CPU(struct runqueue, runqueues);
8709  extern int nr_processes(void);
8710  extern unsigned long nr_running(void);
8711  extern unsigned long nr_uninterruptible(void);
8712 @@ -760,6 +761,110 @@
8713  void yield(void);
8714  
8715  /*
8716 + * These are the runqueue data structures:
8717 + */
8718 +
8719 +#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long))
8720 +
8721 +typedef struct runqueue runqueue_t;
8722 +
8723 +struct prio_array {
8724 +       unsigned int nr_active;
8725 +       unsigned long bitmap[BITMAP_SIZE];
8726 +       struct list_head queue[MAX_PRIO];
8727 +};
8728 +
8729 +/*
8730 + * This is the main, per-CPU runqueue data structure.
8731 + *
8732 + * Locking rule: those places that want to lock multiple runqueues
8733 + * (such as the load balancing or the thread migration code), lock
8734 + * acquire operations must be ordered by ascending &runqueue.
8735 + */
8736 +struct runqueue {
8737 +       spinlock_t lock;
8738 +
8739 +       /*
8740 +        * nr_running and cpu_load should be in the same cacheline because
8741 +        * remote CPUs use both these fields when doing load calculation.
8742 +        */
8743 +       unsigned long nr_running;
8744 +#ifdef CONFIG_SMP
8745 +       unsigned long cpu_load;
8746 +#endif
8747 +       unsigned long long nr_switches;
8748 +
8749 +       /*
8750 +        * This is part of a global counter where only the total sum
8751 +        * over all CPUs matters. A task can increase this counter on
8752 +        * one CPU and if it got migrated afterwards it may decrease
8753 +        * it on another CPU. Always updated under the runqueue lock:
8754 +        */
8755 +       unsigned long nr_uninterruptible;
8756 +
8757 +       unsigned long expired_timestamp;
8758 +       unsigned long long timestamp_last_tick;
8759 +       task_t *curr, *idle;
8760 +       struct mm_struct *prev_mm;
8761 +       prio_array_t *active, *expired, arrays[2];
8762 +       int best_expired_prio;
8763 +       atomic_t nr_iowait;
8764 +
8765 +#ifdef CONFIG_SMP
8766 +       struct sched_domain *sd;
8767 +
8768 +       /* For active balancing */
8769 +       int active_balance;
8770 +       int push_cpu;
8771 +
8772 +       task_t *migration_thread;
8773 +       struct list_head migration_queue;
8774 +#endif
8775 +
8776 +#ifdef CONFIG_SCHEDSTATS
8777 +       /* latency stats */
8778 +       struct sched_info rq_sched_info;
8779 +
8780 +       /* sys_sched_yield() stats */
8781 +       unsigned long yld_exp_empty;
8782 +       unsigned long yld_act_empty;
8783 +       unsigned long yld_both_empty;
8784 +       unsigned long yld_cnt;
8785 +
8786 +       /* schedule() stats */
8787 +       unsigned long sched_noswitch;
8788 +       unsigned long sched_switch;
8789 +       unsigned long sched_cnt;
8790 +       unsigned long sched_goidle;
8791 +
8792 +       /* pull_task() stats */
8793 +       unsigned long pt_gained[MAX_IDLE_TYPES];
8794 +       unsigned long pt_lost[MAX_IDLE_TYPES];
8795 +
8796 +       /* active_load_balance() stats */
8797 +       unsigned long alb_cnt;
8798 +       unsigned long alb_lost;
8799 +       unsigned long alb_gained;
8800 +       unsigned long alb_failed;
8801 +
8802 +       /* try_to_wake_up() stats */
8803 +       unsigned long ttwu_cnt;
8804 +       unsigned long ttwu_attempts;
8805 +       unsigned long ttwu_moved;
8806 +
8807 +       /* wake_up_new_task() stats */
8808 +       unsigned long wunt_cnt;
8809 +       unsigned long wunt_moved;
8810 +
8811 +       /* sched_migrate_task() stats */
8812 +       unsigned long smt_cnt;
8813 +
8814 +       /* sched_balance_exec() stats */
8815 +       unsigned long sbe_cnt;
8816 +#endif
8817 +};
8818 +
8819 +/*
8820   * The default (Linux) execution domain.
8821   */
8822  extern struct exec_domain      default_exec_domain;
8823 Index: linux-2.6.10-base/include/linux/dumpdev.h
8824 ===================================================================
8825 --- linux-2.6.10-base.orig/include/linux/dumpdev.h      2003-09-02 06:26:13.000000000 +0800
8826 +++ linux-2.6.10-base/include/linux/dumpdev.h   2005-05-17 18:52:39.960051560 +0800
8827 @@ -0,0 +1,163 @@
8828 +/*
8829 + * Generic dump device interfaces for flexible system dump 
8830 + * (Enables variation of dump target types e.g disk, network, memory)
8831 + *
8832 + * These interfaces have evolved based on discussions on lkcd-devel. 
8833 + * Eventually the intent is to support primary and secondary or 
8834 + * alternate targets registered at the same time, with scope for 
8835 + * situation based failover or multiple dump devices used for parallel 
8836 + * dump i/o.
8837 + *
8838 + * Started: Oct 2002 - Suparna Bhattacharya (suparna@in.ibm.com)
8839 + *
8840 + * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
8841 + * Copyright (C) 2002 International Business Machines Corp. 
8842 + *
8843 + * This code is released under version 2 of the GNU GPL.
8844 + */
8845 +
8846 +#ifndef _LINUX_DUMPDEV_H
8847 +#define _LINUX_DUMPDEV_H
8848 +
8849 +#include <linux/kernel.h>
8850 +#include <linux/wait.h>
8851 +#include <linux/netpoll.h>
8852 +#include <linux/bio.h>
8853 +
8854 +/* Determined by the dump target (device) type */
8855 +
8856 +struct dump_dev;
8857 +
8858 +struct dump_dev_ops {
8859 +       int (*open)(struct dump_dev *, unsigned long); /* configure */
8860 +       int (*release)(struct dump_dev *); /* unconfigure */
8861 +       int (*silence)(struct dump_dev *); /* when dump starts */
8862 +       int (*resume)(struct dump_dev *); /* when dump is over */
8863 +       int (*seek)(struct dump_dev *, loff_t);
8864 +       /* trigger a write (async in nature typically) */
8865 +       int (*write)(struct dump_dev *, void *, unsigned long);
8866 +       /* not usually used during dump, but option available */
8867 +       int (*read)(struct dump_dev *, void *, unsigned long);
8868 +       /* use to poll for completion */
8869 +       int (*ready)(struct dump_dev *, void *); 
8870 +       int (*ioctl)(struct dump_dev *, unsigned int, unsigned long);
8871 +};
8872 +
8873 +struct dump_dev {
8874 +       char type_name[32]; /* block, net-poll etc */
8875 +       unsigned long device_id; /* interpreted differently for various types */
8876 +       struct dump_dev_ops *ops;
8877 +       struct list_head list;
8878 +       loff_t curr_offset;
8879 +       struct netpoll np;
8880 +};
8881 +
8882 +/*
8883 + * dump_dev type variations: 
8884 + */
8885 +
8886 +/* block */
8887 +struct dump_blockdev {
8888 +       struct dump_dev ddev;
8889 +       dev_t dev_id;
8890 +       struct block_device *bdev;
8891 +       struct bio *bio;
8892 +       loff_t start_offset;
8893 +       loff_t limit;
8894 +       int err;
8895 +};
8896 +
8897 +static inline struct dump_blockdev *DUMP_BDEV(struct dump_dev *dev)
8898 +{
8899 +       return container_of(dev, struct dump_blockdev, ddev);
8900 +}
8901 +
8902 +
8903 +/* mem  - for internal use by soft-boot based dumper */
8904 +struct dump_memdev {
8905 +       struct dump_dev ddev;
8906 +       unsigned long indirect_map_root;
8907 +       unsigned long nr_free;
8908 +       struct page *curr_page;
8909 +       unsigned long *curr_map;
8910 +       unsigned long curr_map_offset;
8911 +       unsigned long last_offset;
8912 +       unsigned long last_used_offset;
8913 +       unsigned long last_bs_offset;
8914 +};     
8915 +
8916 +static inline struct dump_memdev *DUMP_MDEV(struct dump_dev *dev)
8917 +{
8918 +       return container_of(dev, struct dump_memdev, ddev);
8919 +}
8920 +
8921 +/* Todo/future - meant for raw dedicated interfaces e.g. mini-ide driver */
8922 +struct dump_rdev {
8923 +       struct dump_dev ddev;
8924 +       char name[32];
8925 +       int (*reset)(struct dump_rdev *, unsigned int, 
8926 +               unsigned long);
8927 +       /* ... to do ... */
8928 +};
8929 +
8930 +/* just to get the size right when saving config across a soft-reboot */
8931 +struct dump_anydev {
8932 +       union {
8933 +               struct dump_blockdev bddev;
8934 +               /* .. add other types here .. */
8935 +       };
8936 +};
8937 +
8938 +
8939 +
8940 +/* Dump device / target operation wrappers */
8941 +/* These assume that dump_dev is initiatized to dump_config.dumper->dev */
8942 +
8943 +extern struct dump_dev *dump_dev;
8944 +
8945 +static inline int dump_dev_open(unsigned long arg)
8946 +{
8947 +       return dump_dev->ops->open(dump_dev, arg);
8948 +}
8949 +
8950 +static inline int dump_dev_release(void)
8951 +{
8952 +       return dump_dev->ops->release(dump_dev);
8953 +}
8954 +
8955 +static inline int dump_dev_silence(void)
8956 +{
8957 +       return dump_dev->ops->silence(dump_dev);
8958 +}
8959 +
8960 +static inline int dump_dev_resume(void)
8961 +{
8962 +       return dump_dev->ops->resume(dump_dev);
8963 +}
8964 +
8965 +static inline int dump_dev_seek(loff_t offset)
8966 +{
8967 +       return dump_dev->ops->seek(dump_dev, offset);
8968 +}
8969 +
8970 +static inline int dump_dev_write(void *buf, unsigned long len)
8971 +{
8972 +       return dump_dev->ops->write(dump_dev, buf, len);
8973 +}
8974 +
8975 +static inline int dump_dev_ready(void *buf)
8976 +{
8977 +       return dump_dev->ops->ready(dump_dev, buf);
8978 +}
8979 +
8980 +static inline int dump_dev_ioctl(unsigned int cmd, unsigned long arg)
8981 +{
8982 +       if (!dump_dev || !dump_dev->ops->ioctl)
8983 +               return -EINVAL;
8984 +       return dump_dev->ops->ioctl(dump_dev, cmd, arg);
8985 +}
8986 +
8987 +extern int dump_register_device(struct dump_dev *);
8988 +extern void dump_unregister_device(struct dump_dev *);
8989 +
8990 +#endif /*  _LINUX_DUMPDEV_H */
8991 Index: linux-2.6.10-base/include/linux/dump.h
8992 ===================================================================
8993 --- linux-2.6.10-base.orig/include/linux/dump.h 2003-09-02 06:26:13.000000000 +0800
8994 +++ linux-2.6.10-base/include/linux/dump.h      2005-05-17 18:52:39.960051560 +0800
8995 @@ -0,0 +1,406 @@
8996 +/*
8997 + * Kernel header file for Linux crash dumps.
8998 + *
8999 + * Created by: Matt Robinson (yakker@sgi.com)
9000 + * Copyright 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
9001 + *
9002 + * vmdump.h to dump.h by: Matt D. Robinson (yakker@sourceforge.net)
9003 + * Copyright 2001 - 2002 Matt D. Robinson.  All rights reserved.
9004 + * Copyright (C) 2002 Free Software Foundation, Inc. All rights reserved.
9005 + *
9006 + * Most of this is the same old stuff from vmdump.h, except now we're
9007 + * actually a stand-alone driver plugged into the block layer interface,
9008 + * with the exception that we now allow for compression modes externally
9009 + * loaded (e.g., someone can come up with their own).
9010 + *
9011 + * This code is released under version 2 of the GNU GPL.
9012 + */
9013 +
9014 +/* This header file includes all structure definitions for crash dumps. */
9015 +#ifndef _DUMP_H
9016 +#define _DUMP_H
9017 +
9018 +#if defined(CONFIG_CRASH_DUMP) || defined (CONFIG_CRASH_DUMP_MODULE)
9019 +
9020 +#include <linux/list.h>
9021 +#include <linux/notifier.h>
9022 +#include <linux/dumpdev.h>
9023 +#include <asm/ioctl.h>
9024 +
9025 +/* 
9026 + * Predefine default DUMP_PAGE constants, asm header may override.
9027 + *
9028 + * On ia64 discontinuous memory systems it's possible for the memory
9029 + * banks to stop at 2**12 page alignments, the smallest possible page
9030 + * size. But the system page size, PAGE_SIZE, is in fact larger.
9031 + */
9032 +#define DUMP_PAGE_SHIFT        PAGE_SHIFT
9033 +#define DUMP_PAGE_MASK         PAGE_MASK
9034 +#define DUMP_PAGE_ALIGN(addr)  PAGE_ALIGN(addr)
9035 +
9036 +/*
9037 + * Dump offset changed from 4Kb to 64Kb to support multiple PAGE_SIZE 
9038 + * (kernel page size). Assumption goes that 64K is the highest page size 
9039 + * supported 
9040 + */
9041 +
9042 +#define DUMP_HEADER_OFFSET     (1ULL << 16)
9043 +
9044 +#define OLDMINORBITS   8
9045 +#define OLDMINORMASK   ((1U << OLDMINORBITS) -1)
9046 +
9047 +/* Making DUMP_PAGE_SIZE = PAGE_SIZE, to support dumping on architectures 
9048 + * which support page sizes (PAGE_SIZE) greater than 4KB.
9049 + * Will it affect ia64 discontinuous memory systems ????
9050 + */
9051 +#define DUMP_PAGE_SIZE         PAGE_SIZE
9052 +
9053 +/* thread_info lies at the bottom of stack, (Except IA64). */
9054 +#define STACK_START_POSITION(tsk)               (tsk->thread_info)
9055 +/* 
9056 + * Predefined default memcpy() to use when copying memory to the dump buffer.
9057 + *
9058 + * On ia64 there is a heads up function that can be called to let the prom
9059 + * machine check monitor know that the current activity is risky and it should
9060 + * ignore the fault (nofault). In this case the ia64 header will redefine this
9061 + * macro to __dump_memcpy() and use it's arch specific version.
9062 + */
9063 +#define DUMP_memcpy            memcpy
9064 +#define bzero(a,b)              memset(a, 0, b)
9065 +
9066 +/* necessary header files */
9067 +#include <asm/dump.h>                  /* for architecture-specific header */
9068 +
9069 +/* 
9070 + * Size of the buffer that's used to hold:
9071 + *
9072 + *     1. the dump header (padded to fill the complete buffer)
9073 + *     2. the possibly compressed page headers and data
9074 + *   
9075 + *  = 256k for page size >= 64k
9076 + *  = 64k  for page size < 64k
9077 + */
9078 +#if (PAGE_SHIFT >= 16)
9079 +#define DUMP_BUFFER_SIZE       (256 * 1024)  /* size of dump buffer         */
9080 +#else
9081 +#define DUMP_BUFFER_SIZE       (64 * 1024)  /* size of dump buffer         */
9082 +#endif
9083 +
9084 +#define DUMP_HEADER_SIZE       DUMP_BUFFER_SIZE
9085 +
9086 +/* standard header definitions */
9087 +#define DUMP_MAGIC_NUMBER      0xa8190173618f23edULL  /* dump magic number */
9088 +#define DUMP_MAGIC_LIVE                0xa8190173618f23cdULL  /* live magic number */
9089 +#define DUMP_VERSION_NUMBER    0x8     /* dump version number              */
9090 +#define DUMP_PANIC_LEN         0x100   /* dump panic string length         */
9091 +
9092 +/* dump levels - type specific stuff added later -- add as necessary */
9093 +#define DUMP_LEVEL_NONE                0x0     /* no dumping at all -- just bail   */
9094 +#define DUMP_LEVEL_HEADER      0x1     /* kernel dump header only          */
9095 +#define DUMP_LEVEL_KERN                0x2     /* dump header and kernel pages     */
9096 +#define DUMP_LEVEL_USED                0x4     /* dump header, kernel/user pages   */
9097 +#define DUMP_LEVEL_ALL_RAM     0x8     /* dump header, all RAM pages       */
9098 +#define DUMP_LEVEL_ALL         0x10    /* dump all memory RAM and firmware */
9099 +
9100 +
9101 +/* dump compression options -- add as necessary */
9102 +#define DUMP_COMPRESS_NONE     0x0     /* don't compress this dump         */
9103 +#define DUMP_COMPRESS_RLE      0x1     /* use RLE compression              */
9104 +#define DUMP_COMPRESS_GZIP     0x2     /* use GZIP compression             */
9105 +
9106 +/* dump flags - any dump-type specific flags -- add as necessary */
9107 +#define DUMP_FLAGS_NONE                0x0     /* no flags are set for this dump   */
9108 +#define DUMP_FLAGS_SOFTBOOT    0x2     /* 2 stage soft-boot based dump     */
9109 +#define DUMP_FLAGS_NONDISRUPT   0X1    /* non-disruptive dumping           */
9110 +
9111 +#define DUMP_FLAGS_TARGETMASK  0xf0000000 /* handle special case targets   */
9112 +#define DUMP_FLAGS_DISKDUMP    0x80000000 /* dump to local disk            */
9113 +#define DUMP_FLAGS_NETDUMP     0x40000000 /* dump over the network         */
9114 +
9115 +/* dump header flags -- add as necessary */
9116 +#define DUMP_DH_FLAGS_NONE     0x0     /* no flags set (error condition!)  */
9117 +#define DUMP_DH_RAW            0x1     /* raw page (no compression)        */
9118 +#define DUMP_DH_COMPRESSED     0x2     /* page is compressed               */
9119 +#define DUMP_DH_END            0x4     /* end marker on a full dump        */
9120 +#define DUMP_DH_TRUNCATED      0x8     /* dump is incomplete               */
9121 +#define DUMP_DH_TEST_PATTERN   0x10    /* dump page is a test pattern      */
9122 +#define DUMP_DH_NOT_USED       0x20    /* 1st bit not used in flags        */
9123 +
9124 +/* names for various dump parameters in /proc/kernel */
9125 +#define DUMP_ROOT_NAME         "sys/dump"
9126 +#define DUMP_DEVICE_NAME       "device"
9127 +#define DUMP_COMPRESS_NAME     "compress"
9128 +#define DUMP_LEVEL_NAME                "level"
9129 +#define DUMP_FLAGS_NAME                "flags"
9130 +#define DUMP_ADDR_NAME         "addr"
9131 +
9132 +#define DUMP_SYSRQ_KEY         'd'     /* key to use for MAGIC_SYSRQ key   */
9133 +
9134 +/* CTL_DUMP names: */
9135 +enum
9136 +{
9137 +       CTL_DUMP_DEVICE=1,
9138 +       CTL_DUMP_COMPRESS=3,
9139 +       CTL_DUMP_LEVEL=3,
9140 +       CTL_DUMP_FLAGS=4,
9141 +       CTL_DUMP_ADDR=5,
9142 +       CTL_DUMP_TEST=6,
9143 +};
9144 +
9145 +
9146 +/* page size for gzip compression -- buffered slightly beyond hardware PAGE_SIZE used by DUMP */
9147 +#define DUMP_DPC_PAGE_SIZE     (DUMP_PAGE_SIZE + 512)
9148 +
9149 +/* dump ioctl() control options */
9150 +#define DIOSDUMPDEV     _IOW('p', 0xA0, unsigned int)  /* set the dump device              */
9151 +#define DIOGDUMPDEV     _IOR('p', 0xA1, unsigned int)  /* get the dump device              */
9152 +#define DIOSDUMPLEVEL   _IOW('p', 0xA2, unsigned int)  /* set the dump level               */
9153 +#define DIOGDUMPLEVEL   _IOR('p', 0xA3, unsigned int)  /* get the dump level               */
9154 +#define DIOSDUMPFLAGS   _IOW('p', 0xA4, unsigned int)  /* set the dump flag parameters     */
9155 +#define DIOGDUMPFLAGS   _IOR('p', 0xA5, unsigned int)  /* get the dump flag parameters     */
9156 +#define DIOSDUMPCOMPRESS _IOW('p', 0xA6, unsigned int) /* set the dump compress level      */
9157 +#define DIOGDUMPCOMPRESS _IOR('p', 0xA7, unsigned int) /* get the dump compress level      */
9158 +
9159 +/* these ioctls are used only by netdump module */
9160 +#define DIOSTARGETIP    _IOW('p', 0xA8, unsigned int)  /* set the target m/c's ip           */
9161 +#define DIOGTARGETIP    _IOR('p', 0xA9, unsigned int)  /* get the target m/c's ip           */
9162 +#define DIOSTARGETPORT  _IOW('p', 0xAA, unsigned int) /* set the target m/c's port          */
9163 +#define DIOGTARGETPORT  _IOR('p', 0xAB, unsigned int) /* get the target m/c's port          */
9164 +#define DIOSSOURCEPORT  _IOW('p', 0xAC, unsigned int) /* set the source m/c's port          */
9165 +#define DIOGSOURCEPORT  _IOR('p', 0xAD, unsigned int) /* get the source m/c's port          */
9166 +#define DIOSETHADDR     _IOW('p', 0xAE, unsigned int) /* set ethernet address      */
9167 +#define DIOGETHADDR     _IOR('p', 0xAF, unsigned int) /* get ethernet address       */
9168 +#define DIOGDUMPOKAY   _IOR('p', 0xB0, unsigned int) /* check if dump is configured      */
9169 +#define DIOSDUMPTAKE    _IOW('p', 0xB1, unsigned int) /* Take a manual dump               */
9170 +
9171 +/*
9172 + * Structure: __dump_header
9173 + *  Function: This is the header dumped at the top of every valid crash
9174 + *            dump.  
9175 + */
9176 +struct __dump_header {
9177 +       /* the dump magic number -- unique to verify dump is valid */
9178 +       u64     dh_magic_number;
9179 +
9180 +       /* the version number of this dump */
9181 +       u32     dh_version;
9182 +
9183 +       /* the size of this header (in case we can't read it) */
9184 +       u32     dh_header_size;
9185 +
9186 +       /* the level of this dump (just a header?) */
9187 +       u32     dh_dump_level;
9188 +
9189 +       /* 
9190 +        * We assume dump_page_size to be 4K in every case.
9191 +        * Store here the configurable system page size (4K, 8K, 16K, etc.) 
9192 +        */
9193 +       u32     dh_page_size;
9194 +
9195 +       /* the size of all physical memory */
9196 +       u64     dh_memory_size;
9197 +
9198 +       /* the start of physical memory */
9199 +       u64     dh_memory_start;
9200 +
9201 +       /* the end of physical memory */
9202 +       u64     dh_memory_end;
9203 +
9204 +       /* the number of hardware/physical pages in this dump specifically */
9205 +       u32     dh_num_dump_pages;
9206 +
9207 +       /* the panic string, if available */
9208 +       char    dh_panic_string[DUMP_PANIC_LEN];
9209 +
9210 +       /* timeval depends on architecture, two long values */
9211 +       struct {
9212 +               u64 tv_sec;
9213 +               u64 tv_usec;
9214 +       } dh_time; /* the time of the system crash */
9215 +
9216 +       /* the NEW utsname (uname) information -- in character form */
9217 +       /* we do this so we don't have to include utsname.h         */
9218 +       /* plus it helps us be more architecture independent        */
9219 +       /* now maybe one day soon they'll make the [65] a #define!  */
9220 +       char    dh_utsname_sysname[65];
9221 +       char    dh_utsname_nodename[65];
9222 +       char    dh_utsname_release[65];
9223 +       char    dh_utsname_version[65];
9224 +       char    dh_utsname_machine[65];
9225 +       char    dh_utsname_domainname[65];
9226 +
9227 +       /* the address of current task (OLD = void *, NEW = u64) */
9228 +       u64     dh_current_task;
9229 +
9230 +       /* what type of compression we're using in this dump (if any) */
9231 +       u32     dh_dump_compress;
9232 +
9233 +       /* any additional flags */
9234 +       u32     dh_dump_flags;
9235 +
9236 +       /* any additional flags */
9237 +       u32     dh_dump_device;
9238 +} __attribute__((packed));
9239 +
9240 +/*
9241 + * Structure: __dump_page
9242 + *  Function: To act as the header associated to each physical page of
9243 + *            memory saved in the system crash dump.  This allows for
9244 + *            easy reassembly of each crash dump page.  The address bits
9245 + *            are split to make things easier for 64-bit/32-bit system
9246 + *            conversions.
9247 + *
9248 + * dp_byte_offset and dp_page_index are landmarks that are helpful when
9249 + * looking at a hex dump of /dev/vmdump,
9250 + */
9251 +struct __dump_page {
9252 +       /* the address of this dump page */
9253 +       u64     dp_address;
9254 +
9255 +       /* the size of this dump page */
9256 +       u32     dp_size;
9257 +
9258 +       /* flags (currently DUMP_COMPRESSED, DUMP_RAW or DUMP_END) */
9259 +       u32     dp_flags;
9260 +} __attribute__((packed));
9261 +
9262 +/*
9263 + * Structure: __lkcdinfo
9264 + * Function:  This structure contains information needed for the lkcdutils
9265 + *            package (particularly lcrash) to determine what information is
9266 + *            associated to this kernel, specifically.
9267 + */
9268 +struct __lkcdinfo {
9269 +       int     arch;
9270 +       int     ptrsz;
9271 +       int     byte_order;
9272 +       int     linux_release;
9273 +       int     page_shift;
9274 +       int     page_size;
9275 +       u64     page_mask;
9276 +       u64     page_offset;
9277 +       int     stack_offset;
9278 +};
9279 +
9280 +#ifdef __KERNEL__
9281 +
9282 +/*
9283 + * Structure: __dump_compress
9284 + *  Function: This is what an individual compression mechanism can use
9285 + *            to plug in their own compression techniques.  It's always
9286 + *            best to build these as individual modules so that people
9287 + *            can put in whatever they want.
9288 + */
9289 +struct __dump_compress {
9290 +       /* the list_head structure for list storage */
9291 +       struct list_head list;
9292 +
9293 +       /* the type of compression to use (DUMP_COMPRESS_XXX) */
9294 +       int compress_type;
9295 +       const char *compress_name;
9296 +
9297 +       /* the compression function to call */
9298 +       u32 (*compress_func)(const u8 *, u32, u8 *, u32, unsigned long);
9299 +};
9300 +
9301 +/* functions for dump compression registration */
9302 +extern void dump_register_compression(struct __dump_compress *);
9303 +extern void dump_unregister_compression(int);
9304 +
9305 +/*
9306 + * Structure dump_mbank[]:
9307 + *
9308 + * For CONFIG_DISCONTIGMEM systems this array specifies the
9309 + * memory banks/chunks that need to be dumped after a panic.
9310 + *
9311 + * For classic systems it specifies a single set of pages from
9312 + * 0 to max_mapnr.
9313 + */
9314 +struct __dump_mbank {
9315 +       u64     start;
9316 +       u64     end;
9317 +       int     type;
9318 +       int     pad1;
9319 +       long    pad2;
9320 +};
9321 +
9322 +#define DUMP_MBANK_TYPE_CONVENTIONAL_MEMORY            1
9323 +#define DUMP_MBANK_TYPE_OTHER                          2
9324 +
9325 +#define MAXCHUNKS 256
9326 +extern int dump_mbanks;
9327 +extern struct __dump_mbank dump_mbank[MAXCHUNKS];
9328 +
9329 +/* notification event codes */
9330 +#define DUMP_BEGIN             0x0001  /* dump beginning */
9331 +#define DUMP_END               0x0002  /* dump ending */
9332 +
9333 +/* Scheduler soft spin control.
9334 + *
9335 + * 0 - no dump in progress
9336 + * 1 - cpu0 is dumping, ...
9337 + */
9338 +extern unsigned long dump_oncpu;
9339 +extern void dump_execute(const char *, const struct pt_regs *);
9340 +
9341 +/*
9342 + *     Notifier list for kernel code which wants to be called
9343 + *     at kernel dump. 
9344 + */
9345 +extern struct notifier_block *dump_notifier_list;
9346 +static inline int register_dump_notifier(struct notifier_block *nb)
9347 +{
9348 +       return notifier_chain_register(&dump_notifier_list, nb);
9349 +}
9350 +static inline int unregister_dump_notifier(struct notifier_block * nb)
9351 +{
9352 +       return notifier_chain_unregister(&dump_notifier_list, nb);
9353 +}
9354 +
9355 +extern void (*dump_function_ptr)(const char *, const struct pt_regs *);
9356 +static inline void dump(char * str, struct pt_regs * regs)
9357 +{
9358 +       if (dump_function_ptr)
9359 +               dump_function_ptr(str, regs);
9360 +}
9361 +
9362 +/*
9363 + * Common Arch Specific Functions should be declared here.
9364 + * This allows the C compiler to detect discrepancies.
9365 + */
9366 +extern void    __dump_open(void);
9367 +extern void    __dump_cleanup(void);
9368 +extern void    __dump_clean_irq_state(void);
9369 +extern void    __dump_init(u64);
9370 +extern void    __dump_save_regs(struct pt_regs *, const struct pt_regs *);
9371 +extern void    __dump_save_context(int cpu, const struct pt_regs *, struct task_struct *tsk);
9372 +extern int     __dump_configure_header(const struct pt_regs *);
9373 +extern int     __dump_irq_enable(void);
9374 +extern void    __dump_irq_restore(void);
9375 +extern int     __dump_page_valid(unsigned long index);
9376 +#ifdef CONFIG_SMP
9377 +extern void    __dump_save_other_cpus(void);
9378 +#else
9379 +#define        __dump_save_other_cpus()
9380 +#endif
9381 +
9382 +extern int manual_handle_crashdump(void);
9383 +
9384 +/* to track all used (compound + zero order) pages */
9385 +#define PageInuse(p)   (PageCompound(p) || page_count(p))
9386 +
9387 +#endif /* __KERNEL__ */
9388 +
9389 +#else  /* !CONFIG_CRASH_DUMP */
9390 +
9391 +/* If not configured then make code disappear! */
9392 +#define register_dump_watchdog(x)      do { } while(0)
9393 +#define unregister_dump_watchdog(x)    do { } while(0)
9394 +#define register_dump_notifier(x)      do { } while(0)
9395 +#define unregister_dump_notifier(x)    do { } while(0)
9396 +#define dump_in_progress()             0
9397 +#define dump(x, y)                     do { } while(0)
9398 +
9399 +#endif /* !CONFIG_CRASH_DUMP */
9400 +
9401 +#endif /* _DUMP_H */
9402 Index: linux-2.6.10-base/include/linux/miscdevice.h
9403 ===================================================================
9404 --- linux-2.6.10-base.orig/include/linux/miscdevice.h   2004-12-25 05:34:58.000000000 +0800
9405 +++ linux-2.6.10-base/include/linux/miscdevice.h        2005-05-17 18:52:39.961051408 +0800
9406 @@ -25,6 +25,7 @@
9407  #define MICROCODE_MINOR                184
9408  #define MWAVE_MINOR    219             /* ACP/Mwave Modem */
9409  #define MPT_MINOR      220
9410 +#define CRASH_DUMP_MINOR   230         /* LKCD */
9411  #define MISC_DYNAMIC_MINOR 255
9412  
9413  #define TUN_MINOR           200
9414 Index: linux-2.6.10-base/include/asm-um/kerntypes.h
9415 ===================================================================
9416 --- linux-2.6.10-base.orig/include/asm-um/kerntypes.h   2003-09-02 06:26:13.000000000 +0800
9417 +++ linux-2.6.10-base/include/asm-um/kerntypes.h        2005-05-17 18:52:39.961051408 +0800
9418 @@ -0,0 +1,21 @@
9419 +/*
9420 + * asm-um/kerntypes.h
9421 + *
9422 + * Arch-dependent header file that includes headers for all arch-specific 
9423 + * types of interest.
9424 + * The kernel type information is used by the lcrash utility when
9425 + * analyzing system crash dumps or the live system. Using the type
9426 + * information for the running system, rather than kernel header files,
9427 + * makes for a more flexible and robust analysis tool.
9428 + *
9429 + * This source code is released under the GNU GPL.
9430 + */
9431 +
9432 +/* Usermode-Linux-specific header files */
9433 +#ifndef _UM_KERNTYPES_H
9434 +#define _UM_KERNTYPES_H
9435 +
9436 +/* Use the default */
9437 +#include <asm-generic/kerntypes.h>
9438 +
9439 +#endif /* _UM_KERNTYPES_H */
9440 Index: linux-2.6.10-base/include/asm-generic/kerntypes.h
9441 ===================================================================
9442 --- linux-2.6.10-base.orig/include/asm-generic/kerntypes.h      2003-09-02 06:26:13.000000000 +0800
9443 +++ linux-2.6.10-base/include/asm-generic/kerntypes.h   2005-05-17 18:52:39.961051408 +0800
9444 @@ -0,0 +1,20 @@
9445 +/*
9446 + * asm-generic/kerntypes.h
9447 + *
9448 + * Arch-dependent header file that includes headers for all arch-specific 
9449 + * types of interest.
9450 + * The kernel type information is used by the lcrash utility when
9451 + * analyzing system crash dumps or the live system. Using the type
9452 + * information for the running system, rather than kernel header files,
9453 + * makes for a more flexible and robust analysis tool.
9454 + *
9455 + * This source code is released under the GNU GPL.
9456 + */
9457 +
9458 +/* Arch-independent header files */
9459 +#ifndef _GENERIC_KERNTYPES_H
9460 +#define _GENERIC_KERNTYPES_H
9461 +
9462 +#include <linux/pci.h>
9463 +
9464 +#endif /* _GENERIC_KERNTYPES_H */
9465 Index: linux-2.6.10-base/include/asm-sparc/kerntypes.h
9466 ===================================================================
9467 --- linux-2.6.10-base.orig/include/asm-sparc/kerntypes.h        2003-09-02 06:26:13.000000000 +0800
9468 +++ linux-2.6.10-base/include/asm-sparc/kerntypes.h     2005-05-17 18:52:39.961051408 +0800
9469 @@ -0,0 +1,21 @@
9470 +/*
9471 + * asm-sparc/kerntypes.h
9472 + *
9473 + * Arch-dependent header file that includes headers for all arch-specific 
9474 + * types of interest.
9475 + * The kernel type information is used by the lcrash utility when
9476 + * analyzing system crash dumps or the live system. Using the type
9477 + * information for the running system, rather than kernel header files,
9478 + * makes for a more flexible and robust analysis tool.
9479 + *
9480 + * This source code is released under the GNU GPL.
9481 + */
9482 +
9483 +/* SPARC-specific header files */
9484 +#ifndef _SPARC_KERNTYPES_H
9485 +#define _SPARC_KERNTYPES_H
9486 +
9487 +/* Use the default */
9488 +#include <asm-generic/kerntypes.h>
9489 +
9490 +#endif /* _SPARC_KERNTYPES_H */
9491 Index: linux-2.6.10-base/include/asm-arm/kerntypes.h
9492 ===================================================================
9493 --- linux-2.6.10-base.orig/include/asm-arm/kerntypes.h  2003-09-02 06:26:13.000000000 +0800
9494 +++ linux-2.6.10-base/include/asm-arm/kerntypes.h       2005-05-17 18:52:39.962051256 +0800
9495 @@ -0,0 +1,21 @@
9496 +/*
9497 + * asm-arm/kerntypes.h
9498 + *
9499 + * Arch-dependent header file that includes headers for all arch-specific 
9500 + * types of interest.
9501 + * The kernel type information is used by the lcrash utility when
9502 + * analyzing system crash dumps or the live system. Using the type
9503 + * information for the running system, rather than kernel header files,
9504 + * makes for a more flexible and robust analysis tool.
9505 + *
9506 + * This source code is released under the GNU GPL.
9507 + */
9508 +
9509 +/* ARM-specific header files */
9510 +#ifndef _ARM_KERNTYPES_H
9511 +#define _ARM_KERNTYPES_H
9512 +
9513 +/* Use the default */
9514 +#include <asm-generic/kerntypes.h>
9515 +
9516 +#endif /* _ARM_KERNTYPES_H */
9517 Index: linux-2.6.10-base/include/asm-sparc64/kerntypes.h
9518 ===================================================================
9519 --- linux-2.6.10-base.orig/include/asm-sparc64/kerntypes.h      2003-09-02 06:26:13.000000000 +0800
9520 +++ linux-2.6.10-base/include/asm-sparc64/kerntypes.h   2005-05-17 18:52:39.962051256 +0800
9521 @@ -0,0 +1,21 @@
9522 +/*
9523 + * asm-sparc64/kerntypes.h
9524 + *
9525 + * Arch-dependent header file that includes headers for all arch-specific 
9526 + * types of interest.
9527 + * The kernel type information is used by the lcrash utility when
9528 + * analyzing system crash dumps or the live system. Using the type
9529 + * information for the running system, rather than kernel header files,
9530 + * makes for a more flexible and robust analysis tool.
9531 + *
9532 + * This source code is released under the GNU GPL.
9533 + */
9534 +
9535 +/* SPARC64-specific header files */
9536 +#ifndef _SPARC64_KERNTYPES_H
9537 +#define _SPARC64_KERNTYPES_H
9538 +
9539 +/* Use the default */
9540 +#include <asm-generic/kerntypes.h>
9541 +
9542 +#endif /* _SPARC64_KERNTYPES_H */
9543 Index: linux-2.6.10-base/include/asm-mips64/kerntypes.h
9544 ===================================================================
9545 --- linux-2.6.10-base.orig/include/asm-mips64/kerntypes.h       2003-09-02 06:26:13.000000000 +0800
9546 +++ linux-2.6.10-base/include/asm-mips64/kerntypes.h    2005-05-17 18:52:39.962051256 +0800
9547 @@ -0,0 +1,21 @@
9548 +/*
9549 + * asm-mips64/kerntypes.h
9550 + *
9551 + * Arch-dependent header file that includes headers for all arch-specific 
9552 + * types of interest.
9553 + * The kernel type information is used by the lcrash utility when
9554 + * analyzing system crash dumps or the live system. Using the type
9555 + * information for the running system, rather than kernel header files,
9556 + * makes for a more flexible and robust analysis tool.
9557 + *
9558 + * This source code is released under the GNU GPL.
9559 + */
9560 +
9561 +/* MIPS64-specific header files */
9562 +#ifndef _MIPS64_KERNTYPES_H
9563 +#define _MIPS64_KERNTYPES_H
9564 +
9565 +/* Use the default */
9566 +#include <asm-generic/kerntypes.h>
9567 +
9568 +#endif /* _MIPS64_KERNTYPES_H */
9569 Index: linux-2.6.10-base/include/asm-v850/kerntypes.h
9570 ===================================================================
9571 --- linux-2.6.10-base.orig/include/asm-v850/kerntypes.h 2003-09-02 06:26:13.000000000 +0800
9572 +++ linux-2.6.10-base/include/asm-v850/kerntypes.h      2005-05-17 18:52:39.962051256 +0800
9573 @@ -0,0 +1,21 @@
9574 +/*
9575 + * asm-v850/kerntypes.h
9576 + *
9577 + * Arch-dependent header file that includes headers for all arch-specific 
9578 + * types of interest.
9579 + * The kernel type information is used by the lcrash utility when
9580 + * analyzing system crash dumps or the live system. Using the type
9581 + * information for the running system, rather than kernel header files,
9582 + * makes for a more flexible and robust analysis tool.
9583 + *
9584 + * This source code is released under the GNU GPL.
9585 + */
9586 +
9587 +/* V850-specific header files */
9588 +#ifndef _V850_KERNTYPES_H
9589 +#define _V850_KERNTYPES_H
9590 +
9591 +/* Use the default */
9592 +#include <asm-generic/kerntypes.h>
9593 +
9594 +#endif /* _V850_KERNTYPES_H */
9595 Index: linux-2.6.10-base/include/asm-sh/kerntypes.h
9596 ===================================================================
9597 --- linux-2.6.10-base.orig/include/asm-sh/kerntypes.h   2003-09-02 06:26:13.000000000 +0800
9598 +++ linux-2.6.10-base/include/asm-sh/kerntypes.h        2005-05-17 18:52:39.963051104 +0800
9599 @@ -0,0 +1,21 @@
9600 +/*
9601 + * asm-sh/kerntypes.h
9602 + *
9603 + * Arch-dependent header file that includes headers for all arch-specific 
9604 + * types of interest.
9605 + * The kernel type information is used by the lcrash utility when
9606 + * analyzing system crash dumps or the live system. Using the type
9607 + * information for the running system, rather than kernel header files,
9608 + * makes for a more flexible and robust analysis tool.
9609 + *
9610 + * This source code is released under the GNU GPL.
9611 + */
9612 +
9613 +/* Super-H-specific header files */
9614 +#ifndef _SH_KERNTYPES_H
9615 +#define _SH_KERNTYPES_H
9616 +
9617 +/* Use the default */
9618 +#include <asm-generic/kerntypes.h>
9619 +
9620 +#endif /* _SH_KERNTYPES_H */
9621 Index: linux-2.6.10-base/include/asm-alpha/kerntypes.h
9622 ===================================================================
9623 --- linux-2.6.10-base.orig/include/asm-alpha/kerntypes.h        2003-09-02 06:26:13.000000000 +0800
9624 +++ linux-2.6.10-base/include/asm-alpha/kerntypes.h     2005-05-17 18:52:39.963051104 +0800
9625 @@ -0,0 +1,21 @@
9626 +/*
9627 + * asm-alpha/kerntypes.h
9628 + *
9629 + * Arch-dependent header file that includes headers for all arch-specific 
9630 + * types of interest.
9631 + * The kernel type information is used by the lcrash utility when
9632 + * analyzing system crash dumps or the live system. Using the type
9633 + * information for the running system, rather than kernel header files,
9634 + * makes for a more flexible and robust analysis tool.
9635 + *
9636 + * This source code is released under the GNU GPL.
9637 + */
9638 +
9639 +/* Alpha-specific header files */
9640 +#ifndef _ALPHA_KERNTYPES_H
9641 +#define _ALPHA_KERNTYPES_H
9642 +
9643 +/* Use the default */
9644 +#include <asm-generic/kerntypes.h>
9645 +
9646 +#endif /* _ALPHA_KERNTYPES_H */
9647 Index: linux-2.6.10-base/include/asm-ppc/kerntypes.h
9648 ===================================================================
9649 --- linux-2.6.10-base.orig/include/asm-ppc/kerntypes.h  2003-09-02 06:26:13.000000000 +0800
9650 +++ linux-2.6.10-base/include/asm-ppc/kerntypes.h       2005-05-17 18:52:39.963051104 +0800
9651 @@ -0,0 +1,21 @@
9652 +/*
9653 + * asm-ppc/kerntypes.h
9654 + *
9655 + * Arch-dependent header file that includes headers for all arch-specific 
9656 + * types of interest.
9657 + * The kernel type information is used by the lcrash utility when
9658 + * analyzing system crash dumps or the live system. Using the type
9659 + * information for the running system, rather than kernel header files,
9660 + * makes for a more flexible and robust analysis tool.
9661 + *
9662 + * This source code is released under the GNU GPL.
9663 + */
9664 +
9665 +/* PowerPC-specific header files */
9666 +#ifndef _PPC_KERNTYPES_H
9667 +#define _PPC_KERNTYPES_H
9668 +
9669 +/* Use the default */
9670 +#include <asm-generic/kerntypes.h>
9671 +
9672 +#endif /* _PPC_KERNTYPES_H */
9673 Index: linux-2.6.10-base/include/asm-m68knommu/kerntypes.h
9674 ===================================================================
9675 --- linux-2.6.10-base.orig/include/asm-m68knommu/kerntypes.h    2003-09-02 06:26:13.000000000 +0800
9676 +++ linux-2.6.10-base/include/asm-m68knommu/kerntypes.h 2005-05-17 18:52:39.963051104 +0800
9677 @@ -0,0 +1,21 @@
9678 +/*
9679 + * asm-m68knommu/kerntypes.h
9680 + *
9681 + * Arch-dependent header file that includes headers for all arch-specific 
9682 + * types of interest.
9683 + * The kernel type information is used by the lcrash utility when
9684 + * analyzing system crash dumps or the live system. Using the type
9685 + * information for the running system, rather than kernel header files,
9686 + * makes for a more flexible and robust analysis tool.
9687 + *
9688 + * This source code is released under the GNU GPL.
9689 + */
9690 +
9691 +/* m68k/no-MMU-specific header files */
9692 +#ifndef _M68KNOMMU_KERNTYPES_H
9693 +#define _M68KNOMMU_KERNTYPES_H
9694 +
9695 +/* Use the default */
9696 +#include <asm-generic/kerntypes.h>
9697 +
9698 +#endif /* _M68KNOMMU_KERNTYPES_H */
9699 Index: linux-2.6.10-base/include/asm-x86_64/hw_irq.h
9700 ===================================================================
9701 --- linux-2.6.10-base.orig/include/asm-x86_64/hw_irq.h  2004-12-25 05:35:39.000000000 +0800
9702 +++ linux-2.6.10-base/include/asm-x86_64/hw_irq.h       2005-05-17 18:52:39.964050952 +0800
9703 @@ -34,7 +34,6 @@
9704  
9705  #define IA32_SYSCALL_VECTOR    0x80
9706  
9707 -
9708  /*
9709   * Vectors 0x20-0x2f are used for ISA interrupts.
9710   */
9711 @@ -55,6 +54,7 @@
9712  #define TASK_MIGRATION_VECTOR  0xfb
9713  #define CALL_FUNCTION_VECTOR   0xfa
9714  #define KDB_VECTOR     0xf9
9715 +#define DUMP_VECTOR    0xf8
9716  
9717  #define THERMAL_APIC_VECTOR    0xf0
9718  
9719 Index: linux-2.6.10-base/include/asm-x86_64/kerntypes.h
9720 ===================================================================
9721 --- linux-2.6.10-base.orig/include/asm-x86_64/kerntypes.h       2003-09-02 06:26:13.000000000 +0800
9722 +++ linux-2.6.10-base/include/asm-x86_64/kerntypes.h    2005-05-17 18:52:39.964050952 +0800
9723 @@ -0,0 +1,21 @@
9724 +/*
9725 + * asm-x86_64/kerntypes.h
9726 + *
9727 + * Arch-dependent header file that includes headers for all arch-specific 
9728 + * types of interest.
9729 + * The kernel type information is used by the lcrash utility when
9730 + * analyzing system crash dumps or the live system. Using the type
9731 + * information for the running system, rather than kernel header files,
9732 + * makes for a more flexible and robust analysis tool.
9733 + *
9734 + * This source code is released under the GNU GPL.
9735 + */
9736 +
9737 +/* x86_64-specific header files */
9738 +#ifndef _X86_64_KERNTYPES_H
9739 +#define _X86_64_KERNTYPES_H
9740 +
9741 +/* Use the default */
9742 +#include <asm-generic/kerntypes.h>
9743 +
9744 +#endif /* _X86_64_KERNTYPES_H */
9745 Index: linux-2.6.10-base/include/asm-x86_64/dump.h
9746 ===================================================================
9747 --- linux-2.6.10-base.orig/include/asm-x86_64/dump.h    2003-09-02 06:26:13.000000000 +0800
9748 +++ linux-2.6.10-base/include/asm-x86_64/dump.h 2005-05-17 18:52:39.964050952 +0800
9749 @@ -0,0 +1,93 @@
9750 +/*
9751 + * Kernel header file for Linux crash dumps.
9752 + *
9753 + * Created by: Matt Robinson (yakker@sgi.com)
9754 + *
9755 + * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
9756 + * x86_64 lkcd port Sachin Sant ( sachinp@in.ibm.com)
9757 + * This code is released under version 2 of the GNU GPL.
9758 + */
9759 +
9760 +/* This header file holds the architecture specific crash dump header */
9761 +#ifndef _ASM_DUMP_H
9762 +#define _ASM_DUMP_H
9763 +
9764 +/* necessary header files */
9765 +#include <asm/ptrace.h>                          /* for pt_regs             */
9766 +#include <linux/threads.h>
9767 +
9768 +/* definitions */
9769 +#define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number            */
9770 +#define DUMP_ASM_VERSION_NUMBER   0x2            /* version number          */
9771 +
9772 +
9773 +/*
9774 + * Structure: dump_header_asm_t
9775 + *  Function: This is the header for architecture-specific stuff.  It
9776 + *            follows right after the dump header.
9777 + */
9778 +struct __dump_header_asm {
9779 +
9780 +        /* the dump magic number -- unique to verify dump is valid */
9781 +        uint64_t             dha_magic_number;
9782 +
9783 +        /* the version number of this dump */
9784 +        uint32_t             dha_version;
9785 +
9786 +        /* the size of this header (in case we can't read it) */
9787 +        uint32_t             dha_header_size;
9788 +
9789 +       /* the dump registers */
9790 +       struct pt_regs       dha_regs;
9791 +
9792 +       /* smp specific */
9793 +       uint32_t             dha_smp_num_cpus;
9794 +       int                  dha_dumping_cpu;   
9795 +       struct pt_regs       dha_smp_regs[NR_CPUS];
9796 +       uint64_t             dha_smp_current_task[NR_CPUS];
9797 +       uint64_t             dha_stack[NR_CPUS];
9798 +       uint64_t             dha_stack_ptr[NR_CPUS];
9799 +} __attribute__((packed));
9800 +
9801 +#ifdef __KERNEL__
9802 +static inline void get_current_regs(struct pt_regs *regs)
9803 +{
9804 +       unsigned seg;
9805 +       __asm__ __volatile__("movq %%r15,%0" : "=m"(regs->r15));
9806 +       __asm__ __volatile__("movq %%r14,%0" : "=m"(regs->r14));
9807 +       __asm__ __volatile__("movq %%r13,%0" : "=m"(regs->r13));
9808 +       __asm__ __volatile__("movq %%r12,%0" : "=m"(regs->r12));
9809 +       __asm__ __volatile__("movq %%r11,%0" : "=m"(regs->r11));
9810 +       __asm__ __volatile__("movq %%r10,%0" : "=m"(regs->r10));
9811 +       __asm__ __volatile__("movq %%r9,%0" : "=m"(regs->r9));
9812 +       __asm__ __volatile__("movq %%r8,%0" : "=m"(regs->r8));
9813 +       __asm__ __volatile__("movq %%rbx,%0" : "=m"(regs->rbx));
9814 +       __asm__ __volatile__("movq %%rcx,%0" : "=m"(regs->rcx));
9815 +       __asm__ __volatile__("movq %%rdx,%0" : "=m"(regs->rdx));
9816 +       __asm__ __volatile__("movq %%rsi,%0" : "=m"(regs->rsi));
9817 +       __asm__ __volatile__("movq %%rdi,%0" : "=m"(regs->rdi));
9818 +       __asm__ __volatile__("movq %%rbp,%0" : "=m"(regs->rbp));
9819 +       __asm__ __volatile__("movq %%rax,%0" : "=m"(regs->rax));
9820 +       __asm__ __volatile__("movq %%rsp,%0" : "=m"(regs->rsp));
9821 +       __asm__ __volatile__("movl %%ss, %0" :"=r"(seg)); 
9822 +       regs->ss = (unsigned long)seg;
9823 +       __asm__ __volatile__("movl %%cs, %0" :"=r"(seg));
9824 +       regs->cs = (unsigned long)seg;
9825 +       __asm__ __volatile__("pushfq; popq %0" :"=m"(regs->eflags));
9826 +       regs->rip = (unsigned long)current_text_addr();
9827 +       
9828 +}
9829 +
9830 +extern volatile int dump_in_progress;
9831 +extern struct __dump_header_asm dump_header_asm;
9832 +
9833 +#ifdef CONFIG_SMP
9834 +
9835 +
9836 +extern void dump_send_ipi(void);
9837 +#else
9838 +#define dump_send_ipi() do { } while(0)
9839 +#endif
9840 +#endif /* __KERNEL__ */
9841 +
9842 +#endif /* _ASM_DUMP_H */
9843 Index: linux-2.6.10-base/include/asm-x86_64/kmap_types.h
9844 ===================================================================
9845 --- linux-2.6.10-base.orig/include/asm-x86_64/kmap_types.h      2004-12-25 05:35:23.000000000 +0800
9846 +++ linux-2.6.10-base/include/asm-x86_64/kmap_types.h   2005-05-17 18:52:39.965050800 +0800
9847 @@ -13,7 +13,8 @@
9848         KM_IRQ1,
9849         KM_SOFTIRQ0,
9850         KM_SOFTIRQ1,
9851 -       KM_TYPE_NR
9852 +       KM_DUMP,
9853 +       KM_TYPE_NR,
9854  };
9855  
9856  #endif
9857 Index: linux-2.6.10-base/include/asm-x86_64/smp.h
9858 ===================================================================
9859 --- linux-2.6.10-base.orig/include/asm-x86_64/smp.h     2004-12-25 05:33:48.000000000 +0800
9860 +++ linux-2.6.10-base/include/asm-x86_64/smp.h  2005-05-17 18:52:39.965050800 +0800
9861 @@ -41,6 +41,7 @@
9862  extern int pic_mode;
9863  extern int smp_num_siblings;
9864  extern void smp_flush_tlb(void);
9865 +extern void dump_send_ipi(void);
9866  extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
9867  extern void smp_send_reschedule(int cpu);
9868  extern void smp_invalidate_rcv(void);          /* Process an NMI */
9869 Index: linux-2.6.10-base/include/asm-h8300/kerntypes.h
9870 ===================================================================
9871 --- linux-2.6.10-base.orig/include/asm-h8300/kerntypes.h        2003-09-02 06:26:13.000000000 +0800
9872 +++ linux-2.6.10-base/include/asm-h8300/kerntypes.h     2005-05-17 18:52:39.965050800 +0800
9873 @@ -0,0 +1,21 @@
9874 +/*
9875 + * asm-h8300/kerntypes.h
9876 + *
9877 + * Arch-dependent header file that includes headers for all arch-specific 
9878 + * types of interest.
9879 + * The kernel type information is used by the lcrash utility when
9880 + * analyzing system crash dumps or the live system. Using the type
9881 + * information for the running system, rather than kernel header files,
9882 + * makes for a more flexible and robust analysis tool.
9883 + *
9884 + * This source code is released under the GNU GPL.
9885 + */
9886 +
9887 +/* H8300-specific header files */
9888 +#ifndef _H8300_KERNTYPES_H
9889 +#define _H8300_KERNTYPES_H
9890 +
9891 +/* Use the default */
9892 +#include <asm-generic/kerntypes.h>
9893 +
9894 +#endif /* _H8300_KERNTYPES_H */
9895 Index: linux-2.6.10-base/include/asm-cris/kerntypes.h
9896 ===================================================================
9897 --- linux-2.6.10-base.orig/include/asm-cris/kerntypes.h 2003-09-02 06:26:13.000000000 +0800
9898 +++ linux-2.6.10-base/include/asm-cris/kerntypes.h      2005-05-17 18:52:39.965050800 +0800
9899 @@ -0,0 +1,21 @@
9900 +/*
9901 + * asm-cris/kerntypes.h
9902 + *
9903 + * Arch-dependent header file that includes headers for all arch-specific 
9904 + * types of interest.
9905 + * The kernel type information is used by the lcrash utility when
9906 + * analyzing system crash dumps or the live system. Using the type
9907 + * information for the running system, rather than kernel header files,
9908 + * makes for a more flexible and robust analysis tool.
9909 + *
9910 + * This source code is released under the GNU GPL.
9911 + */
9912 +
9913 +/* CRIS-specific header files */
9914 +#ifndef _CRIS_KERNTYPES_H
9915 +#define _CRIS_KERNTYPES_H
9916 +
9917 +/* Use the default */
9918 +#include <asm-generic/kerntypes.h>
9919 +
9920 +#endif /* _CRIS_KERNTYPES_H */
9921 Index: linux-2.6.10-base/include/asm-mips/kerntypes.h
9922 ===================================================================
9923 --- linux-2.6.10-base.orig/include/asm-mips/kerntypes.h 2003-09-02 06:26:13.000000000 +0800
9924 +++ linux-2.6.10-base/include/asm-mips/kerntypes.h      2005-05-17 18:52:39.966050648 +0800
9925 @@ -0,0 +1,21 @@
9926 +/*
9927 + * asm-mips/kerntypes.h
9928 + *
9929 + * Arch-dependent header file that includes headers for all arch-specific 
9930 + * types of interest.
9931 + * The kernel type information is used by the lcrash utility when
9932 + * analyzing system crash dumps or the live system. Using the type
9933 + * information for the running system, rather than kernel header files,
9934 + * makes for a more flexible and robust analysis tool.
9935 + *
9936 + * This source code is released under the GNU GPL.
9937 + */
9938 +
9939 +/* MIPS-specific header files */
9940 +#ifndef _MIPS_KERNTYPES_H
9941 +#define _MIPS_KERNTYPES_H
9942 +
9943 +/* Use the default */
9944 +#include <asm-generic/kerntypes.h>
9945 +
9946 +#endif /* _MIPS_KERNTYPES_H */
9947 Index: linux-2.6.10-base/include/asm-arm26/kerntypes.h
9948 ===================================================================
9949 --- linux-2.6.10-base.orig/include/asm-arm26/kerntypes.h        2003-09-02 06:26:13.000000000 +0800
9950 +++ linux-2.6.10-base/include/asm-arm26/kerntypes.h     2005-05-17 18:52:39.966050648 +0800
9951 @@ -0,0 +1,21 @@
9952 +/*
9953 + * asm-arm26/kerntypes.h
9954 + *
9955 + * Arch-dependent header file that includes headers for all arch-specific 
9956 + * types of interest.
9957 + * The kernel type information is used by the lcrash utility when
9958 + * analyzing system crash dumps or the live system. Using the type
9959 + * information for the running system, rather than kernel header files,
9960 + * makes for a more flexible and robust analysis tool.
9961 + *
9962 + * This source code is released under the GNU GPL.
9963 + */
9964 +
9965 +/* ARM26-specific header files */
9966 +#ifndef _ARM26_KERNTYPES_H
9967 +#define _ARM26_KERNTYPES_H
9968 +
9969 +/* Use the default */
9970 +#include <asm-generic/kerntypes.h>
9971 +
9972 +#endif /* _ARM26_KERNTYPES_H */
9973 Index: linux-2.6.10-base/include/asm-parisc/kerntypes.h
9974 ===================================================================
9975 --- linux-2.6.10-base.orig/include/asm-parisc/kerntypes.h       2003-09-02 06:26:13.000000000 +0800
9976 +++ linux-2.6.10-base/include/asm-parisc/kerntypes.h    2005-05-17 18:52:39.966050648 +0800
9977 @@ -0,0 +1,21 @@
9978 +/*
9979 + * asm-parisc/kerntypes.h
9980 + *
9981 + * Arch-dependent header file that includes headers for all arch-specific 
9982 + * types of interest.
9983 + * The kernel type information is used by the lcrash utility when
9984 + * analyzing system crash dumps or the live system. Using the type
9985 + * information for the running system, rather than kernel header files,
9986 + * makes for a more flexible and robust analysis tool.
9987 + *
9988 + * This source code is released under the GNU GPL.
9989 + */
9990 +
9991 +/* PA-RISC-specific header files */
9992 +#ifndef _PARISC_KERNTYPES_H
9993 +#define _PARISC_KERNTYPES_H
9994 +
9995 +/* Use the default */
9996 +#include <asm-generic/kerntypes.h>
9997 +
9998 +#endif /* _PARISC_KERNTYPES_H */
9999 Index: linux-2.6.10-base/include/asm-ia64/kerntypes.h
10000 ===================================================================
10001 --- linux-2.6.10-base.orig/include/asm-ia64/kerntypes.h 2003-09-02 06:26:13.000000000 +0800
10002 +++ linux-2.6.10-base/include/asm-ia64/kerntypes.h      2005-05-17 18:52:39.966050648 +0800
10003 @@ -0,0 +1,21 @@
10004 +/*
10005 + * asm-ia64/kerntypes.h
10006 + *
10007 + * Arch-dependent header file that includes headers for all arch-specific 
10008 + * types of interest.
10009 + * The kernel type information is used by the lcrash utility when
10010 + * analyzing system crash dumps or the live system. Using the type
10011 + * information for the running system, rather than kernel header files,
10012 + * makes for a more flexible and robust analysis tool.
10013 + *
10014 + * This source code is released under the GNU GPL.
10015 + */
10016 +
10017 +/* IA64-specific header files */
10018 +#ifndef _IA64_KERNTYPES_H
10019 +#define _IA64_KERNTYPES_H
10020 +
10021 +/* Use the default */
10022 +#include <asm-generic/kerntypes.h>
10023 +
10024 +#endif /* _IA64_KERNTYPES_H */
10025 Index: linux-2.6.10-base/include/asm-ia64/dump.h
10026 ===================================================================
10027 --- linux-2.6.10-base.orig/include/asm-ia64/dump.h      2003-09-02 06:26:13.000000000 +0800
10028 +++ linux-2.6.10-base/include/asm-ia64/dump.h   2005-05-17 18:52:39.967050496 +0800
10029 @@ -0,0 +1,201 @@
10030 +/*
10031 + * Kernel header file for Linux crash dumps.
10032 + *
10033 + * Created by: Matt Robinson (yakker@sgi.com)
10034 + *
10035 + * Copyright 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
10036 + *
10037 + * This code is released under version 2 of the GNU GPL.
10038 + */
10039 +
10040 +/* This header file holds the architecture specific crash dump header */
10041 +#ifndef _ASM_DUMP_H
10042 +#define _ASM_DUMP_H
10043 +
10044 +/* definitions */
10045 +#define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number            */
10046 +#define DUMP_ASM_VERSION_NUMBER   0x4            /* version number          */
10047 +
10048 +#ifdef __KERNEL__
10049 +#include <linux/efi.h>
10050 +#include <asm/pal.h>
10051 +#include <asm/ptrace.h>
10052 +
10053 +#ifdef CONFIG_SMP
10054 +extern cpumask_t irq_affinity[];
10055 +extern int (*dump_ipi_function_ptr)(struct pt_regs *);
10056 +extern void dump_send_ipi(void);
10057 +#else /* !CONFIG_SMP */
10058 +#define dump_send_ipi() do { } while(0)
10059 +#endif
10060 +
10061 +#else  /* !__KERNEL__ */
10062 +/* necessary header files */
10063 +#include <asm/ptrace.h>                          /* for pt_regs             */
10064 +#include <linux/threads.h>
10065 +#endif /* __KERNEL__ */
10066 +
10067 +/* 
10068 + * mkswap.c calls getpagesize() to get the system page size,
10069 + * which is not  necessarily the same as the hardware page size.
10070 + *
10071 + * For ia64 the kernel PAGE_SIZE can be configured from 4KB ... 16KB.
10072 + *
10073 + * The physical memory is layed out out in the hardware/minimal pages.
10074 + * This is the size we need to use for dumping physical pages.
10075 + *
10076 + * Note ths hardware/minimal page size being use in;
10077 + *      arch/ia64/kernel/efi.c`efi_memmap_walk():
10078 + *         curr.end   = curr.start + (md->num_pages << 12);
10079 + *
10080 + * Since the system page size could change between the kernel we boot
10081 + * on the the kernel that cause the core dume we may want to have something
10082 + * more constant like the maximum system page size (See include/asm-ia64/page.h).
10083 + */
10084 +/* IA64 manages the stack in differnt manner as compared to other architectures.
10085 + * task_struct lies at the bottom of stack.
10086 + */
10087 +#undef STACK_START_POSITION
10088 +#define STACK_START_POSITION(tsk)              (tsk)
10089 +#define DUMP_MIN_PAGE_SHIFT                    12
10090 +#define DUMP_MIN_PAGE_SIZE                     (1UL << DUMP_MIN_PAGE_SHIFT)
10091 +#define DUMP_MIN_PAGE_MASK                     (~(DUMP_MIN_PAGE_SIZE - 1))
10092 +#define DUMP_MIN_PAGE_ALIGN(addr)              (((addr) + DUMP_MIN_PAGE_SIZE - 1) & DUMP_MIN_PAGE_MASK)
10093 +
10094 +#define DUMP_MAX_PAGE_SHIFT                    16
10095 +#define DUMP_MAX_PAGE_SIZE                     (1UL << DUMP_MAX_PAGE_SHIFT)
10096 +#define DUMP_MAX_PAGE_MASK                     (~(DUMP_MAX_PAGE_SIZE - 1))
10097 +#define DUMP_MAX_PAGE_ALIGN(addr)              (((addr) + DUMP_MAX_PAGE_SIZE - 1) & DUMP_MAX_PAGE_MASK)
10098 +
10099 +#define DUMP_EF_PAGE_SHIFT                     DUMP_MIN_PAGE_SHIFT
10100 +
10101 +extern int _end,_start;
10102 +
10103 +/*
10104 + * Structure: dump_header_asm_t
10105 + *  Function: This is the header for architecture-specific stuff.  It
10106 + *            follows right after the dump header.
10107 + */
10108 +/*typedef struct _dump_header_asm {*/
10109 +
10110 +typedef struct __dump_header_asm {
10111 +
10112 +        /* the dump magic number -- unique to verify dump is valid */
10113 +        uint64_t             dha_magic_number;
10114 +
10115 +        /* the version number of this dump */
10116 +        uint32_t             dha_version;
10117 +
10118 +        /* the size of this header (in case we can't read it) */
10119 +        uint32_t             dha_header_size;
10120 +
10121 +        /* pointer to pt_regs, (OLD: (struct pt_regs *, NEW: (uint64_t)) */
10122 +       uint64_t             dha_pt_regs;
10123 +
10124 +       /* the dump registers */
10125 +       struct pt_regs       dha_regs;
10126 +
10127 +        /* the rnat register saved after flushrs */
10128 +        uint64_t             dha_rnat;
10129 +
10130 +       /* the pfs register saved after flushrs */
10131 +       uint64_t             dha_pfs;
10132 +
10133 +       /* the bspstore register saved after flushrs */
10134 +       uint64_t             dha_bspstore;
10135 +
10136 +       /* smp specific */
10137 +       uint32_t             dha_smp_num_cpus;
10138 +       uint32_t             dha_dumping_cpu;   
10139 +       struct pt_regs       dha_smp_regs[NR_CPUS];
10140 +       uint64_t             dha_smp_current_task[NR_CPUS];
10141 +       uint64_t             dha_stack[NR_CPUS];
10142 +       uint64_t             dha_stack_ptr[NR_CPUS];
10143 +
10144 +} __attribute__((packed)) dump_header_asm_t;
10145 +
10146 +
10147 +extern struct __dump_header_asm dump_header_asm;
10148 +
10149 +#ifdef __KERNEL__
10150 +static inline void get_current_regs(struct pt_regs *regs)
10151 +{
10152 +       /* 
10153 +        * REMIND: Looking at functions/Macros like:
10154 +        *               DO_SAVE_SWITCH_STACK
10155 +        *               ia64_switch_to()
10156 +        *               ia64_save_extra()
10157 +        *               switch_to()
10158 +        *         to implement this new feature that Matt seem to have added
10159 +        *         to panic.c; seems all platforms are now expected to provide
10160 +        *         this function to dump the current registers into the pt_regs
10161 +        *         structure.
10162 +        */
10163 +       volatile unsigned long rsc_value;/*for storing the rsc value*/
10164 +       volatile unsigned long ic_value;
10165 +
10166 +       __asm__ __volatile__("mov %0=b6;;":"=r"(regs->b6));
10167 +       __asm__ __volatile__("mov %0=b7;;":"=r"(regs->b7));
10168 +       
10169 +        __asm__ __volatile__("mov %0=ar.csd;;":"=r"(regs->ar_csd));
10170 +       __asm__ __volatile__("mov %0=ar.ssd;;":"=r"(regs->ar_ssd));
10171 +       __asm__ __volatile__("mov %0=psr;;":"=r"(ic_value));
10172 +       if(ic_value & 0x1000)/*Within an interrupt*/
10173 +       {
10174 +               __asm__ __volatile__("mov %0=cr.ipsr;;":"=r"(regs->cr_ipsr));
10175 +               __asm__ __volatile__("mov %0=cr.iip;;":"=r"(regs->cr_iip));
10176 +               __asm__ __volatile__("mov %0=cr.ifs;;":"=r"(regs->cr_ifs));
10177 +       }
10178 +       else
10179 +       {
10180 +               regs->cr_ipsr=regs->cr_iip=regs->cr_ifs=(unsigned long)-1;
10181 +       }
10182 +       __asm__ __volatile__("mov %0=ar.unat;;":"=r"(regs->ar_unat));
10183 +       __asm__ __volatile__("mov %0=ar.pfs;;":"=r"(regs->ar_pfs));
10184 +       __asm__ __volatile__("mov %0=ar.rsc;;":"=r"(rsc_value));
10185 +       regs->ar_rsc = rsc_value;
10186 +       /*loadrs is from 16th bit to 29th bit of rsc*/
10187 +       regs->loadrs =  rsc_value >> 16 & (unsigned long)0x3fff;
10188 +       /*setting the rsc.mode value to 0 (rsc.mode is the last two bits of rsc)*/
10189 +       __asm__ __volatile__("mov ar.rsc=%0;;"::"r"(rsc_value & (unsigned long)(~3)));
10190 +       __asm__ __volatile__("mov %0=ar.rnat;;":"=r"(regs->ar_rnat));
10191 +       __asm__ __volatile__("mov %0=ar.bspstore;;":"=r"(regs->ar_bspstore));
10192 +       /*copying the original value back*/
10193 +       __asm__ __volatile__("mov ar.rsc=%0;;"::"r"(rsc_value));
10194 +       __asm__ __volatile__("mov %0=pr;;":"=r"(regs->pr));
10195 +       __asm__ __volatile__("mov %0=ar.fpsr;;":"=r"(regs->ar_fpsr));
10196 +       __asm__ __volatile__("mov %0=ar.ccv;;":"=r"(regs->ar_ccv));
10197 +
10198 +       __asm__ __volatile__("mov %0=r2;;":"=r"(regs->r2));
10199 +        __asm__ __volatile__("mov %0=r3;;":"=r"(regs->r3));
10200 +        __asm__ __volatile__("mov %0=r8;;":"=r"(regs->r8));
10201 +        __asm__ __volatile__("mov %0=r9;;":"=r"(regs->r9));
10202 +        __asm__ __volatile__("mov %0=r10;;":"=r"(regs->r10));
10203 +       __asm__ __volatile__("mov %0=r11;;":"=r"(regs->r11));
10204 +        __asm__ __volatile__("mov %0=r12;;":"=r"(regs->r12));
10205 +       __asm__ __volatile__("mov %0=r13;;":"=r"(regs->r13));
10206 +       __asm__ __volatile__("mov %0=r14;;":"=r"(regs->r14));
10207 +       __asm__ __volatile__("mov %0=r15;;":"=r"(regs->r15));
10208 +       __asm__ __volatile__("mov %0=r16;;":"=r"(regs->r16));
10209 +       __asm__ __volatile__("mov %0=r17;;":"=r"(regs->r17));
10210 +       __asm__ __volatile__("mov %0=r18;;":"=r"(regs->r18));
10211 +       __asm__ __volatile__("mov %0=r19;;":"=r"(regs->r19));
10212 +       __asm__ __volatile__("mov %0=r20;;":"=r"(regs->r20));
10213 +       __asm__ __volatile__("mov %0=r21;;":"=r"(regs->r21));
10214 +       __asm__ __volatile__("mov %0=r22;;":"=r"(regs->r22));
10215 +       __asm__ __volatile__("mov %0=r23;;":"=r"(regs->r23));
10216 +       __asm__ __volatile__("mov %0=r24;;":"=r"(regs->r24));
10217 +       __asm__ __volatile__("mov %0=r25;;":"=r"(regs->r25));
10218 +       __asm__ __volatile__("mov %0=r26;;":"=r"(regs->r26));
10219 +       __asm__ __volatile__("mov %0=r27;;":"=r"(regs->r27));
10220 +       __asm__ __volatile__("mov %0=r28;;":"=r"(regs->r28));
10221 +       __asm__ __volatile__("mov %0=r29;;":"=r"(regs->r29));
10222 +       __asm__ __volatile__("mov %0=r30;;":"=r"(regs->r30));
10223 +       __asm__ __volatile__("mov %0=r31;;":"=r"(regs->r31));
10224 +}
10225 +
10226 +/* Perhaps added to Common Arch Specific Functions and moved to dump.h some day */
10227 +extern void * __dump_memcpy(void *, const void *, size_t);
10228 +#endif /* __KERNEL__ */
10229 +
10230 +#endif /* _ASM_DUMP_H */
10231 Index: linux-2.6.10-base/include/asm-ia64/nmi.h
10232 ===================================================================
10233 --- linux-2.6.10-base.orig/include/asm-ia64/nmi.h       2003-09-02 06:26:13.000000000 +0800
10234 +++ linux-2.6.10-base/include/asm-ia64/nmi.h    2005-05-17 18:52:39.967050496 +0800
10235 @@ -0,0 +1,28 @@
10236 +/*
10237 + *  linux/include/asm-ia64/nmi.h
10238 + */
10239 +#ifndef ASM_NMI_H
10240 +#define ASM_NMI_H
10241 +
10242 +#include <linux/pm.h>
10243 +
10244 +struct pt_regs;
10245
10246 +typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu);
10247
10248 +/** 
10249 + * set_nmi_callback
10250 + *
10251 + * Set a handler for an NMI. Only one handler may be
10252 + * set. Return 1 if the NMI was handled.
10253 + */
10254 +void set_nmi_callback(nmi_callback_t callback);
10255
10256 +/** 
10257 + * unset_nmi_callback
10258 + *
10259 + * Remove the handler previously set.
10260 + */
10261 +void unset_nmi_callback(void);
10262
10263 +#endif /* ASM_NMI_H */
10264 Index: linux-2.6.10-base/include/asm-ppc64/kerntypes.h
10265 ===================================================================
10266 --- linux-2.6.10-base.orig/include/asm-ppc64/kerntypes.h        2003-09-02 06:26:13.000000000 +0800
10267 +++ linux-2.6.10-base/include/asm-ppc64/kerntypes.h     2005-05-17 18:52:39.967050496 +0800
10268 @@ -0,0 +1,21 @@
10269 +/*
10270 + * asm-ppc64/kerntypes.h
10271 + *
10272 + * Arch-dependent header file that includes headers for all arch-specific 
10273 + * types of interest.
10274 + * The kernel type information is used by the lcrash utility when
10275 + * analyzing system crash dumps or the live system. Using the type
10276 + * information for the running system, rather than kernel header files,
10277 + * makes for a more flexible and robust analysis tool.
10278 + *
10279 + * This source code is released under the GNU GPL.
10280 + */
10281 +
10282 +/* PPC64-specific header files */
10283 +#ifndef _PPC64_KERNTYPES_H
10284 +#define _PPC64_KERNTYPES_H
10285 +
10286 +/* Use the default */
10287 +#include <asm-generic/kerntypes.h>
10288 +
10289 +#endif /* _PPC64_KERNTYPES_H */
10290 Index: linux-2.6.10-base/include/asm-ppc64/dump.h
10291 ===================================================================
10292 --- linux-2.6.10-base.orig/include/asm-ppc64/dump.h     2003-09-02 06:26:13.000000000 +0800
10293 +++ linux-2.6.10-base/include/asm-ppc64/dump.h  2005-05-17 18:52:39.968050344 +0800
10294 @@ -0,0 +1,115 @@
10295 +/*
10296 + * Kernel header file for Linux crash dumps.
10297 + *
10298 + * Created by: Todd Inglett <tinglett@vnet.ibm.com>
10299 + *
10300 + * Copyright 2002 - 2004 International Business Machines
10301 + *
10302 + * This code is released under version 2 of the GNU GPL.
10303 + */
10304 +
10305 +/* This header file holds the architecture specific crash dump header */
10306 +#ifndef _ASM_DUMP_H
10307 +#define _ASM_DUMP_H
10308 +
10309 +/* necessary header files */
10310 +#include <asm/ptrace.h>                          /* for pt_regs             */
10311 +#include <asm/kmap_types.h>
10312 +#include <linux/threads.h>
10313 +
10314 +/* definitions */
10315 +#define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number            */
10316 +#define DUMP_ASM_VERSION_NUMBER   0x5            /* version number          */
10317 +
10318 +/*
10319 + * Structure: __dump_header_asm
10320 + *  Function: This is the header for architecture-specific stuff.  It
10321 + *            follows right after the dump header.
10322 + */
10323 +struct __dump_header_asm {
10324 +
10325 +        /* the dump magic number -- unique to verify dump is valid */
10326 +        uint64_t             dha_magic_number;
10327 +
10328 +        /* the version number of this dump */
10329 +        uint32_t             dha_version;
10330 +
10331 +        /* the size of this header (in case we can't read it) */
10332 +        uint32_t             dha_header_size;
10333 +
10334 +       /* the dump registers */
10335 +       struct pt_regs       dha_regs;
10336 +
10337 +       /* smp specific */
10338 +       uint32_t             dha_smp_num_cpus;
10339 +       int                  dha_dumping_cpu;   
10340 +       struct pt_regs       dha_smp_regs[NR_CPUS];
10341 +       uint64_t             dha_smp_current_task[NR_CPUS];
10342 +       uint64_t             dha_stack[NR_CPUS];
10343 +       uint64_t             dha_stack_ptr[NR_CPUS];
10344 +} __attribute__((packed));
10345 +
10346 +#ifdef __KERNEL__
10347 +static inline void get_current_regs(struct pt_regs *regs)
10348 +{
10349 +       unsigned long tmp1, tmp2;
10350 +
10351 +       __asm__ __volatile__ (
10352 +               "std    0,0(%2)\n"
10353 +               "std    1,8(%2)\n"
10354 +               "std    2,16(%2)\n"
10355 +               "std    3,24(%2)\n"
10356 +               "std    4,32(%2)\n"
10357 +               "std    5,40(%2)\n"
10358 +               "std    6,48(%2)\n"
10359 +               "std    7,56(%2)\n"
10360 +               "std    8,64(%2)\n"
10361 +               "std    9,72(%2)\n"
10362 +               "std    10,80(%2)\n"
10363 +               "std    11,88(%2)\n"
10364 +               "std    12,96(%2)\n"
10365 +               "std    13,104(%2)\n"
10366 +               "std    14,112(%2)\n"
10367 +               "std    15,120(%2)\n"
10368 +               "std    16,128(%2)\n"
10369 +               "std    17,136(%2)\n"
10370 +               "std    18,144(%2)\n"
10371 +               "std    19,152(%2)\n"
10372 +               "std    20,160(%2)\n"
10373 +               "std    21,168(%2)\n"
10374 +               "std    22,176(%2)\n"
10375 +               "std    23,184(%2)\n"
10376 +               "std    24,192(%2)\n"
10377 +               "std    25,200(%2)\n"
10378 +               "std    26,208(%2)\n"
10379 +               "std    27,216(%2)\n"
10380 +               "std    28,224(%2)\n"
10381 +               "std    29,232(%2)\n"
10382 +               "std    30,240(%2)\n"
10383 +               "std    31,248(%2)\n"
10384 +               "mfmsr  %0\n"
10385 +               "std    %0, 264(%2)\n"
10386 +               "mfctr  %0\n"
10387 +               "std    %0, 280(%2)\n"
10388 +               "mflr   %0\n"
10389 +               "std    %0, 288(%2)\n"
10390 +               "bl     1f\n"
10391 +       "1:      mflr   %1\n"
10392 +               "std    %1, 256(%2)\n"
10393 +               "mtlr   %0\n"
10394 +               "mfxer  %0\n"
10395 +               "std    %0, 296(%2)\n"
10396 +               : "=&r" (tmp1), "=&r" (tmp2)
10397 +               : "b" (regs));
10398 +}
10399 +
10400 +extern struct __dump_header_asm dump_header_asm;
10401 +
10402 +#ifdef CONFIG_SMP
10403 +extern void dump_send_ipi(int (*dump_ipi_callback)(struct pt_regs *));
10404 +#else
10405 +#define dump_send_ipi() do { } while(0)
10406 +#endif
10407 +#endif /* __KERNEL__ */
10408 +
10409 +#endif /* _ASM_DUMP_H */
10410 Index: linux-2.6.10-base/include/asm-ppc64/kmap_types.h
10411 ===================================================================
10412 --- linux-2.6.10-base.orig/include/asm-ppc64/kmap_types.h       2004-12-25 05:34:45.000000000 +0800
10413 +++ linux-2.6.10-base/include/asm-ppc64/kmap_types.h    2005-05-17 18:52:39.968050344 +0800
10414 @@ -16,7 +16,8 @@
10415         KM_IRQ1,
10416         KM_SOFTIRQ0,
10417         KM_SOFTIRQ1,    
10418 -       KM_TYPE_NR
10419 +       KM_TYPE_NR,
10420 +       KM_DUMP
10421  };
10422  
10423  #endif
10424 Index: linux-2.6.10-base/include/asm-ppc64/smp.h
10425 ===================================================================
10426 --- linux-2.6.10-base.orig/include/asm-ppc64/smp.h      2004-12-25 05:33:47.000000000 +0800
10427 +++ linux-2.6.10-base/include/asm-ppc64/smp.h   2005-05-17 18:52:39.968050344 +0800
10428 @@ -36,7 +36,7 @@
10429  extern void smp_send_debugger_break(int cpu);
10430  struct pt_regs;
10431  extern void smp_message_recv(int, struct pt_regs *);
10432 -
10433 +extern void dump_send_ipi(int (*dump_ipi_callback)(struct pt_regs *));
10434  
10435  #define smp_processor_id() (get_paca()->paca_index)
10436  #define hard_smp_processor_id() (get_paca()->hw_cpu_id)
10437 Index: linux-2.6.10-base/include/asm-s390/kerntypes.h
10438 ===================================================================
10439 --- linux-2.6.10-base.orig/include/asm-s390/kerntypes.h 2003-09-02 06:26:13.000000000 +0800
10440 +++ linux-2.6.10-base/include/asm-s390/kerntypes.h      2005-05-17 18:52:39.968050344 +0800
10441 @@ -0,0 +1,46 @@
10442 +/*
10443 + * asm-s390/kerntypes.h
10444 + *
10445 + * Arch-dependent header file that includes headers for all arch-specific 
10446 + * types of interest.
10447 + * The kernel type information is used by the lcrash utility when
10448 + * analyzing system crash dumps or the live system. Using the type
10449 + * information for the running system, rather than kernel header files,
10450 + * makes for a more flexible and robust analysis tool.
10451 + *
10452 + * This source code is released under the GNU GPL.
10453 + */
10454 +
10455 +/* S/390 specific header files */
10456 +#ifndef _S390_KERNTYPES_H
10457 +#define _S390_KERNTYPES_H
10458 +
10459 +#include <asm/lowcore.h>
10460 +#include <asm/debug.h>
10461 +#include <asm/ccwdev.h>
10462 +#include <asm/ccwgroup.h>
10463 +#include <asm/qdio.h>
10464 +
10465 +/* channel subsystem driver */
10466 +#include "../../drivers/s390/cio/cio.h"
10467 +#include "../../drivers/s390/cio/chsc.h"
10468 +#include "../../drivers/s390/cio/css.h"
10469 +#include "../../drivers/s390/cio/device.h"
10470 +#include "../../drivers/s390/cio/qdio.h"
10471 +
10472 +/* dasd device driver */
10473 +#include "../../drivers/s390/block/dasd_int.h"
10474 +#include "../../drivers/s390/block/dasd_diag.h"
10475 +#include "../../drivers/s390/block/dasd_eckd.h"
10476 +#include "../../drivers/s390/block/dasd_fba.h"
10477 +
10478 +/* networking drivers */
10479 +#include "../../drivers/s390/net/fsm.h"
10480 +#include "../../drivers/s390/net/iucv.h"
10481 +#include "../../drivers/s390/net/lcs.h"
10482 +
10483 +/* zfcp device driver */
10484 +#include "../../drivers/s390/scsi/zfcp_def.h"
10485 +#include "../../drivers/s390/scsi/zfcp_fsf.h"
10486 +
10487 +#endif /* _S390_KERNTYPES_H */
10488 Index: linux-2.6.10-base/include/asm-s390/dump.h
10489 ===================================================================
10490 --- linux-2.6.10-base.orig/include/asm-s390/dump.h      2003-09-02 06:26:13.000000000 +0800
10491 +++ linux-2.6.10-base/include/asm-s390/dump.h   2005-05-17 18:52:39.969050192 +0800
10492 @@ -0,0 +1,10 @@
10493 +/*
10494 + * Kernel header file for Linux crash dumps.
10495 + */
10496 +
10497 +/* Nothing to be done here, we have proper hardware support */
10498 +#ifndef _ASM_DUMP_H
10499 +#define _ASM_DUMP_H
10500 +
10501 +#endif
10502 +
10503 Index: linux-2.6.10-base/include/asm-i386/kerntypes.h
10504 ===================================================================
10505 --- linux-2.6.10-base.orig/include/asm-i386/kerntypes.h 2003-09-02 06:26:13.000000000 +0800
10506 +++ linux-2.6.10-base/include/asm-i386/kerntypes.h      2005-05-17 18:52:39.969050192 +0800
10507 @@ -0,0 +1,21 @@
10508 +/*
10509 + * asm-i386/kerntypes.h
10510 + *
10511 + * Arch-dependent header file that includes headers for all arch-specific 
10512 + * types of interest.
10513 + * The kernel type information is used by the lcrash utility when
10514 + * analyzing system crash dumps or the live system. Using the type
10515 + * information for the running system, rather than kernel header files,
10516 + * makes for a more flexible and robust analysis tool.
10517 + *
10518 + * This source code is released under the GNU GPL.
10519 + */
10520 +
10521 +/* ix86-specific header files */
10522 +#ifndef _I386_KERNTYPES_H
10523 +#define _I386_KERNTYPES_H
10524 +
10525 +/* Use the default */
10526 +#include <asm-generic/kerntypes.h>
10527 +
10528 +#endif /* _I386_KERNTYPES_H */
10529 Index: linux-2.6.10-base/include/asm-i386/dump.h
10530 ===================================================================
10531 --- linux-2.6.10-base.orig/include/asm-i386/dump.h      2003-09-02 06:26:13.000000000 +0800
10532 +++ linux-2.6.10-base/include/asm-i386/dump.h   2005-05-17 18:52:39.969050192 +0800
10533 @@ -0,0 +1,90 @@
10534 +/*
10535 + * Kernel header file for Linux crash dumps.
10536 + *
10537 + * Created by: Matt Robinson (yakker@sgi.com)
10538 + *
10539 + * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
10540 + *
10541 + * This code is released under version 2 of the GNU GPL.
10542 + */
10543 +
10544 +/* This header file holds the architecture specific crash dump header */
10545 +#ifndef _ASM_DUMP_H
10546 +#define _ASM_DUMP_H
10547 +
10548 +/* necessary header files */
10549 +#include <asm/ptrace.h>
10550 +#include <asm/page.h>
10551 +#include <linux/threads.h>
10552 +#include <linux/mm.h>
10553 +
10554 +/* definitions */
10555 +#define DUMP_ASM_MAGIC_NUMBER  0xdeaddeadULL   /* magic number            */
10556 +#define DUMP_ASM_VERSION_NUMBER        0x3     /* version number          */
10557 +
10558 +/*
10559 + * Structure: __dump_header_asm
10560 + *  Function: This is the header for architecture-specific stuff.  It
10561 + *            follows right after the dump header.
10562 + */
10563 +struct __dump_header_asm {
10564 +       /* the dump magic number -- unique to verify dump is valid */
10565 +       u64             dha_magic_number;
10566 +
10567 +       /* the version number of this dump */
10568 +       u32             dha_version;
10569 +
10570 +       /* the size of this header (in case we can't read it) */
10571 +       u32             dha_header_size;
10572 +
10573 +       /* the esp for i386 systems */
10574 +       u32             dha_esp;
10575 +
10576 +       /* the eip for i386 systems */
10577 +       u32             dha_eip;
10578 +
10579 +       /* the dump registers */
10580 +       struct pt_regs  dha_regs;
10581 +
10582 +       /* smp specific */
10583 +       u32             dha_smp_num_cpus;
10584 +       u32             dha_dumping_cpu;
10585 +       struct pt_regs  dha_smp_regs[NR_CPUS];
10586 +       u32             dha_smp_current_task[NR_CPUS];
10587 +       u32             dha_stack[NR_CPUS];
10588 +       u32             dha_stack_ptr[NR_CPUS];
10589 +} __attribute__((packed));
10590 +
10591 +#ifdef __KERNEL__
10592 +
10593 +extern struct __dump_header_asm dump_header_asm;
10594 +
10595 +#ifdef CONFIG_SMP
10596 +extern cpumask_t irq_affinity[];
10597 +extern int (*dump_ipi_function_ptr)(struct pt_regs *);
10598 +extern void dump_send_ipi(void);
10599 +#else
10600 +#define dump_send_ipi() do { } while(0)
10601 +#endif
10602 +
10603 +static inline void get_current_regs(struct pt_regs *regs)
10604 +{
10605 +       __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
10606 +       __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
10607 +       __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
10608 +       __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
10609 +       __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
10610 +       __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
10611 +       __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
10612 +       __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
10613 +       __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
10614 +       __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
10615 +       __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
10616 +       __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
10617 +       __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
10618 +       regs->eip = (unsigned long)current_text_addr();
10619 +}
10620 +
10621 +#endif /* __KERNEL__ */
10622 +
10623 +#endif /* _ASM_DUMP_H */
10624 Index: linux-2.6.10-base/include/asm-i386/kmap_types.h
10625 ===================================================================
10626 --- linux-2.6.10-base.orig/include/asm-i386/kmap_types.h        2004-12-25 05:35:23.000000000 +0800
10627 +++ linux-2.6.10-base/include/asm-i386/kmap_types.h     2005-05-17 18:52:39.969050192 +0800
10628 @@ -23,7 +23,8 @@
10629  D(10)  KM_IRQ1,
10630  D(11)  KM_SOFTIRQ0,
10631  D(12)  KM_SOFTIRQ1,
10632 -D(13)  KM_TYPE_NR
10633 +D(13)  KM_DUMP,
10634 +D(14)  KM_TYPE_NR
10635  };
10636  
10637  #undef D
10638 Index: linux-2.6.10-base/include/asm-i386/smp.h
10639 ===================================================================
10640 --- linux-2.6.10-base.orig/include/asm-i386/smp.h       2004-12-25 05:35:50.000000000 +0800
10641 +++ linux-2.6.10-base/include/asm-i386/smp.h    2005-05-17 18:52:39.970050040 +0800
10642 @@ -37,6 +37,7 @@
10643  extern cpumask_t cpu_sibling_map[];
10644  
10645  extern void smp_flush_tlb(void);
10646 +extern void dump_send_ipi(void);
10647  extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
10648  extern void smp_invalidate_rcv(void);          /* Process an NMI */
10649  extern void (*mtrr_hook) (void);
10650 Index: linux-2.6.10-base/include/asm-i386/mach-default/irq_vectors.h
10651 ===================================================================
10652 --- linux-2.6.10-base.orig/include/asm-i386/mach-default/irq_vectors.h  2004-12-25 05:34:26.000000000 +0800
10653 +++ linux-2.6.10-base/include/asm-i386/mach-default/irq_vectors.h       2005-05-17 18:52:39.970050040 +0800
10654 @@ -48,6 +48,7 @@
10655  #define INVALIDATE_TLB_VECTOR  0xfd
10656  #define RESCHEDULE_VECTOR      0xfc
10657  #define CALL_FUNCTION_VECTOR   0xfb
10658 +#define DUMP_VECTOR            0xfa
10659  
10660  #define THERMAL_APIC_VECTOR    0xf0
10661  /*
10662 Index: linux-2.6.10-base/include/asm-m68k/kerntypes.h
10663 ===================================================================
10664 --- linux-2.6.10-base.orig/include/asm-m68k/kerntypes.h 2003-09-02 06:26:13.000000000 +0800
10665 +++ linux-2.6.10-base/include/asm-m68k/kerntypes.h      2005-05-17 18:52:39.970050040 +0800
10666 @@ -0,0 +1,21 @@
10667 +/*
10668 + * asm-m68k/kerntypes.h
10669 + *
10670 + * Arch-dependent header file that includes headers for all arch-specific 
10671 + * types of interest.
10672 + * The kernel type information is used by the lcrash utility when
10673 + * analyzing system crash dumps or the live system. Using the type
10674 + * information for the running system, rather than kernel header files,
10675 + * makes for a more flexible and robust analysis tool.
10676 + *
10677 + * This source code is released under the GNU GPL.
10678 + */
10679 +
10680 +/* m68k-specific header files */
10681 +#ifndef _M68K_KERNTYPES_H
10682 +#define _M68K_KERNTYPES_H
10683 +
10684 +/* Use the default */
10685 +#include <asm-generic/kerntypes.h>
10686 +
10687 +#endif /* _M68K_KERNTYPES_H */