Whamcloud - gitweb
b=3550
[fs/lustre-release.git] / lustre / kernel_patches / patches / mcore-2.4.20-8.patch
1 ? linux/.config
2 ? linux/include/linux/autoconf.h
3 ? linux/include/linux/modules
4 Index: linux/Makefile
5 ===================================================================
6 RCS file: /chaos/cvs/kernel-rh/linux/Makefile,v
7 retrieving revision 1.3.2.1
8 retrieving revision 1.3.2.1.2.1
9 diff -u -r1.3.2.1 -r1.3.2.1.2.1
10 --- linux/Makefile      12 Mar 2003 19:48:52 -0000      1.3.2.1
11 +++ linux/Makefile      1 Apr 2003 12:17:40 -0000       1.3.2.1.2.1
12 @@ -99,6 +99,10 @@
13  CFLAGS += -fomit-frame-pointer
14  endif
15  AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
16 +ifeq ($(CONFIG_MCL_COREDUMP),y)
17 +      CFLAGS += -g
18 +endif
19 +
20  
21  #
22  # ROOT_DEV specifies the default root-device when making the image.
23 Index: linux/Documentation/Configure.help
24 ===================================================================
25 RCS file: /chaos/cvs/kernel-rh/linux/Documentation/Configure.help,v
26 retrieving revision 1.3.2.1
27 retrieving revision 1.3.2.1.2.1
28 diff -u -r1.3.2.1 -r1.3.2.1.2.1
29 --- linux/Documentation/Configure.help  12 Mar 2003 19:48:52 -0000      1.3.2.1
30 +++ linux/Documentation/Configure.help  1 Apr 2003 12:17:40 -0000       1.3.2.1.2.1
31 @@ -21660,6 +21660,35 @@
32    This option allows you to run the kernel with data cache disabled.
33    Say Y if you experience CPM lock-ups.
34  
35 +Boot kernel image support
36 +CONFIG_BOOTIMG
37 +  Add support for booting a new Linux kernel from a running Linux
38 +  system. You need to download the bootimg(8) utility from
39 +  ftp://icaftp.epfl.ch/pub/people/almesber/misc/bootimg-current.tar.gz
40 +  in order to use this functionality.
41 +
42 +Protect SMP configuration tables
43 +CONFIG_BOOTIMG_SMP
44 +  On SMP systems, the BIOS stores tables with configuration data in
45 +  memory and an SMP-enabled kernel reads these tables. However, a
46 +  kernel without SMP support will overwrite such tables. If a kernel
47 +  without SMP support used bootimg to boot an SMP-enabled kernel, the
48 +  latter will probably crash when trying to read the SMP tables. The
49 +  CONFIG_BOOTIMG_SMP option enables minimal support for scanning and
50 +  protecting of SMP configuration tables also for kernels without SMP
51 +  support.
52 +
53 +In-memory kernel core dump facility
54 +CONFIG_MCL_COREDUMP
55 +  In conjunction with bootimg, this allows you to get kernel core dumps
56 +  of your system at panic() time.  The panic call is modified so that it
57 +  calls the core dump facility and reboots the system.  On the way back 
58 +  up, the kernel dump image is written out to disk by the accompanying 
59 +  init script.  You can use the crash analysis tool to analyze the core 
60 +  dump.  This tool can be found at :
61 +
62 +        http://www.missioncriticallinux.com/download
63 +
64  #
65  # m68k-specific kernel options
66  # Documented by Chris Lawrence <mailto:quango@themall.net> et al.
67 Index: linux/arch/i386/config.in
68 ===================================================================
69 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/config.in,v
70 retrieving revision 1.3.2.1
71 retrieving revision 1.3.2.1.2.2
72 diff -u -r1.3.2.1 -r1.3.2.1.2.2
73 --- linux/arch/i386/config.in   12 Mar 2003 19:49:05 -0000      1.3.2.1
74 +++ linux/arch/i386/config.in   1 Apr 2003 19:35:12 -0000       1.3.2.1.2.2
75 @@ -502,6 +502,12 @@
76     bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
77     bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
78     bool '  Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
79 +   if [ "$CONFIG_FRAME_POINTER " != "n" ]; then
80 +      bool '  Kernel Core Dump Facility' CONFIG_MCL_COREDUMP
81 +      if [ "$CONFIG_MCL_COREDUMP" = "y" ]; then
82 +         bool '  Reboot using bootimg' CONFIG_BOOTIMG
83 +      fi
84 +   fi
85  fi
86  
87  endmenu
88 Index: linux/arch/i386/vmlinux.lds
89 ===================================================================
90 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/vmlinux.lds,v
91 retrieving revision 1.1.1.1.4.1
92 retrieving revision 1.1.1.1.4.1.2.1
93 diff -u -r1.1.1.1.4.1 -r1.1.1.1.4.1.2.1
94 --- linux/arch/i386/vmlinux.lds 12 Mar 2003 19:49:05 -0000      1.1.1.1.4.1
95 +++ linux/arch/i386/vmlinux.lds 1 Apr 2003 12:17:40 -0000       1.1.1.1.4.1.2.1
96 @@ -19,6 +19,13 @@
97    .rodata : { *(.rodata) *(.rodata.*) }
98    .kstrtab : { *(.kstrtab) }
99  
100 +  . = ALIGN(16);               /* Relocatable bootimage code */
101 +  __bootimg_start = .;
102 +  .bootimg : {
103 +       *(.bootimg)
104 +       }
105 +  __bootimg_end = .;
106 +
107    . = ALIGN(16);               /* Exception table */
108    __start___ex_table = .;
109    __ex_table : { *(__ex_table) }
110 Index: linux/arch/i386/boot/setup.S
111 ===================================================================
112 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/boot/setup.S,v
113 retrieving revision 1.2.2.1
114 retrieving revision 1.2.2.1.2.1
115 diff -u -r1.2.2.1 -r1.2.2.1.2.1
116 --- linux/arch/i386/boot/setup.S        12 Mar 2003 19:49:05 -0000      1.2.2.1
117 +++ linux/arch/i386/boot/setup.S        1 Apr 2003 12:17:40 -0000       1.2.2.1.2.1
118 @@ -105,16 +105,22 @@
119  # flags, unused bits must be zero (RFU) bit within loadflags
120  loadflags:
121  LOADED_HIGH    = 1                     # If set, the kernel is loaded high
122 +RELOADS_GDT    = 2                     # if set, kernel reloads GDT, such that
123 +                                       # boot loader does not have to provide
124 +                                       # GDT in a "safe" memory location
125  CAN_USE_HEAP   = 0x80                  # If set, the loader also has set
126                                         # heap_end_ptr to tell how much
127                                         # space behind setup.S can be used for
128                                         # heap purposes.
129                                         # Only the loader knows what is free
130 -#ifndef __BIG_KERNEL__
131 -               .byte   0
132 -#else
133 -               .byte   LOADED_HIGH
134 +_FLAGS = 0
135 +#ifdef __BIG_KERNEL__
136 +               _FLAGS = _FLAGS | LOADED_HIGH
137  #endif
138 +#ifdef CONFIG_BOOTIMG
139 +               _FLAGS = _FLAGS | RELOADS_GDT
140 +#endif
141 +               .byte _FLAGS
142  
143  setup_move_size: .word  0x8000         # size to move, when setup is not
144                                         # loaded at 0x90000. We will move setup 
145 Index: linux/arch/i386/kernel/Makefile
146 ===================================================================
147 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/Makefile,v
148 retrieving revision 1.2.2.1
149 retrieving revision 1.2.2.1.2.1
150 diff -u -r1.2.2.1 -r1.2.2.1.2.1
151 --- linux/arch/i386/kernel/Makefile     12 Mar 2003 19:49:05 -0000      1.2.2.1
152 +++ linux/arch/i386/kernel/Makefile     1 Apr 2003 12:17:40 -0000       1.2.2.1.2.1
153 @@ -49,6 +49,7 @@
154  obj-$(CONFIG_X86_LONGRUN)      += longrun.o
155  obj-$(CONFIG_ELAN_CPUFREQ)     += elanfreq.o
156  obj-$(CONFIG_PROFILING)                += profile.o
157 +obj-$(CONFIG_MCL_COREDUMP)     += crash.o
158  
159  
160  include $(TOPDIR)/Rules.make
161 Index: linux/arch/i386/kernel/crash.c
162 ===================================================================
163 RCS file: linux/arch/i386/kernel/crash.c
164 diff -N linux/arch/i386/kernel/crash.c
165 --- /dev/null   1 Jan 1970 00:00:00 -0000
166 +++ linux/arch/i386/kernel/crash.c      1 Apr 2003 12:17:40 -0000       1.1.6.1
167 @@ -0,0 +1,82 @@
168 +/*
169 + *  linux/arch/i386/crash.c
170 + *
171 + *  Architecture dependant code for MCL in-memory core dump.
172 + */
173 +#include <linux/sched.h>
174 +#include <linux/types.h>
175 +#include <linux/smp.h>
176 +#include <linux/crash.h>
177 +#include <linux/reboot.h>
178 +#include <linux/bootimg.h>
179 +
180 +inline void crash_save_regs(void) {
181 +       static unsigned long regs[8];
182 +
183 +       __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs[0]));
184 +       __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs[1]));
185 +       __asm__ __volatile__("movl %%edx,%0" : "=m"(regs[2]));
186 +       __asm__ __volatile__("movl %%esi,%0" : "=m"(regs[3]));
187 +       __asm__ __volatile__("movl %%edi,%0" : "=m"(regs[4]));
188 +       __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs[5]));
189 +       __asm__ __volatile__("movl %%eax,%0" : "=m"(regs[6]));
190 +       __asm__ __volatile__("movl %%esp,%0" : "=m"(regs[7]));
191 +
192 +       panic_regs = regs;
193 +}
194 +
195 +/*
196 + *  Save the current stack pointer and EIP.
197 + */
198 +void crash_save_current_state(struct task_struct *tp)
199 +{
200 +       /*
201 +        *  Here we save ebp instead of esp just in case the compiler
202 +        *  decides to put an extra push in before we execute this
203 +        *  instruction (thus invalidating our frame pointer).
204 +        */
205 +       asm volatile("movl %%ebp,%0":"=m" (*(u_long *)&tp->thread.esp));
206 +       tp->thread.eip = (u_long)crash_save_current_state;
207 +       panic_ksp[smp_processor_id()] = tp->thread.esp;
208 +       mb();
209 +
210 +       save_core();
211 +
212 +       crash_halt_or_reboot(1);
213 +}
214 +
215 +/*
216 + *  If we are not the panicking thread, we simply halt.  Otherwise,
217 + *  we take care of calling the reboot code.
218 + */
219 +void crash_halt_or_reboot(int boot_cpu)
220 +{
221 +#ifdef CONFIG_SMP
222 +       if (!boot_cpu) {
223 +               stop_this_cpu(NULL);
224 +               /* NOTREACHED */
225 +       }
226 +#endif
227 +       machine_restart(NULL);
228 +}
229 +
230 +void crash_cleanup_smp_state(void)
231 +{
232 +       /*
233 +        *  Here we duplicate smp_send_stop.  Crash_halt_or_reboot() calls
234 +        *  stop_this_cpu.  We now know that we are the only one running, 
235 +        *  so we finish off the smp_send_stop function.
236 +        */
237 +       __cli();
238 +#ifdef CONFIG_SMP
239 +       disable_local_APIC();
240 +#endif
241 +}
242 +
243 +/*
244 + *  Core dump IPI
245 + */
246 +void smp_crash_funnel_cpu(void)
247 +{
248 +       crash_save_current_state(current);
249 +}
250 Index: linux/arch/i386/kernel/nmi.c
251 ===================================================================
252 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/nmi.c,v
253 retrieving revision 1.2.2.1
254 retrieving revision 1.2.2.1.2.1
255 diff -u -r1.2.2.1 -r1.2.2.1.2.1
256 --- linux/arch/i386/kernel/nmi.c        12 Mar 2003 19:49:06 -0000      1.2.2.1
257 +++ linux/arch/i386/kernel/nmi.c        1 Apr 2003 12:17:40 -0000       1.2.2.1.2.1
258 @@ -374,11 +374,18 @@
259                         bust_spinlocks(1);
260                         printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
261                         show_registers(regs);
262 +#ifdef CONFIG_MCL_COREDUMP
263 +                       spin_unlock(&nmi_print_lock);
264 +                       bust_spinlocks(0);
265 +                       panic("die");
266 +                       /* NOTREACHED */
267 +#else
268                         printk("console shuts up ...\n");
269                         console_silent();
270                         spin_unlock(&nmi_print_lock);
271                         bust_spinlocks(0);
272                         do_exit(SIGSEGV);
273 +#endif
274                 }
275         } else {
276                 last_irq_sums[cpu] = sum;
277 Index: linux/arch/i386/kernel/process.c
278 ===================================================================
279 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/process.c,v
280 retrieving revision 1.2.2.2
281 retrieving revision 1.2.2.2.2.1
282 diff -u -r1.2.2.2 -r1.2.2.2.2.1
283 --- linux/arch/i386/kernel/process.c    1 Apr 2003 02:11:17 -0000       1.2.2.2
284 +++ linux/arch/i386/kernel/process.c    1 Apr 2003 12:17:40 -0000       1.2.2.2.2.1
285 @@ -50,6 +50,9 @@
286  #ifdef CONFIG_MATH_EMULATION
287  #include <asm/math_emu.h>
288  #endif
289 +#ifdef CONFIG_BOOTIMG
290 +#include <linux/bootimg.h>
291 +#endif
292  
293  #include <linux/irq.h>
294  
295 @@ -377,7 +380,21 @@
296  
297  void machine_restart(char * __unused)
298  {
299 +#ifdef CONFIG_MCL_COREDUMP
300 +       extern char *panicmsg;
301 +       /*
302 +        *  Only call bootimg if we have a valid descriptor and
303 +        *  we are in a panic() context.
304 +        */
305 +       if (panicmsg)
306 +#endif
307 +#ifdef CONFIG_BOOTIMG
308 +               if (bootimg_dsc.page_dir)
309 +                       boot_image();
310 +#endif
311 +
312  #if CONFIG_SMP
313 +{
314         int cpuid;
315         
316         cpuid = GET_APIC_ID(apic_read(APIC_ID));
317 @@ -413,6 +430,7 @@
318         if (!netdump_func)
319                 smp_send_stop();
320         disable_IO_APIC();
321 +}
322  #endif
323  
324         if(!reboot_thru_bios) {
325 Index: linux/arch/i386/kernel/setup.c
326 ===================================================================
327 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/setup.c,v
328 retrieving revision 1.3.2.1
329 retrieving revision 1.3.2.1.2.2
330 diff -u -r1.3.2.1 -r1.3.2.1.2.2
331 --- linux/arch/i386/kernel/setup.c      12 Mar 2003 19:49:06 -0000      1.3.2.1
332 +++ linux/arch/i386/kernel/setup.c      1 Apr 2003 17:55:35 -0000       1.3.2.1.2.2
333 @@ -116,6 +116,9 @@
334  #include <asm/mpspec.h>
335  #include <asm/mmu_context.h>
336  #include <asm/edd.h>
337 +#ifdef CONFIG_MCL_COREDUMP
338 +#include <linux/crash.h>
339 +#endif
340  /*
341   * Machine setup..
342   */
343 @@ -973,6 +976,7 @@
344  static unsigned long __init setup_memory(void)
345  {
346         unsigned long bootmap_size, start_pfn, max_low_pfn;
347 +       unsigned long bootmap_pages = 0UL, crash_pages = 0UL;
348  
349         /*
350          * partially used pages are not usable - thus
351 @@ -992,6 +996,21 @@
352         printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
353                 pages_to_mb(highend_pfn - highstart_pfn));
354  #endif
355 +
356 +#ifdef CONFIG_MCL_COREDUMP
357 +       bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
358 +       crash_pages = crash_pages_needed();
359 +
360 +       printk("start_pfn: %d, bootmap_pages: %d\n", start_pfn, bootmap_pages);
361 +
362 +       crash_init((u_long)phys_to_virt(PFN_PHYS(start_pfn)),
363 +                  (u_long)phys_to_virt(PFN_PHYS(LOW_OFFSET + start_pfn)),
364 +                  (u_long)phys_to_virt(PFN_PHYS(LOW_OFFSET + start_pfn +
365 +                                                crash_pages)));
366 +
367 +       printk("new start_pfn: %08lx\n", PFN_PHYS(start_pfn));
368 +       printk("crash map starts at %lx\n",(start_pfn+bootmap_pages)*PAGE_SIZE);
369 +#endif
370         printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
371                         pages_to_mb(max_low_pfn));
372         /*
373 @@ -1007,8 +1026,8 @@
374          * the (very unlikely) case of us accidentally initializing the
375          * bootmem allocator with an invalid RAM area.
376          */
377 -       reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
378 -                        bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
379 +       reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) + bootmap_size + 
380 +                    ((1+crash_pages)*PAGE_SIZE) + PAGE_SIZE-1) - (HIGH_MEMORY));
381  
382         /*
383          * reserve physical page 0 - it's a special BIOS page on many boxes,
384 @@ -1016,6 +1035,16 @@
385          */
386         reserve_bootmem(0, PAGE_SIZE);
387  
388 +#ifdef CONFIG_BOOTIMG
389 +       /*
390 +        * bootimg(8) reads the old parameter block. Note that the copy in
391 +        * empty_zero_page will vanish when mem_init runs. (Should we
392 +        * memcpy(phys_to_virt(0x90000), PARAM, PAGE_SIZE);
393 +        * now ?)
394 +        */
395 +       reserve_bootmem(0x90000, PAGE_SIZE);
396 +#endif
397 +
398  #ifdef CONFIG_SMP
399         /*
400          * But first pinch a few for the stack/trampoline stuff
401 @@ -1032,6 +1061,7 @@
402         find_smp_config();
403  #endif
404  #ifdef CONFIG_BLK_DEV_INITRD
405 +       printk("caution: initrd may overwrite dump\n"); /* phro */
406         if (LOADER_TYPE && INITRD_START) {
407                 if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
408                         reserve_bootmem(INITRD_START, INITRD_SIZE);
409 @@ -1172,6 +1202,12 @@
410         smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
411  #endif
412         paging_init();
413 +#ifdef CONFIG_MCL_COREDUMP
414 +       /*
415 +        * Reserve crash pages
416 +        */
417 +       crash_mark_dump_reserved();
418 +#endif
419  #ifdef CONFIG_X86_LOCAL_APIC
420         /*
421          * get boot-time SMP configuration:
422 Index: linux/arch/i386/kernel/smp.c
423 ===================================================================
424 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/smp.c,v
425 retrieving revision 1.3.2.1
426 retrieving revision 1.3.2.1.2.1
427 diff -u -r1.3.2.1 -r1.3.2.1.2.1
428 --- linux/arch/i386/kernel/smp.c        12 Mar 2003 19:49:06 -0000      1.3.2.1
429 +++ linux/arch/i386/kernel/smp.c        1 Apr 2003 12:17:40 -0000       1.3.2.1.2.1
430 @@ -23,6 +23,9 @@
431  #include <asm/pgalloc.h>
432  #include <asm/smpboot.h>
433  
434 +#ifdef CONFIG_MCL_COREDUMP
435 +#include <asm/crash.h>
436 +#endif
437  /*
438   *     Some notes on x86 processor bugs affecting SMP operation:
439   *
440 @@ -579,7 +582,7 @@
441         return 0;
442  }
443  
444 -static void stop_this_cpu (void * dummy)
445 +void stop_this_cpu (void * dummy)
446  {
447         /*
448          * Remove this CPU:
449 Index: linux/arch/i386/kernel/traps.c
450 ===================================================================
451 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/traps.c,v
452 retrieving revision 1.3.2.1
453 retrieving revision 1.3.2.1.2.1
454 diff -u -r1.3.2.1 -r1.3.2.1.2.1
455 --- linux/arch/i386/kernel/traps.c      12 Mar 2003 19:49:06 -0000      1.3.2.1
456 +++ linux/arch/i386/kernel/traps.c      1 Apr 2003 12:17:40 -0000       1.3.2.1.2.1
457 @@ -52,6 +52,10 @@
458  #include <linux/irq.h>
459  #include <linux/module.h>
460  
461 +#ifdef CONFIG_MCL_COREDUMP
462 +#include <linux/crash.h>
463 +#endif
464 +
465  asmlinkage int system_call(void);
466  asmlinkage void lcall7(void);
467  asmlinkage void lcall27(void);
468 @@ -309,7 +313,11 @@
469                 netdump_func(regs);
470         bust_spinlocks(0);
471         spin_unlock_irq(&die_lock);
472 -       do_exit(SIGSEGV);
473 +#ifdef CONFIG_MCL_COREDUMP 
474 +       if(panic_on_oops)
475 +               panic("die");
476 +#endif
477 +       do_exit(SIGSEGV);/* NOTREACHED */
478  }
479  
480  static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
481 Index: linux/drivers/char/misc.c
482 ===================================================================
483 RCS file: /chaos/cvs/kernel-rh/linux/drivers/char/misc.c,v
484 retrieving revision 1.2
485 retrieving revision 1.2.4.1
486 diff -u -r1.2 -r1.2.4.1
487 --- linux/drivers/char/misc.c   25 Sep 2002 17:11:05 -0000      1.2
488 +++ linux/drivers/char/misc.c   1 Apr 2003 12:17:41 -0000       1.2.4.1
489 @@ -78,6 +78,8 @@
490  extern int i8k_init(void);
491  extern int lcd_init(void);
492  
493 +extern int crash_init_chrdev(void);
494 +
495  static int misc_read_proc(char *buf, char **start, off_t offset,
496                           int len, int *eof, void *private)
497  {
498 @@ -255,6 +257,9 @@
499  int __init misc_init(void)
500  {
501         create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL);
502 +#ifdef CONFIG_MCL_COREDUMP
503 +       crash_init_chrdev();
504 +#endif
505  #ifdef CONFIG_MVME16x
506         rtc_MK48T08_init();
507  #endif
508 Index: linux/drivers/char/sysrq.c
509 ===================================================================
510 RCS file: /chaos/cvs/kernel-rh/linux/drivers/char/sysrq.c,v
511 retrieving revision 1.2.2.1
512 retrieving revision 1.2.2.1.2.2
513 diff -u -r1.2.2.1 -r1.2.2.1.2.2
514 --- linux/drivers/char/sysrq.c  12 Mar 2003 19:49:47 -0000      1.2.2.1
515 +++ linux/drivers/char/sysrq.c  1 Apr 2003 17:55:35 -0000       1.2.2.1.2.2
516 @@ -97,7 +97,18 @@
517         action_msg:     "Resetting",
518  };
519  
520 -
521 +#ifdef CONFIG_MCL_COREDUMP
522 +/* kernel core dump sysrq */
523 +static void sysrq_handle_coredump(int key, struct pt_regs *pt_regs,
524 +               struct kbd_struct *kbd, struct tty_struct *ttty) {
525 +       panic("sysrq");
526 +}
527 +static struct sysrq_key_op sysrq_coredump_op = {
528 +       handler:        sysrq_handle_coredump,
529 +       help_msg:       "Crash",
530 +       action_msg:     "Dumping core",
531 +};
532 +#endif
533  
534  /* SYNC SYSRQ HANDLERS BLOCK */
535  
536 @@ -334,7 +345,11 @@
537                  it is handled specially on the spark
538                  and will never arive */
539  /* b */        &sysrq_reboot_op,
540 +#ifdef CONFIG_MCL_COREDUMP
541 +/* c */        &sysrq_coredump_op,
542 +#else
543  /* c */        NULL,
544 +#endif
545  /* d */        NULL,
546  /* e */        &sysrq_term_op,
547  /* f */        NULL,
548 Index: linux/include/asm-i386/bootimg.h
549 ===================================================================
550 RCS file: linux/include/asm-i386/bootimg.h
551 diff -N linux/include/asm-i386/bootimg.h
552 --- /dev/null   1 Jan 1970 00:00:00 -0000
553 +++ linux/include/asm-i386/bootimg.h    1 Apr 2003 12:17:41 -0000       1.1.6.1
554 @@ -0,0 +1,141 @@
555 +/* asm-i386/bootimg.h - Boot image, i386-specific code */
556 +
557 +/* Written 2000 by Werner Almesberger */
558 +
559 +/*
560 + * When porting bootimg(2) to a new architcture, you need to adapt the
561 + * functions and definitions in this file.
562 + */
563 +
564 +
565 +#ifndef _ASM_I386_BOOTIMG_H
566 +#define _ASM_I386_BOOTIMG_H
567 +
568 +#include <linux/config.h>
569 +#include <asm/system.h>
570 +
571 +#ifdef CONFIG_SMP
572 +#include <linux/smp.h>
573 +#include <linux/irq.h>
574 +#endif
575 +
576 +
577 +/*
578 + * The memory page with the code currently executing has been copied from
579 + * old_page to new_page. Jump there.
580 + *
581 + * Note: flush_icache_range has already been called on the new page.
582 + */
583 +
584 +static inline void jump_relocated(unsigned long old_page,unsigned long new_page)
585 +{
586 +       int tmp;
587 +
588 +       __asm__ __volatile__(
589 +       "stc\n\t"
590 +       "call 1f\n"
591 +       "1:\tjnc 2f\n\t"
592 +       "popl %0\n\t"
593 +       "addl %1,%0\n\t"
594 +       "addl %1,%%esp\n\t"
595 +       "clc\n\t"
596 +       "jmp *%0\n"
597 +       "2:"
598 +       : "=&r" (tmp) : "r" (new_page-old_page));
599 +}
600 +
601 +
602 +/*
603 + * Stop paging, such that
604 + *  - page tables can be overwritten
605 + *  - all physical memory can be accessed
606 + *  - all physical memory is identity-mapped
607 + *
608 + * (Other rules are possible, but need to be encoded in bootimg(8).)
609 + */
610 +
611 +static inline void stop_paging(void)
612 +{
613 +       unsigned long msw;
614 +
615 +       __asm__ __volatile__(
616 +       "movl %%cr0,%0\n\t"
617 +       "andl $0x7fffffff,%0\n\t"
618 +       "movl %0,%%cr0\n\t"
619 +       "jmp 1f\n\t"    /* i486 and such */
620 +       "1:"
621 +
622 +/* Clear the PAE bit in register %cr4 if we were in PAE mode.  The initial
623 + * page table set up by the new kernel's bootstrap code is non-PAE regardless
624 + * of whether the new kernel is a PAE kernel.  By clearing the PAE bit here,
625 + * we make sure the bootstrap code doesn't accidentally enable PAE mode when
626 + * it turns on address translation.
627 + */
628 +#ifdef CONFIG_X86_PAE
629 +       "movl %%cr4,%0\n\t"
630 +       "andl $0xffffffdf,%0\n\t"
631 +       "movl %0,%%cr4\n\t"
632 +#endif
633 +
634 +       : "=&r" (msw) : : "memory");
635 +}
636 +
637 +
638 +/*
639 + * Stop any remaining concurrency in the system. If become_only_thread fails
640 + * but the system is still usable, become_only_thread should return an error
641 + * code. If no recovery is possible, it may as well panic.
642 + */
643 +
644 +static inline int become_only_thread(void)
645 +{
646 +#ifdef CONFIG_SMP
647 +       smp_send_stop();
648 +       disable_IO_APIC();
649 +#endif
650 +       cli();
651 +       return 0;
652 +}
653 +
654 +
655 +/*
656 + * A conservative estimate of the number of bytes relocate_and_jump allocated
657 + * on the stack. This is only used for sanity checking before running code,
658 + * because we can't recover from failure in relocate_and_jump.
659 + */
660 +
661 +#define RESERVE_MIN_RELOC_STACK        256
662 +
663 +
664 +/*
665 + * Change the stack pointer such that stack is at the end of the specified
666 + * page. No data on the old stack will be accessed anymore, so no copying is
667 + * required.
668 + */
669 +
670 +static inline void stack_on_page(void *page)
671 +{
672 +       __asm__ __volatile__(
673 +       "push %%ds\n\t"
674 +       "pop %%ss\n\t"
675 +       "movl %0,%%esp\n\t"
676 +       "addl $0x1000,%%esp\n\t"
677 +       : : "r" (page));
678 +}
679 +
680 +/*
681 + * Set up things such that the kernel will be comfortable (e.g. some
682 + * architectures expect the boot loader to set registers in certain ways),
683 + * and then jump to the kernel's entry address.
684 + */
685 +
686 +static inline void jump_to_kernel(void (*kernel_entry)(void))
687 +{
688 +       __asm__ __volatile__(
689 +       "mov $0x90000,%%esi\n\t"
690 +       : : );
691 +
692 +       kernel_entry();
693 +}
694 +
695 +#endif
696 Index: linux/include/asm-i386/crash.h
697 ===================================================================
698 RCS file: linux/include/asm-i386/crash.h
699 diff -N linux/include/asm-i386/crash.h
700 --- /dev/null   1 Jan 1970 00:00:00 -0000
701 +++ linux/include/asm-i386/crash.h      1 Apr 2003 12:17:41 -0000       1.1.6.1
702 @@ -0,0 +1,15 @@
703 +#ifndef __ASM_CRASH_H
704 +#define __ASM_CRASH_H
705 +
706 +#define UPPER_MEM_BACKUP 0
707 +#define LOWER_MEM_FORWARD 0
708 +#define LOW_OFFSET 100
709 +
710 +/*
711 + *  These two functions are inlined on alpha.  That's why they appear
712 + *  in the arch dependent include file.
713 + */
714 +void crash_save_current_state(struct task_struct *);
715 +void crash_halt_or_reboot(int);
716 +
717 +#endif
718 Index: linux/include/linux/bootimg.h
719 ===================================================================
720 RCS file: linux/include/linux/bootimg.h
721 diff -N linux/include/linux/bootimg.h
722 --- /dev/null   1 Jan 1970 00:00:00 -0000
723 +++ linux/include/linux/bootimg.h       1 Apr 2003 12:17:41 -0000       1.1.6.1
724 @@ -0,0 +1,84 @@
725 +/* linux/bootimg.h - Boot image, general definitions */
726 +
727 +/* Written 2000 by Werner Almesberger */
728 +
729 +
730 +#ifndef _LINUX_BOOTIMG_H
731 +#define _LINUX_BOOTIMG_H
732 +
733 +
734 +/*
735 + * Constraints on image_map:
736 + *  - each image_map[n] is the virtual address of a page-sized memory region
737 + *    readable by the user
738 + *  - currently, image_map[n] is not required to be page-aligned, but this may
739 + *    change in the future if we want to map pages directly to lower memory
740 + *    pressure (NB: mapping works for ELF and plain binary images, but usually
741 + *    not for (b)zImages, because the prepended boot and setup sectors
742 + *    mis-align them)
743 + *
744 + * Constraints on load_map:
745 + *  - each load_map[] is the physical address of a page in RAM
746 + */
747 +
748 +struct boot_image {
749 +       void **image_map;       /* pointers to image pages in user memory */
750 +       int pages;              /* length in pages */
751 +       unsigned long *load_map;/* list of destination pages (physical addr) */
752 +       unsigned long start;    /* jump to this physical address */
753 +       int flags;              /* for future use, must be zero for now */
754 +};
755 +
756 +
757 +#ifdef __KERNEL__
758 +
759 +#define __bootimg __attribute__ ((__section__ (".bootimg")))
760 +
761 +
762 +struct bootimg_dsc {
763 +       unsigned long self;             /* code page            ALL ADDRESSES */
764 +       unsigned long scratch;          /* scratch page         ARE PHYSICAL !*/
765 +       unsigned long **page_dir;       /* src & dst page tables              */
766 +       void (*jump_to)(void);          /* start address                      */
767 +       int pages;                      /* number of pages */
768 +    unsigned long csum; /* Kernel Image checksum */
769 +};
770 +
771 +/*
772 + * page_dir contains pointers to pages containing pointers to pages. We call
773 + * page_dir a "directory" and the page page_dir[n] points to a "table". The
774 + * first PAGES_PER_TABLE/2 entries of page_dir are for source pages, and other
775 + * half are for destination pages.
776 + */
777 +
778 +/*
779 + * Note that the definitions used here do not necessarily correspond to the
780 + * architecture-specific PTRS_PER_PTE, __pte_offset, etc.
781 + */
782
783 +#define PAGES_PER_TABLE        (PAGE_SIZE/sizeof(void *))
784 +#define FROM_TABLE(i)  ((i)/PAGES_PER_TABLE)
785 +#define TO_TABLE(i)    ((i)/PAGES_PER_TABLE+PAGES_PER_TABLE/2)
786 +#define PAGE_NR(i)     ((i) % PAGES_PER_TABLE)
787 +
788 +
789 +extern char __bootimg_start,__bootimg_end;     /* linker segment boundaries */
790 +extern unsigned long *unity_page; /* unity-mapped page for i386 */
791 +
792 +/*
793 + * relocate_and_jump runs in its own page with its own stack. This makes it
794 + * difficult to pass parameters. The solution chosen here is to use the global
795 + * variable bootimg_dsc, which is copied into an "auto" variable by
796 + * relocate_and_jump before any copying or relocation takes place.
797 + */
798 +
799 +extern struct bootimg_dsc bootimg_dsc;
800 +
801 +typedef void (*relocate_and_jump_t)(void);
802 +
803 +void relocate_and_jump(void);
804 +int  boot_image(void);
805 +
806 +#endif /* __KERNEL__ */
807 +
808 +#endif
809 Index: linux/include/linux/crash.h
810 ===================================================================
811 RCS file: linux/include/linux/crash.h
812 diff -N linux/include/linux/crash.h
813 --- /dev/null   1 Jan 1970 00:00:00 -0000
814 +++ linux/include/linux/crash.h 1 Apr 2003 12:17:41 -0000       1.1.6.1
815 @@ -0,0 +1,119 @@
816 +#ifndef __LINUX_CRASH_H
817 +#define __LINUX_CRASH_H
818 +
819 +/* defines for interfacing with user-space (ioctls, etc) */
820 +struct ioctl_getdump {
821 +       unsigned long kva;
822 +       unsigned long buf;
823 +};
824 +
825 +#define CRASH_IOC_MAGIC 'C'
826 +
827 +#define CRASH_IOCFREEDUMP _IO(CRASH_IOC_MAGIC, 0)
828 +#define CRASH_IOCGETDUMP _IOWR(CRASH_IOC_MAGIC, 1, struct ioctl_getdump)
829 +#define CRASH_IOCBOOTIMG _IOWR(CRASH_IOC_MAGIC, 2, struct boot_image)
830 +#define CRASH_IOCVERSION _IO(CRASH_IOC_MAGIC, 3)
831 +
832 +/* kernel-only part of crash.h */
833 +#ifdef __KERNEL__
834 +#include <asm/crash.h>
835 +
836 +#define CRASH_K_MINOR (1)
837 +#define CRASH_K_MAJOR (0)
838 +
839 +/*
840 + * Crash prototypes.
841 + */
842 +void save_core(void);
843 +void crash_mark_dump_reserved(void);
844 +void crash_init(u_long bootmap_va, u_long crash_va, u_long end_alloc_va);
845 +u_long crash_pages_needed(void);
846 +void smp_crash_funnel_cpu(void);
847 +void crash_cleanup_smp_state(void);
848 +
849 +/*
850 + *  Arch dependant crash.c funcs
851 + */
852 +void crash_save_current_state(struct task_struct *);
853 +void crash_halt_or_reboot(int);
854 +inline void crash_save_regs(void);
855 +
856 +/*
857 + * Crash globals
858 + */
859 +extern u_long crash_dump_header;
860 +extern volatile u_long panic_ksp[];
861 +extern volatile int crash_release;
862 +extern int panic_on_oops;
863 +extern char *panicmsg;
864 +extern int panic_processor;
865 +extern int crash_perform_sync;
866 +extern unsigned long *panic_regs;
867 +
868 +/*
869 + * symbols not exported by linux header files
870 + */
871 +extern void stop_this_cpu(void *);
872 +
873 +/*  struct crash_map_hdr located at byte offset 0 */
874 +/* on-disk formats */
875 +
876 +#define trunc_page(x)   ((void *)(((unsigned long)(x)) & ~((unsigned long)(PAGE_SIZE - 1))))
877 +#define round_page(x)   trunc_page(((unsigned long)(x)) + ((unsigned long)(PAGE_SIZE - 1)))
878 +
879 +#define CRASH_MAGIC 0x9a8bccdd
880 +#define CRASH_SOURCE_PAGES 128
881 +#define CRASH_SUB_MAP_BYTES ((u_long)round_page((CRASH_SOURCE_PAGES+1)*sizeof(u_long)))
882 +#define CRASH_SUB_MAP_PAGES (CRASH_SUB_MAP_BYTES / PAGE_SIZE)
883 +#define CRASH_UNCOMPR_BUF_PAGES (CRASH_SOURCE_PAGES + CRASH_SUB_MAP_PAGES)
884 +#define CRASH_COMPR_BUF_PAGES (CRASH_UNCOMPR_BUF_PAGES + (CRASH_UNCOMPR_BUF_PAGES/4))
885 +#define CRASH_COMPESS_PRIME_PAGES (2*CRASH_COMPR_BUF_PAGES)
886 +#define CRASH_ZALLOC_PAGES 16*5*2      /* 2 to handle crash in crash */
887 +#define CRASH_LOW_WATER_PAGES 100
888 +
889 +#define CRASH_CPU_TIMEOUT 5000 /* 5 sec wait for other cpus to stop */
890 +
891 +#define CRASH_MARK_RESERVED(addr) (set_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags))
892 +#define CRASH_CLEAR_RESERVED(addr) (clear_bit(PG_reserved,&mem_map[MAP_NR(addr)].flags))
893 +#define CRASH_MARK_BOOT_RESERVED(addr) reserve_bootmem(virt_to_phys((void *)addr), PAGE_SIZE);
894 +
895 +typedef int boolean_t;
896 +
897 +#define TRUE 1
898 +#define FALSE 0
899 +
900 +/* mem structure */
901 +struct mem_crash_map_hdr {
902 +       long magic[4];          /* identify crash dump */
903 +       u_long map;             /* location of map */
904 +       u_long map_pages;
905 +       u_long data_pages;
906 +       u_long compr_units;
907 +       u_long boot_reserved_start;
908 +       u_long boot_reserved_end;
909 +};
910 +struct mem_crash_map_entry {
911 +       u_long src_va;          /* source start of larger non-contig 
912 +                                * block.  a src_va of -1 means that 
913 +                                * the dest_page_va is the location of 
914 +                                * the next map page */
915 +       u_long dest_page_va;    /* dest of this sub block */
916 +       u_long check_sum;       /* check_sum for dest data */
917 +};
918 +
919 +/* file structure */
920 +struct crash_map_hdr {
921 +       long magic[4];          /* identify crash dump */
922 +       int blk_size;           /* block size for this device */
923 +       int map_block;          /* location of map */
924 +       int map_blocks;         /* number of blocks for map */
925 +};
926 +struct crash_map_entry {
927 +       u_long start_va;        /* virtual address */
928 +       char *exp_data;         /* expanded data in memory */
929 +       int start_blk;          /* device location */
930 +       int num_blks;
931 +};
932 +
933 +#endif /* __KERNEL__ */
934 +#endif /* __LINUX_CRASH_H */
935 Index: linux/include/linux/mm.h
936 ===================================================================
937 RCS file: /chaos/cvs/kernel-rh/linux/include/linux/mm.h,v
938 retrieving revision 1.2.2.1
939 retrieving revision 1.2.2.1.2.2
940 diff -u -r1.2.2.1 -r1.2.2.1.2.2
941 --- linux/include/linux/mm.h    12 Mar 2003 19:51:27 -0000      1.2.2.1
942 +++ linux/include/linux/mm.h    1 Apr 2003 17:55:35 -0000       1.2.2.1.2.2
943 @@ -331,6 +331,11 @@
944  #define PG_lru                 18
945  #define PG_active_cache                19
946  #define PG_fs_1                        20      /* Filesystem specific */
947 +#ifdef CONFIG_MCL_COREDUMP
948 +#define PG_free                        21
949 +#define PG_shm                 22
950 +#define PG_anon                        23
951 +#endif
952  
953  /* Make it prettier to test the above... */
954  #define UnlockPage(page)       unlock_page(page)
955 @@ -452,6 +457,11 @@
956  #define PageSetSlab(page)      set_bit(PG_slab, &(page)->flags)
957  #define PageClearSlab(page)    clear_bit(PG_slab, &(page)->flags)
958  #define PageReserved(page)     test_bit(PG_reserved, &(page)->flags)
959 +#ifdef CONFIG_MCL_COREDUMP
960 +#define PageFree(page)          (test_bit(PG_free, &(page)->flags))
961 +#define PageAnon(page)          (test_bit(PG_anon, &(page)->flags))
962 +#define PageShm(page)           (test_bit(PG_shm, &(page)->flags))
963 +#endif
964  
965  #define PageActiveAnon(page)           test_bit(PG_active_anon, &(page)->flags)
966  #define SetPageActiveAnon(page)        set_bit(PG_active_anon, &(page)->flags)
967 Index: linux/include/linux/reboot.h
968 ===================================================================
969 RCS file: /chaos/cvs/kernel-rh/linux/include/linux/reboot.h,v
970 retrieving revision 1.1.1.1
971 retrieving revision 1.1.1.1.10.2
972 diff -u -r1.1.1.1 -r1.1.1.1.10.2
973 --- linux/include/linux/reboot.h        7 May 2002 21:53:47 -0000       1.1.1.1
974 +++ linux/include/linux/reboot.h        1 Apr 2003 17:55:35 -0000       1.1.1.1.10.2
975 @@ -20,6 +20,7 @@
976   * CAD_OFF     Ctrl-Alt-Del sequence sends SIGINT to init task.
977   * POWER_OFF   Stop OS and remove all power from system, if possible.
978   * RESTART2    Restart system using given command string.
979 + * COREDUMP    We're taking a core dump, secondary cpus already stopped.
980   */
981  
982  #define        LINUX_REBOOT_CMD_RESTART        0x01234567
983 @@ -28,7 +29,9 @@
984  #define        LINUX_REBOOT_CMD_CAD_OFF        0x00000000
985  #define        LINUX_REBOOT_CMD_POWER_OFF      0x4321FEDC
986  #define        LINUX_REBOOT_CMD_RESTART2       0xA1B2C3D4
987 -
988 +#ifdef CONFIG_MCL_COREDUMP
989 +#define LINUX_REBOOT_CMD_COREDUMP      0x9A8BCCDD
990 +#endif
991  
992  #ifdef __KERNEL__
993  
994 Index: linux/include/linux/sysctl.h
995 ===================================================================
996 RCS file: /chaos/cvs/kernel-rh/linux/include/linux/sysctl.h,v
997 retrieving revision 1.3.2.1
998 retrieving revision 1.3.2.1.2.1
999 diff -u -r1.3.2.1 -r1.3.2.1.2.1
1000 --- linux/include/linux/sysctl.h        12 Mar 2003 19:51:30 -0000      1.3.2.1
1001 +++ linux/include/linux/sysctl.h        1 Apr 2003 12:17:41 -0000       1.3.2.1.2.1
1002 @@ -126,6 +126,7 @@
1003         KERN_CADPID=54,         /* int: PID of the process to notify on CAD */
1004         KERN_CORE_PATTERN=56,   /* string: pattern for core-files */
1005         KERN_PID_MAX=55,        /* int: max PID value of processes */
1006 +       KERN_PANIC_ON_OOPS      /* int: panic on oops enabled */
1007  };
1008  
1009  
1010 Index: linux/init/main.c
1011 ===================================================================
1012 RCS file: /chaos/cvs/kernel-rh/linux/init/main.c,v
1013 retrieving revision 1.2.2.1
1014 retrieving revision 1.2.2.1.2.1
1015 diff -u -r1.2.2.1 -r1.2.2.1.2.1
1016 --- linux/init/main.c   12 Mar 2003 19:51:35 -0000      1.2.2.1
1017 +++ linux/init/main.c   1 Apr 2003 12:17:41 -0000       1.2.2.1.2.1
1018 @@ -70,6 +70,10 @@
1019  #include <asm/smp.h>
1020  #endif
1021  
1022 +#ifdef CONFIG_BOOTIMG
1023 +#include <linux/bootimg.h>
1024 +#endif
1025 +
1026  /*
1027   * Versions of gcc older than that listed below may actually compile
1028   * and link okay, but the end product can have subtle run time bugs.
1029 @@ -352,10 +356,14 @@
1030  {
1031         char * command_line;
1032         extern char saved_command_line[];
1033 +#if defined(CONFIG_BOOTIMG) && defined(CONFIG_X86_LOCAL_APIC)
1034 +       unsigned long value;
1035 +#endif
1036  /*
1037   * Interrupts are still disabled. Do necessary setups, then
1038   * enable them
1039   */
1040 +       printk("start_kernel\n");
1041         lock_kernel();
1042         printk(linux_banner);
1043         setup_arch(&command_line);
1044 @@ -373,12 +381,26 @@
1045          * this. But we do want output early, in case something goes wrong.
1046          */
1047         console_init();
1048 +
1049 +#ifdef CONFIG_BOOTIMG
1050 +       unity_page = alloc_bootmem_pages(PAGE_SIZE);
1051 +       printk("unity_page addr: %p\n",unity_page);
1052 +#endif
1053  #ifdef CONFIG_MODULES
1054         init_modules();
1055  #endif
1056         profile_init();
1057         kmem_cache_init();
1058         sti();
1059 +#if defined(CONFIG_BOOTIMG) && defined(CONFIG_X86_LOCAL_APIC)
1060 +       /* If we don't make sure the APIC is enabled, AND the LVT0
1061 +        * register is programmed properly, we won't get timer interrupts
1062 +        */
1063 +       setup_local_APIC();
1064 +       
1065 +       value = apic_read(APIC_LVT0);
1066 +       apic_write_around(APIC_LVT0, value & ~APIC_LVT_MASKED);
1067 +#endif
1068         calibrate_delay();
1069  #ifdef CONFIG_BLK_DEV_INITRD
1070         if (initrd_start && !initrd_below_start_ok &&
1071 Index: linux/kernel/Makefile
1072 ===================================================================
1073 RCS file: /chaos/cvs/kernel-rh/linux/kernel/Makefile,v
1074 retrieving revision 1.1.1.1.4.1
1075 retrieving revision 1.1.1.1.4.1.2.1
1076 diff -u -r1.1.1.1.4.1 -r1.1.1.1.4.1.2.1
1077 --- linux/kernel/Makefile       12 Mar 2003 19:51:36 -0000      1.1.1.1.4.1
1078 +++ linux/kernel/Makefile       1 Apr 2003 12:17:41 -0000       1.1.1.1.4.1.2.1
1079 @@ -22,7 +22,8 @@
1080  obj-$(CONFIG_PM) += pm.o
1081  obj-$(CONFIG_KALLSYMS) += kallsyms.o
1082  obj-$(CONFIG_CPU_FREQ) += cpufreq.o
1083 -
1084 +obj-$(CONFIG_BOOTIMG) += bootimg.o bootimg_pic.o
1085 +obj-$(CONFIG_MCL_COREDUMP) += crash.o
1086  
1087  ifneq ($(CONFIG_IA64),y)
1088  # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
1089 Index: linux/kernel/bootimg.c
1090 ===================================================================
1091 RCS file: linux/kernel/bootimg.c
1092 diff -N linux/kernel/bootimg.c
1093 --- /dev/null   1 Jan 1970 00:00:00 -0000
1094 +++ linux/kernel/bootimg.c      1 Apr 2003 12:17:41 -0000       1.1.6.1
1095 @@ -0,0 +1,301 @@
1096 +/* bootimg.c - Boot another (kernel) image */
1097 +
1098 +/* Written 2000 by Werner Almesberger */
1099 +
1100 +
1101 +#include <linux/config.h>
1102 +#include <linux/kernel.h>
1103 +#include <linux/errno.h>
1104 +#include <linux/mm.h>
1105 +#include <linux/capability.h>
1106 +#include <linux/bootimg.h>
1107 +#include <asm/bootimg.h>
1108 +#include <asm/uaccess.h>
1109 +#include <asm/io.h>
1110 +#include <asm/pgtable.h>
1111 +#include <linux/delay.h>
1112 +
1113 +#if 0
1114 +#define DPRINTK_CONT(format,args...) printk(format,##args)
1115 +#else
1116 +#define DPRINTK_CONT(format,args...)
1117 +#endif
1118 +#define DPRINTK(format,args...) DPRINTK_CONT(KERN_DEBUG format,##args)
1119 +
1120 +unsigned long **bootimg_page_dir;
1121 +
1122 +struct bootimg_dsc bootimg_dsc; /* communication with PIC */
1123 +unsigned long *unity_page; /* unity-mapped page for i386 */
1124 +
1125 +static unsigned long bootimg_checksum(unsigned long **page_dir, int num_pages)
1126 +{
1127 +       unsigned long checksum, *page;
1128 +       int i, j;
1129 +
1130 +       checksum = 0;
1131 +
1132 +       for (i = 0; i < num_pages; i++) {
1133 +               page = __va((unsigned long *)
1134 +                           page_dir[FROM_TABLE(i)][PAGE_NR(i)]);
1135 +
1136 +               for (j = 0; j < PAGES_PER_TABLE; j++)
1137 +                       checksum ^= page[j];
1138 +
1139 +               checksum ^= page_dir[TO_TABLE(i)][PAGE_NR(i)];
1140 +       }
1141 +
1142 +        return checksum;
1143 +}
1144 +
1145 +#ifdef CONFIG_X86_PAE
1146 +
1147 +static unsigned long get_identity_mapped_page(void)
1148 +{
1149 +       pgd_t *pgd;
1150 +       pmd_t *pmd;
1151 +       unsigned long phys_addr, page_base;
1152 +
1153 +       /* Set up a 2 Mb identity-mapped page. */
1154 +
1155 +       phys_addr = virt_to_phys(unity_page);
1156 +       pgd = pgd_offset(current->active_mm, phys_addr);
1157 +       pmd = pmd_offset(pgd, phys_addr);
1158 +
1159 +       /* We hardcode this rather than using PMD_MASK just in case the PAE
1160 +        * mode setup ever changes so that 2 Mb pages are no longer used.
1161 +        */
1162 +       page_base = phys_addr & ~((1 << 21) - 1);
1163 +
1164 +       set_pmd(pmd, __pmd(page_base | _PAGE_PSE | _KERNPG_TABLE));
1165 +       __flush_tlb_one(phys_addr);
1166 +
1167 +       return (unsigned long) unity_page;
1168 +}
1169 +
1170 +#else
1171 +
1172 +static unsigned long get_identity_mapped_page(void)
1173 +{
1174 +       set_pgd(pgd_offset(current->active_mm,virt_to_phys(unity_page)),
1175 +               __pgd((_KERNPG_TABLE + _PAGE_PSE + (virt_to_phys(unity_page)&PGDIR_MASK))));
1176 +       __flush_tlb_one(virt_to_phys(unity_page));
1177 +       return (unsigned long)unity_page;
1178 +}
1179 +
1180 +#endif
1181 +
1182 +#if 0 /* Perhaps we'll need this in the future? */
1183 +static void unmap_identity_mapped_page(void)
1184 +{
1185 +       set_pgd(pgd_offset(current->active_mm,virt_to_phys(unity_page)),__pgd(0));
1186 +       __flush_tlb();
1187 +}
1188 +#endif
1189 +
1190 +static int fill_page_dir(unsigned long **page_dir,struct boot_image *image)
1191 +{
1192 +       int i, count=0;
1193 +
1194 +       memset(page_dir,0,PAGE_SIZE);
1195 +       for (i = 0; i < image->pages; i += PAGES_PER_TABLE) {
1196 +               unsigned long **table;
1197 +               int bytes_left;
1198 +
1199 +               table = page_dir+FROM_TABLE(i);
1200 +               *table = (unsigned long *) get_free_page(GFP_KERNEL);
1201 +               if (!*table) return -ENOMEM;
1202 +
1203 +               memset(*table,0,PAGE_SIZE);
1204 +               DPRINTK("page %d: from table %p @ %p\n",i,*table,table);
1205 +               table = page_dir+TO_TABLE(i);
1206 +               *table = (unsigned long *) get_free_page(GFP_KERNEL);
1207 +               if (!*table) return -ENOMEM;
1208 +
1209 +               bytes_left = (image->pages-i)*sizeof(unsigned long);
1210 +               if (copy_from_user(*table,image->load_map+i,
1211 +                   bytes_left > PAGE_SIZE ? PAGE_SIZE : bytes_left))
1212 +                       return -EFAULT;
1213 +               DPRINTK("page %d: to table %p @ %p\n",i,*table,table);
1214 +               count+=2; /* 2 pages per loop */
1215 +       }
1216 +
1217 +       for (i = 0; i < image->pages; i++) {
1218 +               unsigned long page = get_free_page(GFP_KERNEL);
1219 +               void *src;
1220 +
1221 +               if (!page) return -ENOMEM;
1222 +               count++;
1223 +
1224 +               page_dir[FROM_TABLE(i)][PAGE_NR(i)] =
1225 +                   virt_to_phys((void *) page);
1226 +               if (get_user(src,image->image_map+i) ||
1227 +                   copy_from_user((void *) page,src,PAGE_SIZE))
1228 +                       return -EFAULT;
1229 +
1230 +               DPRINTK("page %d: %p->%p->%p @ %p\n",i,src,(void *) page,
1231 +                   (void *) page_dir[FROM_TABLE(i)][PAGE_NR(i)],
1232 +                   &page_dir[FROM_TABLE(i)][PAGE_NR(i)]);
1233 +       }
1234 +
1235 +       DPRINTK("fill_page_dir: %d pages allocated\n", count);
1236 +
1237 +       return 0;
1238 +}
1239 +
1240 +
1241 +static void free_page_dir(unsigned long **page_dir)
1242 +{
1243 +       int i,j,count=0;
1244 +
1245 +       for (i = 0; i < PAGES_PER_TABLE/2; i++)
1246 +               if (page_dir[i])
1247 +                       for (j = 0; j < PAGES_PER_TABLE; j++)
1248 +                               if (page_dir[i][j]) {
1249 +                                       free_page((unsigned long)
1250 +                                           phys_to_virt(page_dir[i][j]));
1251 +                                       count++;
1252 +                               }
1253 +       for (i = 0; i < PAGES_PER_TABLE; i++)
1254 +               if (page_dir[i]) {
1255 +                       free_page((unsigned long) *page_dir[i]);
1256 +                       count++;
1257 +               }
1258 +       DPRINTK("free_page_dir: %d pages freed\n", count);
1259 +}
1260 +
1261 +
1262 +static void convert_table_refs_to_phys(unsigned long **page_dir)
1263 +{
1264 +       int i;
1265 +
1266 +       DPRINTK("PAGES_PER_TABLE: %d\n",PAGES_PER_TABLE);
1267 +       for (i = 0; i < PAGES_PER_TABLE; i++)
1268 +               if (page_dir[i]) {
1269 +                       DPRINTK("table %i: mapped %p -> ",i,page_dir[i]);
1270 +                       page_dir[i] = (unsigned long *)
1271 +                           virt_to_phys(page_dir[i]);
1272 +                       DPRINTK_CONT("%p\n",page_dir[i]);
1273 +               }
1274 +}
1275 +
1276 +
1277 +
1278 +static int fill_bootimg_dsc(struct boot_image *image)
1279 +{
1280 +       unsigned long scratch;
1281 +       int error = -ENOMEM;
1282 +
1283 +       if(bootimg_page_dir) {
1284 +               /* free previously allocated memory */
1285 +               free_page_dir(bootimg_page_dir);
1286 +               free_page((unsigned long) bootimg_page_dir);
1287 +               DPRINTK("free_page (bootimg_page_dir)\n");
1288 +       }
1289 +
1290 +       bootimg_page_dir = (unsigned long **) get_free_page(GFP_KERNEL);
1291 +       if (!bootimg_page_dir) goto out0;
1292 +       DPRINTK("get_free_page (bootimg_page_dir)\n");
1293 +
1294 +       error = fill_page_dir(bootimg_page_dir,image);
1295 +       if (error) goto out1;
1296 +
1297 +       if(!bootimg_dsc.scratch) {
1298 +               scratch = get_free_page(GFP_KERNEL);
1299 +               DPRINTK("get_free_page (scratch)\n");
1300 +       } else
1301 +               scratch = 1; /* already allocated */
1302 +
1303 +       if (!scratch) goto out1;
1304 +       /*
1305 +        * Not all architectures need the code to be identity-mapped, but it
1306 +        * can't hurt ...
1307 +        */
1308 +       DPRINTK("bootimg_page_dir: mapped %p -> ",bootimg_page_dir);
1309 +       bootimg_dsc.page_dir = (unsigned long **) virt_to_phys(bootimg_page_dir);
1310 +       DPRINTK_CONT("%p\n",bootimg_dsc.page_dir);
1311 +       if(!bootimg_dsc.scratch)
1312 +               bootimg_dsc.scratch = virt_to_phys((void *) scratch);
1313 +       bootimg_dsc.jump_to = (void (*)(void)) image->start;
1314 +       bootimg_dsc.pages = image->pages;
1315 +       bootimg_dsc.csum = bootimg_checksum(bootimg_page_dir, image->pages);
1316 +
1317 +       return 0;
1318 +
1319 +out1:
1320 +       free_page_dir(bootimg_page_dir);
1321 +       free_page((unsigned long) bootimg_page_dir);
1322 +       DPRINTK("free_page (bootimg_page_dir)\n");
1323 +       bootimg_page_dir = 0;
1324 +out0:
1325 +       return error;
1326 +}
1327 +
1328 +extern char *panicmsg;
1329 +int boot_image()
1330 +{
1331 +       relocate_and_jump_t code;
1332 +       unsigned long code_page;
1333 +       int error = -ENOMEM;
1334 +
1335 +       if (bootimg_checksum(__va(bootimg_dsc.page_dir),bootimg_dsc.pages) 
1336 +               != bootimg_dsc.csum)
1337 +               printk("Checksum of kernel image failed.  Rebooting via BIOS\n");
1338 +
1339 +       code_page = get_identity_mapped_page();
1340 +       if (!code_page) goto out3;
1341 +       code = (relocate_and_jump_t) virt_to_phys((void *) code_page);
1342 +       memcpy(code,&__bootimg_start,&__bootimg_end-&__bootimg_start);
1343 +       flush_icache_range(&__bootimg_start, &__bootimg_end-&__bootimg_start);
1344 +
1345 +       bootimg_dsc.self = (unsigned long) code;
1346 +       printk(KERN_INFO "Running boot code at 0x%p\n",code);
1347 +       
1348 +       /*
1349 +        * The point of no return. Not even printk may work after a successful
1350 +        * return from become_only_thread.
1351 +        */
1352 +
1353 +       if (!panicmsg) {
1354 +                       error = become_only_thread();
1355 +                       if (error) goto out3;
1356 +       } else {
1357 +#ifdef CONFIG_SMP
1358 +                       disable_IO_APIC();
1359 +#endif
1360 +                       __cli();
1361 +       }
1362 +
1363 +       convert_table_refs_to_phys((unsigned long **)__va(bootimg_dsc.page_dir));
1364 +       stack_on_page(code);
1365 +
1366 +       code();
1367 +
1368 +       panic("PIC code exec failed");
1369 +out3:
1370 +       printk("boot_image() failed!\n");
1371 +       for(;;); 
1372 +}
1373 +
1374 +/* changed from asmlinkage because we're called via an IOCTL on /dev/crash now */
1375 +int sys_bootimg(struct boot_image *user_dsc)
1376 +{
1377 +       struct boot_image dsc;
1378 +
1379 +       if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_MODULE)) return -EPERM;
1380 +       if (&__bootimg_end-&__bootimg_start > PAGE_SIZE-RESERVE_MIN_RELOC_STACK)
1381 +          {
1382 +               printk(KERN_ERR "boot_image: PIC too large (%d bytes)\n",
1383 +                   &__bootimg_end-&__bootimg_start);
1384 +               return -EIO;
1385 +       }
1386 +       if ((void *) relocate_and_jump != (void *) &__bootimg_start) {
1387 +               printk(KERN_ERR "boot_image: relocate_and_jump is mis-placed"
1388 +                   "(0x%p != 0x%p)\n",relocate_and_jump,&__bootimg_start);
1389 +               return -EIO;
1390 +       }
1391 +       
1392 +       if (copy_from_user(&dsc,user_dsc,sizeof(dsc))) return -EFAULT;
1393 +       if (dsc.pages >= PAGES_PER_TABLE*PAGES_PER_TABLE/2) return -EFBIG;
1394 +       if (dsc.flags) return -EINVAL; /* for future use */
1395 +       return fill_bootimg_dsc(&dsc);
1396 +}
1397 Index: linux/kernel/bootimg_pic.c
1398 ===================================================================
1399 RCS file: linux/kernel/bootimg_pic.c
1400 diff -N linux/kernel/bootimg_pic.c
1401 --- /dev/null   1 Jan 1970 00:00:00 -0000
1402 +++ linux/kernel/bootimg_pic.c  1 Apr 2003 12:17:41 -0000       1.1.6.1
1403 @@ -0,0 +1,91 @@
1404 +/* bootimg_pic.c - Boot image, position-independent code */
1405 +
1406 +/* Written 2000 by Werner Almesberger */
1407 +
1408 +/*
1409 + * Strongly inspired by FiPaBoL designed mainly by Otfried Cheong and Roger
1410 + * Gammans, and written by the latter.
1411 + */
1412 +
1413 +/*
1414 + * This code is position-independent and must fit in a single page !
1415 + * Furthermore, everything (text+data+stack) has to go into the
1416 + * .bootimg segment.
1417 + */
1418 +
1419 +
1420 +#include <linux/config.h>
1421 +#include <linux/kernel.h>
1422 +#include <linux/errno.h>
1423 +#include <linux/mm.h>
1424 +#include <linux/bootimg.h>
1425 +#include <asm/bootimg.h>
1426 +
1427 +#include <asm/io.h>
1428 +
1429 +#define copy_and_swap(from,to) \
1430 +    ( { my_copy_page(from,to); \
1431 +    tmp = from; \
1432 +    from = to; \
1433 +    to = tmp; } )
1434 +
1435 +
1436 +static inline void my_copy_page(unsigned long from,unsigned long to)
1437 +{
1438 +       unsigned long end = from+PAGE_SIZE;
1439 +
1440 +       do *((unsigned long *) to)++ = *((unsigned long *) from)++;
1441 +       while (from != end);
1442 +}
1443 +
1444 +
1445 +void __bootimg relocate_and_jump(void)
1446 +{
1447 +       struct bootimg_dsc dsc = bootimg_dsc;
1448 +       int i;
1449 +
1450 +       stop_paging();
1451 +       for (i = 0; i < dsc.pages; i++) {
1452 +               unsigned long from,to,tmp;
1453 +
1454 +               from = dsc.page_dir[FROM_TABLE(i)][PAGE_NR(i)];
1455 +               to = dsc.page_dir[TO_TABLE(i)][PAGE_NR(i)];
1456 +               if (from == to) continue;
1457 +               if (to == dsc.self) {
1458 +                       copy_and_swap(dsc.self,dsc.scratch);
1459 +                       /* WARNING: flush_icache_range MUST BE INLINED !!! */
1460 +                       flush_icache_range(dsc.self,dsc.self+PAGE_SIZE-1);
1461 +                       jump_relocated(dsc.scratch,dsc.self);
1462 +               }
1463 +               else if (to == (unsigned long) dsc.page_dir)
1464 +                       copy_and_swap((unsigned long) dsc.page_dir,dsc.scratch);
1465 +               else {
1466 +                       /*
1467 +                        * O((n^2-n)/2), sigh ...
1468 +                        */
1469 +                       unsigned long **table;
1470 +                       int j;
1471 +
1472 +                       for (j = i+1; j < dsc.pages; j++) {
1473 +                               table = dsc.page_dir+FROM_TABLE(j);
1474 +                               if (((unsigned long) *table) == to) {
1475 +                                       copy_and_swap(*table,dsc.scratch);
1476 +                                       break;
1477 +                               }
1478 +                               if ((*table)[PAGE_NR(j)] == to) {
1479 +                                       copy_and_swap((*table)[PAGE_NR(j)],
1480 +                                           dsc.scratch);
1481 +                                       break;
1482 +                               }
1483 +                               table = dsc.page_dir+TO_TABLE(j);
1484 +                               if (((unsigned long) *table) == to) {
1485 +                                       copy_and_swap(*table,dsc.scratch);
1486 +                                       break;
1487 +                               }
1488 +                       }
1489 +               }
1490 +               my_copy_page(from,to);
1491 +               dsc.scratch = from;
1492 +       }
1493 +       jump_to_kernel(dsc.jump_to);
1494 +}
1495 Index: linux/kernel/crash.c
1496 ===================================================================
1497 RCS file: linux/kernel/crash.c
1498 diff -N linux/kernel/crash.c
1499 --- /dev/null   1 Jan 1970 00:00:00 -0000
1500 +++ linux/kernel/crash.c        1 Apr 2003 12:17:41 -0000       1.1.6.1
1501 @@ -0,0 +1,886 @@
1502 +#include <linux/locks.h>
1503 +#include <linux/slab.h>
1504 +#include <linux/crash.h>
1505 +#include <linux/vmalloc.h>
1506 +#include <linux/mm.h>
1507 +#include <linux/fs.h>
1508 +#include <linux/ext2_fs.h>
1509 +#include <asm/param.h>
1510 +#include <asm/uaccess.h>
1511 +#include <linux/zlib.h>
1512 +#include <linux/reboot.h>
1513 +#include <linux/delay.h>
1514 +#include <asm/io.h>
1515 +#include <linux/miscdevice.h>
1516 +#include <linux/bootmem.h>
1517 +
1518 +#ifdef CONFIG_BOOTIMG
1519 +#include <linux/bootimg.h>
1520 +#endif
1521 +
1522 +static void crash_print_data_around(u_long p);
1523 +static void crash_free_page(u_long addr);
1524 +static int crash_chksum_page(u_long pg_addr, u_long * sum_addr);
1525 +static void *czalloc(void *arg, unsigned int items, unsigned int size);
1526 +static void czfree(void *arg, void *ptr);
1527 +static u_long crash_alloc_dest_page(void);
1528 +static void crash_free_dest_page(u_long dest);
1529 +static void init_dest_page_alloc(void);
1530 +static int crash_audit_maps(void);
1531 +static u_long crash_get_source_page(void);
1532 +static u_long crash_update_map(u_long map, u_long src_base, u_long dest, u_long * pages);
1533 +static int crash_reset_stream(z_stream * stream);
1534 +static boolean_t crash_is_kseg(u_long addr);
1535 +static u_long *crash_link(u_long p);
1536 +static int crash_chksum(u_long limit, u_long * sum_addr);
1537 +static int crash_audit_map_page(u_long map);
1538 +static void crash_wait_cpus(void);
1539 +static int crash_is_dir_page(struct page *page);
1540 +
1541 +/* for the /dev/crash interface */
1542 +int crash_init_chrdev(void);
1543 +static int crashdev_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
1544 +
1545 +#define CRASH_DEBUG 1
1546 +
1547 +#ifdef CONFIG_BOOTIMG
1548 +extern int sys_bootimg(struct boot_image *);
1549 +#endif
1550 +
1551 +static u_long crash_compr_buf;
1552 +static u_long crash_uncompr_buf;
1553 +static u_long crash_dump_header = 0;
1554 +static u_long crash_dest_free_list = 0;
1555 +static u_long crash_debug = 0;
1556 +
1557 +static u_long crash_cur_pfn;
1558 +
1559 +static u_long src_pages_skipped = 0;
1560 +static u_long src_pages_saved = 0;
1561 +static u_long dest_pages_free = 0;
1562 +
1563 +/* this information is saved from within panic() */
1564 +char *panicmsg = (char *)0;
1565 +int panic_processor = 0;
1566 +int crash_perform_sync = 0;
1567 +
1568 +u_int console_crash = 0;       /* should be moved to alpha branch */
1569 +
1570 +// typedef struct task_struct *task_t;
1571 +
1572 +/*
1573 + *  Threads active at time of panic:
1574 + */
1575 +volatile task_t *panic_threads[NR_CPUS];
1576 +volatile unsigned long panic_ksp[NR_CPUS];
1577 +unsigned long *panic_regs = NULL;
1578 +
1579 +int panic_on_oops;             /* for /proc/sys/kernel/panic_on_oops */
1580 +
1581 +extern unsigned long max_low_pfn;
1582 +
1583 +u_long crash_zalloc_start; // , crash_zalloc_end, crash_zalloc_cur;
1584 +
1585 +/* 
1586 + * Crash Kernel API functions below
1587 + * crash_pages_needed, computes pages needed for header and compression temp
1588 + * crash_init, partitions out the allocated pages, sets defaults and 
1589 + *             initializes the character device.
1590 + * crash_mark_dump_reserved, marks pages reserved from a previous dump.
1591 + * save_core, called at panic time to save a dump to memory.
1592 + */
1593 +u_long crash_pages_needed(void)
1594 +{
1595 +       /* one for the header */
1596 +       return (1 + CRASH_ZALLOC_PAGES + CRASH_UNCOMPR_BUF_PAGES + CRASH_COMPR_BUF_PAGES);
1597 +}
1598 +
1599 +void crash_init(u_long bootmap_va, u_long crash_va, u_long end_alloc_va)
1600 +{
1601 +       struct mem_crash_map_hdr *header;
1602 +       int i;
1603 +
1604 +       /* the default behavior is not NOT panic on a kernel OOPS */
1605 +       panic_on_oops = 0;
1606 +
1607 +       printk("crash_init (crash_va: %08lx)\n", crash_va);
1608 +       for (i = 0; i < NR_CPUS; i++)
1609 +               panic_threads[i] = 0;
1610 +       crash_dump_header = crash_va;
1611 +       crash_va += PAGE_SIZE;
1612 +       crash_zalloc_start = crash_va;
1613 +       crash_va += CRASH_ZALLOC_PAGES * PAGE_SIZE;
1614 +       crash_uncompr_buf = crash_va;
1615 +       crash_va += CRASH_UNCOMPR_BUF_PAGES * PAGE_SIZE;
1616 +       crash_compr_buf = crash_va;
1617 +       crash_va += CRASH_COMPR_BUF_PAGES * PAGE_SIZE;
1618 +#if 0
1619 +       if (crash_va != end_alloc_va)
1620 +               panic("crash_init inconsistency-1\n");
1621 +#endif
1622 +
1623 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
1624 +#ifdef CRASH_DEBUG
1625 +       printk("crash_dump_header %p {\n", header);
1626 +       printk("    magic[0]            = %lx\n", header->magic[0]);
1627 +       printk("    map                 = %lx\n", header->map);
1628 +       printk("    map_pages           = %lx\n", header->map_pages);
1629 +       printk("    data_pages          = %lx\n", header->data_pages);
1630 +       printk("    compr_units         = %lx\n", header->compr_units);
1631 +       printk("    boot_reserved_start = %lx\n", header->boot_reserved_start);
1632 +       printk("    boot_reserved_end   = %lx\n", header->boot_reserved_end);
1633 +#endif
1634 +
1635 +       if (header->magic[0] == CRASH_MAGIC) {
1636 +               printk("crash found\n");
1637 +               if ((header->boot_reserved_start != bootmap_va) ||
1638 +                   (header->boot_reserved_end != end_alloc_va)) {
1639 +                       /* crash audit will catch the corruption */
1640 +                       printk("crash_init inconsistency, dump may be corrupted\n");
1641 +               }
1642 +       } else {
1643 +printk("memset...");
1644 +               memset(header, 0, sizeof(*header));
1645 +printk("done\n");
1646 +       }
1647 +
1648 +       header->boot_reserved_start = bootmap_va;
1649 +       header->boot_reserved_end = end_alloc_va;
1650 +
1651 +}
1652 +
1653 +void crash_mark_dump_reserved(void)
1654 +{
1655 +       struct mem_crash_map_hdr *header;
1656 +       struct mem_crash_map_entry *m;
1657 +
1658 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
1659 +       if (header->magic[0] != CRASH_MAGIC)
1660 +               return;
1661 +       m = (struct mem_crash_map_entry *)header->map;
1662 +#ifdef CRASH_DEBUG
1663 +       printk("\n\n\ncrash_mark_dump_reserved\n\n");
1664 +       printk("crash_dump_header %p {\n", header);
1665 +       printk("    magic[0]            = %lx\n", header->magic[0]);
1666 +       printk("    map                 = %lx\n", header->map);
1667 +       printk("    map_pages           = %lx\n", header->map_pages);
1668 +       printk("    data_pages          = %lx\n", header->data_pages);
1669 +       printk("    compr_units         = %lx\n", header->compr_units);
1670 +       printk("    boot_reserved_start = %lx\n", header->boot_reserved_start);
1671 +       printk("    boot_reserved_end   = %lx\n", header->boot_reserved_end);
1672 +       printk("mem_crash_map_entry %p {\n", m);
1673 +       printk("    src_va              = %lx\n", m->src_va);
1674 +       printk("    dest_page_va        = %lx\n", m->dest_page_va);
1675 +       printk("    check_sum           = %lx\n", m->check_sum);
1676 +#endif
1677 +
1678 +       if (crash_audit_maps()) {
1679 +               header->magic[0] = 0;
1680 +               return;
1681 +       }
1682 +
1683 +       m = (struct mem_crash_map_entry *)header->map;
1684 + again:
1685 +       CRASH_MARK_BOOT_RESERVED(m);
1686 +       for (; m->src_va; m++) {
1687 +               if (m->src_va == -1) {
1688 +                       m = (struct mem_crash_map_entry *)m->dest_page_va;
1689 +                       goto again;
1690 +               }
1691 +               CRASH_MARK_BOOT_RESERVED(m->dest_page_va);
1692 +       }
1693 +       return;
1694 +}
1695 +
1696 +void save_core(void)
1697 +{
1698 +       int i, j, k;
1699 +       z_stream stream;
1700 +       int err;
1701 +       struct task_struct *tp;
1702 +       struct mem_crash_map_hdr *header;
1703 +       u_long *sub_map;
1704 +       u_long map;
1705 +       u_long src, dest, unc, cp, src_base, comp_pages;
1706 +
1707 +       k = 0;
1708 +       dest = 0;
1709 +       __cli();
1710 +       tp = current;
1711 +       mb();
1712 +       if (smp_processor_id() != 0) {  /* boot_cpu_id is always 0, i think */
1713 +               panic_threads[smp_processor_id()] = tp;
1714 +               crash_halt_or_reboot(0);
1715 +       } else {
1716 +               if (console_crash)
1717 +                       panic_threads[smp_processor_id()] = &init_task_union.task;
1718 +               else
1719 +                       panic_threads[smp_processor_id()] = tp;
1720 +
1721 +               crash_wait_cpus();
1722 +       }
1723 +
1724 +       printk("save_core: started on CPU%d\n", smp_processor_id());
1725 +       if (!crash_dump_header) {
1726 +               printk("save_core: not initialized\n");
1727 +               return;
1728 +       }
1729 +
1730 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
1731 +       header->magic[0] = 0;
1732 +       header->map_pages = 0;
1733 +       header->data_pages = 0;
1734 +       header->compr_units = 0;
1735 +       header->map = 0;
1736 +
1737 +       stream.workspace=(void*)crash_zalloc_start;
1738 +       //      stream.zalloc = czalloc;
1739 +       //      stream.zfree = czfree;
1740 +       //      stream.opaque = (voidpf) 0;
1741 +       stream.next_out = (Bytef *) crash_compr_buf;
1742 +       stream.avail_out = (uInt) (CRASH_COMPR_BUF_PAGES * PAGE_SIZE);
1743 +       stream.next_in = (Bytef *) crash_uncompr_buf;
1744 +       stream.avail_in = (uInt) (CRASH_UNCOMPR_BUF_PAGES * PAGE_SIZE);
1745 +       err = zlib_deflateInit(&stream, Z_BEST_SPEED);
1746 +       if (err != Z_OK) {
1747 +               printk("save_core: bad return %d from deflateInit\n", err);
1748 +               return;
1749 +       }
1750 +
1751 +       init_dest_page_alloc();
1752 +       header->map = map = crash_update_map(0, 0, 0, &header->map_pages);
1753 +       if (!map) {
1754 +               printk("save_core: no dest pages\n");
1755 +               return;
1756 +       }
1757 +       crash_cur_pfn = 0;
1758 +       src_base = 0;
1759 +       src = 0;
1760 +       for (;;) {
1761 +               sub_map = (u_long *) crash_uncompr_buf;
1762 +               unc = crash_uncompr_buf + CRASH_SUB_MAP_PAGES * PAGE_SIZE;
1763 +               for (i = 0; i < CRASH_SOURCE_PAGES; i++) {
1764 +                       src = crash_get_source_page();
1765 +                       if (!src)
1766 +                               break;
1767 +                       if (!i)
1768 +                               src_base = src;
1769 +                       if (!crash_is_kseg(unc) || !crash_is_kseg(src)) {
1770 +                               printk("unc = 0x%lx, src = 0x%lx, i = %d\n", unc, src, i);
1771 +                               i = src = 0;
1772 +                               break;
1773 +                       }
1774 +                       memcpy((void *)unc, (void *)src, PAGE_SIZE);
1775 +                       unc += PAGE_SIZE;
1776 +                       *sub_map++ = src;
1777 +               }
1778 +               *sub_map = 0;
1779 +               if (!i && !src)
1780 +                       break;
1781 +               err = zlib_deflate(&stream, Z_FINISH);
1782 +               if (!(err == Z_STREAM_END)) {
1783 +                       zlib_deflateEnd(&stream);
1784 +                       printk("save_core: bad return %d from deflate, src_base = 0x%lx\n", err,
1785 +                              src_base);
1786 +                       return;
1787 +               }
1788 +               comp_pages = (u_long) round_page(stream.total_out) / PAGE_SIZE;
1789 +               if (crash_debug)
1790 +                       printk("src_base = 0x%lx compressed data in 0x%lx pages\n", src_base,
1791 +                              comp_pages);
1792 +
1793 +               cp = crash_compr_buf;
1794 +               j = 0;
1795 +               if (crash_debug)
1796 +                       printk("\nsrc = %lx\n", src_base);
1797 +               else {
1798 +                       printk(".");
1799 +                       if (!(k++ % 64))
1800 +                               printk("\n");
1801 +               }
1802 +               for (i = 0; i < comp_pages; i++) {
1803 +                       dest = crash_alloc_dest_page();
1804 +                       if (crash_debug) {
1805 +                               printk("%lx ", dest);
1806 +                               if (!(j++ % 8))
1807 +                                       printk("\n");
1808 +                       }
1809 +                       header->data_pages++;
1810 +                       if (!dest) {
1811 +                               printk("save_core: no dest pages\n");
1812 +                               return;
1813 +                       }
1814 +                       if (!crash_is_kseg(dest) || !crash_is_kseg(cp)) {
1815 +                               printk("dest = 0x%lx, cp = 0x%lx, i = %d, comp_pages = 0x%lx\n",
1816 +                                      dest, cp, i, comp_pages);
1817 +                               src = 0;
1818 +                               break;
1819 +                       }
1820 +                       memcpy((void *)dest, (void *)cp, PAGE_SIZE);
1821 +                       cp += PAGE_SIZE;
1822 +                       map = crash_update_map(map, src_base, dest, &header->map_pages); /* links a new map page, if necessary */
1823 +                       if (!map) {
1824 +                               printk("save_core: no map\n");
1825 +                               return;
1826 +                       }
1827 +               }
1828 +               header->compr_units++;
1829 +               if (!src)
1830 +                       break;
1831 +               if (crash_reset_stream(&stream))
1832 +                       return;
1833 +       }
1834 +
1835 +       map = crash_update_map(map, 0, 0, &header->map_pages);
1836 +       header->magic[0] = CRASH_MAGIC;
1837 +
1838 +       if (crash_audit_maps()) {
1839 +               header->magic[0] = 0;
1840 +               return;
1841 +       }
1842 +
1843 +       printk("\nsave_core: src pages skipped = 0x%lx src pages saved = 0x%lx\n",
1844 +              src_pages_skipped, src_pages_saved);
1845 +       printk("save_core: data_pages = 0x%lx map_pages = 0x%lx\n", header->data_pages,
1846 +              header->map_pages);
1847 +       printk("save_core: completed, crash_dump_header = 0x%lx\n", crash_dump_header);
1848 +}
1849 +
1850 +/* helper functions private to this file */
1851 +static int crash_reset_stream(z_stream * stream)
1852 +{
1853 +       int err;
1854 +
1855 +       stream->workspace=(void*)crash_zalloc_start;
1856 +       // stream->zalloc = czalloc;
1857 +       // stream->zfree = czfree;
1858 +       // stream->opaque = (voidpf) 0;
1859 +       stream->next_out = (Bytef *) crash_compr_buf;
1860 +       stream->avail_out = (uInt) (CRASH_COMPR_BUF_PAGES * PAGE_SIZE);
1861 +       stream->next_in = (Bytef *) crash_uncompr_buf;
1862 +       stream->avail_in = (uInt) (CRASH_UNCOMPR_BUF_PAGES * PAGE_SIZE);
1863 +       err = zlib_deflateReset(stream);
1864 +       if (err != Z_OK) {
1865 +               printk("crash_reset_stream: bad return %d from deflateReset\n", err);
1866 +               return 1;
1867 +       }
1868 +       return 0;
1869 +}
1870 +
1871 +static u_long crash_alloc_dest_page(void)
1872 +{
1873 +       u_long addr;
1874 +
1875 +       addr = crash_dest_free_list;
1876 +       if (addr) {
1877 +               crash_dest_free_list = *(u_long *) addr;
1878 +               dest_pages_free--;
1879 +       } else
1880 +               printk("crash_alloc_dest_page: free list empty\n");
1881 +       return addr;
1882 +}
1883 +
1884 +static void crash_free_dest_page(u_long dest)
1885 +{
1886 +       if (!dest) {
1887 +               printk("crash_free_dest_page: freeing addr 0\n");
1888 +               return;
1889 +       }
1890 +       dest_pages_free++;
1891 +       dest = (u_long) trunc_page(dest);
1892 +       *(u_long *) dest = crash_dest_free_list;
1893 +       crash_dest_free_list = dest;
1894 +}
1895 +
1896 +/*
1897 + *  Stolen from setup.c
1898 + */
1899 +#define PFN_PHYS(x)    ((x) << PAGE_SHIFT)
1900 +
1901 +static void init_dest_page_alloc(void)
1902 +{
1903 +       u_long va;
1904 +       long i;
1905 +       struct page *page;
1906 +       struct mem_crash_map_hdr *header;
1907 +
1908 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
1909 +       for (i = ((1 << 24) >> PAGE_SHIFT) + LOWER_MEM_FORWARD;
1910 +            i < (max_low_pfn - UPPER_MEM_BACKUP); i++) {
1911 +               va = (u_long) phys_to_virt(PFN_PHYS(i));
1912 +               if ((va >= header->boot_reserved_start) && (va < header->boot_reserved_end))
1913 +                       continue;
1914 +               page = mem_map + i;
1915 +               if (PageLocked(page) || PageReserved(page))
1916 +                       continue;
1917 +               if (PageFree(page) || PageAnon(page) || PageShm(page) || page->buffers)
1918 +                       crash_free_dest_page(va);
1919 +       }
1920 +       if (crash_debug)
1921 +               printk("init_dest_page_alloc: dest_pages_free = 0x%lx\n", dest_pages_free);
1922 +}
1923 +
1924 +static int crash_is_dir_page(struct page *page) {
1925 +       struct inode *tmp_inode;
1926 +
1927 +       if(page->mapping && page->mapping->host) {
1928 +               tmp_inode = (struct inode *)page->mapping->host;
1929 +               if((tmp_inode->i_sb->s_magic == EXT2_SUPER_MAGIC) &&
1930 +                  (S_ISDIR(tmp_inode->i_mode)))
1931 +                       return 1;
1932 +       }
1933 +
1934 +       return 0;
1935 +}
1936 +
1937 +static u_long crash_get_source_page(void)
1938 +{
1939 +       struct page *page;
1940 +       u_long va;
1941 +
1942 +       while (crash_cur_pfn < max_low_pfn) {
1943 +               page = mem_map + crash_cur_pfn;
1944 +               if (!(PageFree(page) || PageAnon(page) || PageShm(page) || page->buffers))
1945 +                       break;
1946 +               src_pages_skipped++;
1947 +               crash_cur_pfn++;
1948 +       }
1949 +       if (crash_cur_pfn == max_low_pfn)
1950 +               return 0;
1951 +
1952 +       va = (u_long) phys_to_virt(PFN_PHYS(crash_cur_pfn));
1953 +       src_pages_saved++;
1954 +       crash_cur_pfn++;
1955 +       return va;
1956 +}
1957 +
1958 +static u_long crash_update_map(u_long map, u_long src_base, u_long dest, u_long * pages)
1959 +{
1960 +       struct mem_crash_map_entry *m;
1961 +
1962 +
1963 +       if (!map) {
1964 +               (*pages)++;
1965 +               return crash_alloc_dest_page();
1966 +       }
1967 +       m = (struct mem_crash_map_entry *)map;
1968 +       m->src_va = src_base;
1969 +       m->dest_page_va = dest;
1970 +       if (dest)
1971 +               if (crash_chksum_page(dest, &m->check_sum))
1972 +                       return 0;
1973 +
1974 +       map += sizeof(struct mem_crash_map_entry);
1975 +
1976 +       m = (struct mem_crash_map_entry *)map;
1977 +       if (!src_base) {        /* end of list */
1978 +               if (crash_chksum((u_long) m, &m->src_va))
1979 +                       return 0;
1980 +       } else if ((map + 3 * sizeof(struct mem_crash_map_entry)) > (u_long) round_page(map)) {
1981 +               m->src_va = -1;
1982 +               map = m->dest_page_va = crash_alloc_dest_page();
1983 +               if (crash_debug)
1984 +                       printk("\nm = 0x%lx m->src_va = 0x%lx m->dest_page_va = 0x%lx\n",
1985 +                              (u_long) trunc_page(m), m->src_va, m->dest_page_va);
1986 +               m++;
1987 +               if (crash_chksum((u_long) m, &m->src_va))
1988 +                       return 0;
1989 +               if (crash_debug)
1990 +                       printk("m = 0x%lx chksum =  m->src_va = 0x%lx\n", (u_long) trunc_page(m),
1991 +                              m->src_va);
1992 +               if (crash_audit_map_page((u_long) m))
1993 +                       return 0;
1994 +               (*pages)++;
1995 +       }
1996 +       return map;
1997 +}
1998 +
1999 +static int crash_chksum(u_long limit, u_long * sum_addr)
2000 +{
2001 +       u_long sum;
2002 +       u_long *addr;
2003 +
2004 +       if (!crash_is_kseg(limit)) {
2005 +               printk("bad addr = 0x%lx to crash_chksum\n", limit);
2006 +               return 1;
2007 +       }
2008 +       sum = 0;
2009 +       addr = (u_long *) trunc_page(limit);
2010 +       for (; (u_long) addr < limit; addr++)
2011 +               sum += *addr;
2012 +       *sum_addr = sum;
2013 +       return 0;
2014 +}
2015 +
2016 +static int crash_chksum_page(u_long pg_addr, u_long * sum_addr)
2017 +{
2018 +       u_long sum, limit;
2019 +       u_long *addr;
2020 +
2021 +       if (!crash_is_kseg(pg_addr)) {
2022 +               printk("bad addr = 0x%lx to crash_chksum_page\n", pg_addr);
2023 +               return 1;
2024 +       }
2025 +
2026 +       sum = 0;
2027 +       addr = (u_long *) trunc_page(pg_addr);
2028 +       limit = (u_long) addr + PAGE_SIZE;
2029 +       for (; (u_long) addr < limit; addr++)
2030 +               sum += *addr;
2031 +       *sum_addr = sum;
2032 +       return 0;
2033 +}
2034 +
2035 +static int crash_audit_maps(void)
2036 +{
2037 +       u_long m, count;
2038 +       u_long *link_addr;
2039 +       struct mem_crash_map_hdr *header;
2040 +
2041 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
2042 +       if (header->magic[0] != CRASH_MAGIC)
2043 +               return 1;
2044 +
2045 +       link_addr = &header->map;
2046 +       m = header->map;
2047 +
2048 +       count = 0;
2049 +       for (;;) {
2050 +               if (!crash_is_kseg(m)) {
2051 +                       printk("crash_audit_maps: bad link 0x%lx at 0x%lx\n", m,
2052 +                              (u_long) link_addr);
2053 +                       return 1;
2054 +               }
2055 +               if (crash_audit_map_page(m)) {
2056 +                       printk("audit failed while on map page %ld\n", count);
2057 +                       return 1;
2058 +               }
2059 +               if (!crash_link(m))
2060 +                       break;
2061 +               link_addr = crash_link(m);
2062 +               m = *link_addr;
2063 +
2064 +               count++;
2065 +       }
2066 +       return 0;
2067 +}
2068 +
2069 +static int crash_audit_map_page(u_long map)
2070 +{
2071 +       struct mem_crash_map_entry *m;
2072 +       u_long sum;
2073 +
2074 +       if (!map || !crash_is_kseg(map)) {
2075 +               printk("crash_audit_map_page: bad map = 0x%lx\n", map);
2076 +               return 1;
2077 +       }
2078 +       map = (u_long) trunc_page((u_long) map);
2079 +       m = (struct mem_crash_map_entry *)map;
2080 +       for (;;) {
2081 +               if ((m->src_va == -1) || (m->src_va == 0)) {
2082 +                       m++;
2083 +                       if (crash_chksum((u_long) m, &sum))
2084 +                               return 1;
2085 +                       if (m->src_va != sum) {
2086 +                               printk("crash_audit_map_page: checksum failure1\n");
2087 +                               printk("m = 0x%lx, sum = 0x%lx, m->src_va = 0x%lx\n",
2088 +                                      (u_long) m, (u_long) sum, (u_long) m->src_va);
2089 +                               crash_print_data_around((u_long) & m->src_va);
2090 +                               return 1;
2091 +                       } else {
2092 +                               return 0;
2093 +                       }
2094 +               } else {
2095 +                       if (crash_chksum_page((u_long) m->dest_page_va, &sum)
2096 +                           || (m->check_sum != sum)) {
2097 +                               printk("crash_audit_map_page: checksum failure2\n");
2098 +                               printk
2099 +                                       ("dest_page_va = 0x%lx, &dest_page_va = 0x%lx, sum = 0x%lx, m->check_sum = 0x%lx\n",
2100 +                                        (u_long) m->dest_page_va, (u_long) (&m->check_sum),
2101 +                                        (u_long) sum, (u_long) m->check_sum);
2102 +                               crash_print_data_around((u_long) & m->check_sum);
2103 +                               return 1;
2104 +                       }
2105 +               }
2106 +               m++;
2107 +       }
2108 +}
2109 +
2110 +static void crash_print_data_around(u_long p)
2111 +{
2112 +       u_long *a;
2113 +       int i;
2114 +
2115 +       if (!crash_is_kseg(p)) {
2116 +               printk("crash_print_data_around: p = 0x%lx not kseg\n", p);
2117 +               return;
2118 +       }
2119 +       a = (u_long *) p;
2120 +       a -= 20;
2121 +       for (i = 0; i < 40; i++)
2122 +               printk("%lx\n", *a++);
2123 +}
2124 +
2125 +#ifdef CRASH_DEBUG
2126 +static void crash_print_map_page(u_long map)
2127 +{
2128 +       struct mem_crash_map_entry *m;
2129 +       int j = 0;
2130 +       u_long sum;
2131 +
2132 +       map = (u_long) trunc_page((u_long) map);
2133 +       m = (struct mem_crash_map_entry *)map;
2134 +       for (;;) {
2135 +               printk("%lx %lx %lx ", m->src_va, m->dest_page_va, m->check_sum);
2136 +               if (!(j++ % 4))
2137 +                       printk("\n");
2138 +               if ((m->src_va == -1) || (m->src_va == 0)) {
2139 +                       m++;
2140 +                       printk("%lx %lx ", m->src_va, m->dest_page_va);
2141 +                       if (crash_chksum((u_long) m, &sum));
2142 +                       else
2143 +                               printk("\nchksum = 0x%lx\n", sum);
2144 +                       return;
2145 +               }
2146 +               m++;
2147 +       }
2148 +}
2149 +#endif /* CRASH_DEBUG */
2150 +
2151 +static void crash_wait_cpus(void)
2152 +{
2153 +       int i;
2154 +       int msecs = 0;
2155 +
2156 +       for (i = 0; i < smp_num_cpus; i++) {
2157 +               if (i != smp_processor_id()) {
2158 +                       while (!panic_threads[i]) {
2159 +                               msecs++;
2160 +                               mdelay(1);
2161 +                               if (msecs > CRASH_CPU_TIMEOUT) {
2162 +                                       /* if other cpus are still running
2163 +                                        * we have to halt, otherwise we could
2164 +                                        * risk using buffer cache pages which
2165 +                                        * could subsequently get flushed to disk.
2166 +                                        */
2167 +                                       printk("Unable to halt other CPUs, halting system.\n");
2168 +                                       crash_halt_or_reboot(0);
2169 +                               }
2170 +                       }
2171 +               }
2172 +       }
2173 +
2174 +       crash_cleanup_smp_state();
2175 +}
2176 +
2177 +
2178 +#if 0
2179 +static void *czalloc(void *arg, unsigned int items, unsigned int size)
2180 +{
2181 +       u_long nbytes;
2182 +       u_long addr;
2183 +
2184 +       nbytes = (u_long) (items * size);
2185 +       nbytes = (u_long) round_page(nbytes);
2186 +       if ((crash_zalloc_cur + nbytes) > crash_zalloc_end)
2187 +               return 0;
2188 +       addr = crash_zalloc_cur;
2189 +       crash_zalloc_cur += nbytes;
2190 +       return ((void *)addr);
2191 +}
2192 +
2193 +static void czfree(void *arg, void *ptr)
2194 +{
2195 +       printk("zfree: ptr = 0x%lx\n", (u_long) ptr);
2196 +}
2197 +#endif
2198 +
2199 +static boolean_t crash_is_kseg(u_long addr)
2200 +{
2201 +       u_long phys;
2202 +
2203 +       phys = virt_to_phys((void *)addr);
2204 +       if (phys < PFN_PHYS(max_low_pfn))
2205 +               return TRUE;
2206 +       else
2207 +               return FALSE;
2208 +}
2209 +
2210 +static u_long *crash_link(u_long p)
2211 +{
2212 +       struct mem_crash_map_entry *m;
2213 +
2214 +       p = (u_long) trunc_page(p);
2215 +       m = (struct mem_crash_map_entry *)p;
2216 +       for (; m->src_va; m++)
2217 +               if (m->src_va == -1)
2218 +                       return &m->dest_page_va;
2219 +
2220 +       return 0;
2221 +}
2222 +
2223 +/* Call this after data written to disk. */
2224 +static int crash_free_crashmem(void)
2225 +{
2226 +       struct mem_crash_map_hdr *header;
2227 +       struct mem_crash_map_entry *m, *last_m;
2228 +
2229 +       if (crash_debug)
2230 +               printk("crash_free_crashmem: \n");
2231 +
2232 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
2233 +       if (crash_audit_maps()) {
2234 +               header->magic[0] = 0;
2235 +               return 1;
2236 +       }
2237 +       m = (struct mem_crash_map_entry *)header->map;
2238 + again:
2239 +       for (; m->src_va; m++) {
2240 +               if (m->src_va == -1) {
2241 +                       last_m = m;
2242 +                       m = (struct mem_crash_map_entry *)m->dest_page_va;
2243 +                       crash_free_page((unsigned long)last_m);
2244 +                       goto again;
2245 +               }
2246 +               crash_free_page(m->dest_page_va);
2247 +       }
2248 +       if (crash_debug)
2249 +               printk("crash_free_crashmem: 0x%lx freed\n",
2250 +                      (header->data_pages + header->map_pages) * PAGE_SIZE);
2251 +       header->magic[0] = 0;
2252 +       return 0;
2253 +}
2254 +
2255 +static void crash_free_page(u_long addr)
2256 +{
2257 +       struct page *page;
2258 +
2259 +       page = virt_to_page(addr);
2260 +       ClearPageReserved(page);
2261 +       set_page_count(page, 1);
2262 +       __free_page(page);
2263 +}
2264 +
2265 +static int get_dump_helper(u_long kva, u_long buf)
2266 +{
2267 +       struct page *page;
2268 +       struct mem_crash_map_hdr *header;
2269 +
2270 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
2271 +       if (header->magic[0] != CRASH_MAGIC)
2272 +               return 1;
2273 +
2274 +       if (!kva) {
2275 +               if (crash_audit_maps()) {
2276 +                       printk("get_dump_helper: audit failure\n");
2277 +                       header->magic[0] = 0;
2278 +                       return 1;
2279 +               }
2280 +               page = virt_to_page((u_long) crash_dump_header);
2281 +               if (!PageReserved(page)) {
2282 +                       printk("not reserved: crash_dump_header = 0x%lx\n", crash_dump_header);
2283 +                       return 1;
2284 +               }
2285 +               if (copy_to_user((char *)buf, (char *)crash_dump_header,
2286 +                                sizeof(struct mem_crash_map_hdr))) {
2287 +                       printk("get_dump_helper: copy_to_user failed1\n");
2288 +                       return 1;
2289 +               }
2290 +       } else {
2291 +               page = virt_to_page(kva);
2292 +               if (!PageReserved(page)) {
2293 +                       printk("not reserved: kva = 0x%lx\n", kva);
2294 +                       return 1;
2295 +               }
2296 +               if (copy_to_user((char *)buf, (char *)trunc_page(kva), PAGE_SIZE)) {
2297 +                       printk("get_dump_helper: copy_to_user failed2\n");
2298 +                       return 1;
2299 +               }
2300 +       }
2301 +       return 0;
2302 +}
2303 +
2304 +static void free_dump_helper(void)
2305 +{
2306 +       struct mem_crash_map_hdr *header;
2307 +
2308 +       header = (struct mem_crash_map_hdr *)crash_dump_header;
2309 +       if (header->magic[0] != CRASH_MAGIC)
2310 +               return;
2311 +       if (crash_debug)
2312 +               printk("free_dump_helper\n");
2313 +       crash_free_crashmem();
2314 +}
2315 +
2316 +static int crashdev_open(struct inode *inode, struct file *file)
2317 +{
2318 +       /* always return success -- nothing to do here */
2319 +       return 0;
2320 +}
2321 +
2322 +/* character device implementation */
2323 +static struct file_operations crashdev_fops = {
2324 +       ioctl:crashdev_ioctl,
2325 +       open:crashdev_open,
2326 +};
2327 +
2328 +static struct miscdevice crash_miscdev = {
2329 +       190, "crash", &crashdev_fops
2330 +};
2331 +
2332 +int crash_init_chrdev(void)
2333 +{
2334 +       int result;
2335 +
2336 +       result = misc_register(&crash_miscdev);
2337 +
2338 +       if (result < 0)
2339 +               printk(KERN_WARNING "crash: can't register crash device (c 10 190)\n");
2340 +
2341 +       return result;
2342 +}
2343 +
2344 +/* call the original syscalls, just to get things going */
2345 +static int crashdev_ioctl(struct inode *inode, struct file *file,
2346 +                         unsigned int cmd, unsigned long arg)
2347 +{
2348 +       int retval = 0;
2349 +
2350 +       switch (cmd) {
2351 +       case CRASH_IOCFREEDUMP:
2352 +               free_dump_helper();
2353 +               break;
2354 +
2355 +       case CRASH_IOCGETDUMP:
2356 +               if (crash_debug) {
2357 +                       printk("crashdev_ioctl: get dump\n");
2358 +                       printk("vals: %08lx %08lx\n",
2359 +                              ((struct ioctl_getdump *)arg)->kva,
2360 +                              ((struct ioctl_getdump *)arg)->buf);
2361 +               }
2362 +
2363 +               retval = get_dump_helper((u_long) ((struct ioctl_getdump *)arg)->kva,
2364 +                                        (u_long) ((struct ioctl_getdump *)arg)->buf);
2365 +               break;
2366 +
2367 +#ifdef CONFIG_BOOTIMG
2368 +       case CRASH_IOCBOOTIMG:
2369 +               if (crash_debug)
2370 +                       printk("crashdev_ioctl: bootimg\n");
2371 +
2372 +               retval = sys_bootimg((struct boot_image *)arg);
2373 +               break;
2374 +#endif
2375 +
2376 +       case CRASH_IOCVERSION:
2377 +               if (crash_debug)
2378 +                       printk("crashdev_ioctl: version\n");
2379 +               retval = CRASH_K_MINOR | (CRASH_K_MAJOR << 16);
2380 +               break;
2381 +
2382 +       default:
2383 +               return -EINVAL;
2384 +       }
2385 +
2386 +       return retval;
2387 +}
2388 Index: linux/kernel/module.c
2389 ===================================================================
2390 RCS file: /chaos/cvs/kernel-rh/linux/kernel/module.c,v
2391 retrieving revision 1.1.1.1.4.1
2392 retrieving revision 1.1.1.1.4.1.2.1
2393 diff -u -r1.1.1.1.4.1 -r1.1.1.1.4.1.2.1
2394 --- linux/kernel/module.c       12 Mar 2003 19:51:36 -0000      1.1.1.1.4.1
2395 +++ linux/kernel/module.c       1 Apr 2003 12:17:41 -0000       1.1.1.1.4.1.2.1
2396 @@ -311,7 +311,14 @@
2397                 error = -EEXIST;
2398                 goto err1;
2399         }
2400 +#if defined(CONFIG_MCL_COREDUMP)
2401 +       /* Call vmalloc_32 instead of module_map (vmalloc for i386)
2402 +        * to avoid being mapped in highmem where mcore can't see us.
2403 +        */
2404 +       if ((mod = (struct module *)vmalloc_32(size)) == NULL) {
2405 +#else
2406         if ((mod = (struct module *)module_map(size)) == NULL) {
2407 +#endif
2408                 error = -ENOMEM;
2409                 goto err1;
2410         }
2411 Index: linux/kernel/panic.c
2412 ===================================================================
2413 RCS file: /chaos/cvs/kernel-rh/linux/kernel/panic.c,v
2414 retrieving revision 1.3.2.1
2415 retrieving revision 1.3.2.1.2.1
2416 diff -u -r1.3.2.1 -r1.3.2.1.2.1
2417 --- linux/kernel/panic.c        12 Mar 2003 19:51:36 -0000      1.3.2.1
2418 +++ linux/kernel/panic.c        1 Apr 2003 12:17:41 -0000       1.3.2.1.2.1
2419 @@ -19,6 +19,10 @@
2420  #include <linux/vt_kern.h>
2421  #include <linux/pc_keyb.h>
2422  
2423 +#ifdef CONFIG_MCL_COREDUMP
2424 +#include <linux/crash.h>
2425 +#endif
2426 +
2427  asmlinkage void sys_sync(void);        /* it's really int */
2428  
2429  int panic_timeout;
2430 @@ -197,20 +201,43 @@
2431          unsigned long caller = (unsigned long) __builtin_return_address(0);
2432  #endif
2433  
2434 +#ifdef CONFIG_MCL_COREDUMP
2435 +       crash_save_regs();
2436 +#endif
2437 +
2438         bust_spinlocks(1);
2439         va_start(args, fmt);
2440         vsprintf(buf, fmt, args);
2441         va_end(args);
2442         printk(KERN_EMERG "Kernel panic: %s\n",buf);
2443 +
2444 +#ifdef CONFIG_MCL_COREDUMP
2445 +       if (!panicmsg) {
2446 +               panicmsg = buf;
2447 +               panic_processor = smp_processor_id();
2448 +               mb();
2449 +       }
2450 +#endif
2451 +
2452         if (netdump_func)
2453                 BUG();
2454         if (in_interrupt())
2455                 printk(KERN_EMERG "In interrupt handler - not syncing\n");
2456         else if (!current->pid)
2457                 printk(KERN_EMERG "In idle task - not syncing\n");
2458 +#ifdef CONFIG_MCL_COREDUMP
2459 +       else if (crash_perform_sync)
2460 +#else
2461         else
2462 +#endif
2463                 sys_sync();
2464 +
2465         bust_spinlocks(0);
2466 +
2467 +#ifdef CONFIG_MCL_COREDUMP
2468 +       smp_call_function((void *)smp_crash_funnel_cpu,0,0,0);
2469 +       crash_save_current_state(current);
2470 +#endif
2471  
2472  #ifdef CONFIG_SMP
2473         smp_send_stop();
2474 Index: linux/kernel/sysctl.c
2475 ===================================================================
2476 RCS file: /chaos/cvs/kernel-rh/linux/kernel/sysctl.c,v
2477 retrieving revision 1.2.2.1
2478 retrieving revision 1.2.2.1.2.1
2479 diff -u -r1.2.2.1 -r1.2.2.1.2.1
2480 --- linux/kernel/sysctl.c       12 Mar 2003 19:51:36 -0000      1.2.2.1
2481 +++ linux/kernel/sysctl.c       1 Apr 2003 12:17:41 -0000       1.2.2.1.2.1
2482 @@ -37,6 +37,10 @@
2483  #include <linux/nfs_fs.h>
2484  #endif
2485  
2486 +#ifdef CONFIG_MCL_COREDUMP
2487 +#include <linux/crash.h>
2488 +#endif
2489 +
2490  #if defined(CONFIG_SYSCTL)
2491  
2492  /* External variables not in a header file. */
2493 @@ -247,6 +251,10 @@
2494         {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
2495          0644, NULL, &proc_dointvec},
2496  #endif  
2497 +#ifdef CONFIG_MCL_COREDUMP
2498 +       {KERN_PANIC_ON_OOPS, "panic_on_oops", &panic_on_oops, sizeof(int),
2499 +        0644, NULL, &proc_dointvec},
2500 +#endif
2501         {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int),
2502          0600, NULL, &proc_dointvec},
2503         {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
2504 Index: linux/lib/Config.in
2505 ===================================================================
2506 RCS file: /chaos/cvs/kernel-rh/linux/lib/Config.in,v
2507 retrieving revision 1.2
2508 retrieving revision 1.2.4.1
2509 diff -u -r1.2 -r1.2.4.1
2510 --- linux/lib/Config.in 14 Feb 2003 22:59:23 -0000      1.2
2511 +++ linux/lib/Config.in 1 Apr 2003 12:17:41 -0000       1.2.4.1
2512 @@ -23,12 +23,14 @@
2513    fi
2514  fi
2515  
2516 -if [ "$CONFIG_PPP_DEFLATE" = "y" -o \
2517 +if [ "$CONFIG_MCL_COREDUMP" = "y" -o \
2518 +     "$CONFIG_PPP_DEFLATE" = "y" -o \
2519       "$CONFIG_JFFS2_FS" = "y" ]; then
2520     define_tristate CONFIG_ZLIB_DEFLATE y
2521  else
2522    if [ "$CONFIG_PPP_DEFLATE" = "m" -o \
2523 -       "$CONFIG_JFFS2_FS" = "m" ]; then
2524 +       "$CONFIG_JFFS2_FS" = "m" -o \
2525 +       "$CONFIG_MCL_COREDUMP" = "m" ]; then
2526       define_tristate CONFIG_ZLIB_DEFLATE m
2527    else
2528       tristate 'zlib compression support' CONFIG_ZLIB_DEFLATE
2529 Index: linux/mm/memory.c
2530 ===================================================================
2531 RCS file: /chaos/cvs/kernel-rh/linux/mm/memory.c,v
2532 retrieving revision 1.3.2.1
2533 retrieving revision 1.3.2.1.2.1
2534 diff -u -r1.3.2.1 -r1.3.2.1.2.1
2535 --- linux/mm/memory.c   12 Mar 2003 19:51:37 -0000      1.3.2.1
2536 +++ linux/mm/memory.c   1 Apr 2003 12:17:41 -0000       1.3.2.1.2.1
2537 @@ -1381,6 +1381,10 @@
2538         }
2539         lock_page(page);
2540  
2541 +#ifdef CONFIG_MCL_COREDUMP
2542 +       set_bit(PG_anon, &page->flags);
2543 +#endif
2544 +
2545         /*
2546          * Back out if somebody else faulted in this pte while we
2547          * released the page table lock.
2548 @@ -1470,6 +1474,9 @@
2549                 mm->rss++;
2550                 flush_page_to_ram(page);
2551                 entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
2552 +#ifdef CONFIG_MCL_COREDUMP
2553 +               set_bit(PG_anon, &page->flags);
2554 +#endif
2555                 lru_cache_add(page);
2556         }
2557  
2558 Index: linux/mm/page_alloc.c
2559 ===================================================================
2560 RCS file: /chaos/cvs/kernel-rh/linux/mm/page_alloc.c,v
2561 retrieving revision 1.3.2.1
2562 retrieving revision 1.3.2.1.2.1
2563 diff -u -r1.3.2.1 -r1.3.2.1.2.1
2564 --- linux/mm/page_alloc.c       12 Mar 2003 19:51:37 -0000      1.3.2.1
2565 +++ linux/mm/page_alloc.c       1 Apr 2003 12:17:41 -0000       1.3.2.1.2.1
2566 @@ -95,6 +95,10 @@
2567         struct page *base;
2568         per_cpu_t *per_cpu;
2569         zone_t *zone;
2570 +#ifdef CONFIG_MCL_COREDUMP
2571 +       struct page *pagemap;
2572 +       int count = 1<<order;
2573 +#endif
2574  
2575         /*
2576          * Yes, think what happens when other parts of the kernel take 
2577 @@ -163,6 +167,15 @@
2578  
2579         spin_lock(&zone->lock);
2580  
2581 +#ifdef CONFIG_MCL_COREDUMP
2582 +       pagemap = page;
2583 +       do {
2584 +               pagemap->flags |= (1<<PG_free);
2585 +               pagemap->flags &= ~((1<<PG_anon)|(1<<PG_shm));
2586 +               pagemap++;
2587 +       } while(--count);
2588 +#endif
2589 +
2590         zone->free_pages -= mask;
2591  
2592         while (mask + (1 << (MAX_ORDER-1))) {
2593 @@ -268,6 +281,16 @@
2594                         zone->free_pages -= 1UL << order;
2595  
2596                         page = expand(zone, page, index, order, curr_order, area);
2597 +#ifdef CONFIG_MCL_COREDUMP
2598 +                       {
2599 +                               struct page *pagemap = page;
2600 +                               int             count = 1<<order;
2601 +                               do {
2602 +                                       pagemap->flags &= ~(1<<PG_free);
2603 +                                       pagemap++;
2604 +                               } while (--count);
2605 +                       }
2606 +#endif
2607                         spin_unlock_irqrestore(&zone->lock, flags);
2608  
2609                         set_page_count(page, 1);
2610 Index: linux/arch/i386//boot/compressed/head.S
2611 ===================================================================
2612 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/boot/compressed/head.S,v
2613 retrieving revision 1.1.1.1
2614 retrieving revision 1.1.1.1.12.6
2615 diff -u -r1.1.1.1 -r1.1.1.1.12.6
2616 --- linux/arch/i386//boot/compressed/head.S     7 May 2002 21:53:54 -0000       1.1.1.1
2617 +++ linux/arch/i386//boot/compressed/head.S     5 Apr 2003 05:51:27 -0000       1.1.1.1.12.6
2618 @@ -23,6 +23,7 @@
2619   */
2620  .text
2621  
2622 +#include <linux/config.h>
2623  #include <linux/linkage.h>
2624  #include <asm/segment.h>
2625  
2626 @@ -31,6 +32,55 @@
2627  startup_32:
2628         cld
2629         cli
2630 +
2631 +#ifdef CONFIG_BOOTIMG
2632 +/*
2633 + * GDT is invalid if we're booted by bootimg, so reload it now
2634 + */
2635 +       lgdt    %cs:gdt_descr
2636 +       ljmp    $(__KERNEL_CS),$1f
2637 +
2638 +gdt_table_limit = gdt_table_end - gdt_table - 1
2639 +gdt_descr:
2640 +       .word   gdt_table_limit
2641 +       .long   gdt_table
2642 +
2643 +gdt_table: /* stolen from arch/i386/kernel/head.S */
2644 +       .quad 0x0000000000000000        /* NULL descriptor */
2645 +       .quad 0x0000000000000000        /* 0x0b reserved */
2646 +       .quad 0x0000000000000000        /* 0x13 reserved */
2647 +       .quad 0x0000000000000000        /* 0x1b reserved */
2648 +       .quad 0x00cffa000000ffff        /* 0x23 user 4GB code at 0x00000000 */
2649 +       .quad 0x00cff2000000ffff        /* 0x2b user 4GB data at 0x00000000 */
2650 +       .quad 0x0000000000000000        /* 0x33 TLS entry 1 */
2651 +       .quad 0x0000000000000000        /* 0x3b TLS entry 2 */
2652 +       .quad 0x0000000000000000        /* 0x43 TLS entry 3 */
2653 +       .quad 0x0000000000000000        /* 0x4b reserved */
2654 +       .quad 0x0000000000000000        /* 0x53 reserved */
2655 +       .quad 0x0000000000000000        /* 0x5b reserved */
2656 +
2657 +       .quad 0x00cf9a000000ffff        /* 0x60 kernel 4GB code at 0x00000000 */
2658 +       .quad 0x00cf92000000ffff        /* 0x68 kernel 4GB data at 0x00000000 */
2659 +       .quad 0x0000000000000000        /* 0x70 TSS descriptor */
2660 +       .quad 0x0000000000000000        /* 0x78 LDT descriptor */
2661 +
2662 +       /* Segments used for calling PnP BIOS */
2663 +       .quad 0x00c09a0000000000        /* 0x80 32-bit code */
2664 +       .quad 0x00809a0000000000        /* 0x88 16-bit code */
2665 +       .quad 0x0080920000000000        /* 0x90 16-bit data */
2666 +       .quad 0x0080920000000000        /* 0x98 16-bit data */
2667 +       .quad 0x0080920000000000        /* 0xa0 16-bit data */
2668 +       /*
2669 +        * The APM segments have byte granularity and their bases
2670 +        * and limits are set at run time.
2671 +        */
2672 +       .quad 0x00409a0000000000        /* 0xa8 APM CS    code */
2673 +       .quad 0x00009a0000000000        /* 0xb0 APM CS 16 code (16 bit) */
2674 +       .quad 0x0040920000000000        /* 0xb8 APM DS    data */
2675 +gdt_table_end:
2676 +
2677 +1:
2678 +#endif
2679         movl $(__KERNEL_DS),%eax
2680         movl %eax,%ds
2681         movl %eax,%es
2682 @@ -92,7 +142,6 @@
2683         cld
2684         rep
2685         movsl
2686 -
2687         popl %esi       # discard the address
2688         popl %ebx       # real mode pointer
2689         popl %esi       # low_buffer_start
2690 @@ -124,5 +173,10 @@
2691         movsl
2692         movl %ebx,%esi  # Restore setup pointer
2693         xorl %ebx,%ebx
2694 +#ifdef CONFIG_BOOTIMG
2695 +        movl $0x100000,%eax
2696 +        jmpl *%eax
2697 +#else
2698         ljmp $(__KERNEL_CS), $0x100000
2699 +#endif
2700  move_routine_end:
2701 Index: linux/arch/i386//kernel/head.S
2702 ===================================================================
2703 RCS file: /chaos/cvs/kernel-rh/linux/arch/i386/kernel/head.S,v
2704 retrieving revision 1.2.2.1
2705 retrieving revision 1.2.2.1.2.5
2706 diff -u -r1.2.2.1 -r1.2.2.1.2.5
2707 --- linux/arch/i386//kernel/head.S      12 Mar 2003 19:49:06 -0000      1.2.2.1
2708 +++ linux/arch/i386//kernel/head.S      5 Apr 2003 05:51:27 -0000       1.2.2.1.2.5
2709 @@ -42,6 +42,21 @@
2710   * On entry, %esi points to the real-mode code as a 32-bit pointer.
2711   */
2712  startup_32:
2713 +#ifdef CONFIG_BOOTIMG
2714 +/*
2715 + * GDT is invalid if we're booted by bootimg, so reload it now
2716 + */
2717 +       lgdt %cs:_gdt_descr-__PAGE_OFFSET
2718 +       ljmp $(__KERNEL_CS),$1f-__PAGE_OFFSET
2719 +
2720 +gdt_limit = SYMBOL_NAME(cpu_gdt_table_end) - SYMBOL_NAME(cpu_gdt_table) - 1
2721 +
2722 +_gdt_descr:
2723 +       .word gdt_limit
2724 +       .long SYMBOL_NAME(cpu_gdt_table)-__PAGE_OFFSET
2725 +
2726 +1:
2727 +#endif
2728  /*
2729   * Set segments to known values
2730   */
2731 @@ -452,6 +467,7 @@
2732         .quad 0x00409a0000000000        /* 0xa8 APM CS    code */
2733         .quad 0x00009a0000000000        /* 0xb0 APM CS 16 code (16 bit) */
2734         .quad 0x0040920000000000        /* 0xb8 APM DS    data */
2735 +ENTRY(cpu_gdt_table_end)
2736  
2737  #if CONFIG_SMP
2738         .fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */