2 ? linux/include/linux/autoconf.h
3 ? linux/include/linux/modules
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
13 CFLAGS += -fomit-frame-pointer
15 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
16 +ifeq ($(CONFIG_MCL_COREDUMP),y)
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.
35 +Boot kernel image support
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.
42 +Protect SMP configuration tables
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
53 +In-memory kernel core dump facility
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 :
62 + http://www.missioncriticallinux.com/download
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
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
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
97 .rodata : { *(.rodata) *(.rodata.*) }
98 .kstrtab : { *(.kstrtab) }
100 + . = ALIGN(16); /* Relocatable bootimage code */
101 + __bootimg_start = .;
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
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
129 # Only the loader knows what is free
130 -#ifndef __BIG_KERNEL__
135 +#ifdef __BIG_KERNEL__
136 + _FLAGS = _FLAGS | LOADED_HIGH
138 +#ifdef CONFIG_BOOTIMG
139 + _FLAGS = _FLAGS | RELOADS_GDT
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
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
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
169 + * linux/arch/i386/crash.c
171 + * Architecture dependant code for MCL in-memory core dump.
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>
180 +inline void crash_save_regs(void) {
181 + static unsigned long regs[8];
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]));
196 + * Save the current stack pointer and EIP.
198 +void crash_save_current_state(struct task_struct *tp)
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).
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;
212 + crash_halt_or_reboot(1);
216 + * If we are not the panicking thread, we simply halt. Otherwise,
217 + * we take care of calling the reboot code.
219 +void crash_halt_or_reboot(int boot_cpu)
223 + stop_this_cpu(NULL);
227 + machine_restart(NULL);
230 +void crash_cleanup_smp_state(void)
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.
239 + disable_local_APIC();
246 +void smp_crash_funnel_cpu(void)
248 + crash_save_current_state(current);
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 @@
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);
268 printk("console shuts up ...\n");
270 spin_unlock(&nmi_print_lock);
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
286 #ifdef CONFIG_MATH_EMULATION
287 #include <asm/math_emu.h>
289 +#ifdef CONFIG_BOOTIMG
290 +#include <linux/bootimg.h>
293 #include <linux/irq.h>
297 void machine_restart(char * __unused)
299 +#ifdef CONFIG_MCL_COREDUMP
300 + extern char *panicmsg;
302 + * Only call bootimg if we have a valid descriptor and
303 + * we are in a panic() context.
307 +#ifdef CONFIG_BOOTIMG
308 + if (bootimg_dsc.page_dir)
316 cpuid = GET_APIC_ID(apic_read(APIC_ID));
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
334 #include <asm/mpspec.h>
335 #include <asm/mmu_context.h>
337 +#ifdef CONFIG_MCL_COREDUMP
338 +#include <linux/crash.h>
344 static unsigned long __init setup_memory(void)
346 unsigned long bootmap_size, start_pfn, max_low_pfn;
347 + unsigned long bootmap_pages = 0UL, crash_pages = 0UL;
350 * partially used pages are not usable - thus
352 printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
353 pages_to_mb(highend_pfn - highstart_pfn));
356 +#ifdef CONFIG_MCL_COREDUMP
357 + bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
358 + crash_pages = crash_pages_needed();
360 + printk("start_pfn: %d, bootmap_pages: %d\n", start_pfn, bootmap_pages);
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 +
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);
370 printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
371 pages_to_mb(max_low_pfn));
373 @@ -1007,8 +1026,8 @@
374 * the (very unlikely) case of us accidentally initializing the
375 * bootmem allocator with an invalid RAM area.
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));
383 * reserve physical page 0 - it's a special BIOS page on many boxes,
384 @@ -1016,6 +1035,16 @@
386 reserve_bootmem(0, PAGE_SIZE);
388 +#ifdef CONFIG_BOOTIMG
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);
395 + reserve_bootmem(0x90000, PAGE_SIZE);
400 * But first pinch a few for the stack/trampoline stuff
401 @@ -1032,6 +1061,7 @@
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*/
413 +#ifdef CONFIG_MCL_COREDUMP
415 + * Reserve crash pages
417 + crash_mark_dump_reserved();
419 #ifdef CONFIG_X86_LOCAL_APIC
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
431 #include <asm/pgalloc.h>
432 #include <asm/smpboot.h>
434 +#ifdef CONFIG_MCL_COREDUMP
435 +#include <asm/crash.h>
438 * Some notes on x86 processor bugs affecting SMP operation:
444 -static void stop_this_cpu (void * dummy)
445 +void stop_this_cpu (void * dummy)
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
458 #include <linux/irq.h>
459 #include <linux/module.h>
461 +#ifdef CONFIG_MCL_COREDUMP
462 +#include <linux/crash.h>
465 asmlinkage int system_call(void);
466 asmlinkage void lcall7(void);
467 asmlinkage void lcall27(void);
471 spin_unlock_irq(&die_lock);
473 +#ifdef CONFIG_MCL_COREDUMP
477 + do_exit(SIGSEGV);/* NOTREACHED */
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
490 extern int i8k_init(void);
491 extern int lcd_init(void);
493 +extern int crash_init_chrdev(void);
495 static int misc_read_proc(char *buf, char **start, off_t offset,
496 int len, int *eof, void *private)
499 int __init misc_init(void)
501 create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL);
502 +#ifdef CONFIG_MCL_COREDUMP
503 + crash_init_chrdev();
505 #ifdef CONFIG_MVME16x
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
517 action_msg: "Resetting",
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) {
527 +static struct sysrq_key_op sysrq_coredump_op = {
528 + handler: sysrq_handle_coredump,
530 + action_msg: "Dumping core",
534 /* SYNC SYSRQ HANDLERS BLOCK */
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,
546 /* e */ &sysrq_term_op,
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
555 +/* asm-i386/bootimg.h - Boot image, i386-specific code */
557 +/* Written 2000 by Werner Almesberger */
560 + * When porting bootimg(2) to a new architcture, you need to adapt the
561 + * functions and definitions in this file.
565 +#ifndef _ASM_I386_BOOTIMG_H
566 +#define _ASM_I386_BOOTIMG_H
568 +#include <linux/config.h>
569 +#include <asm/system.h>
572 +#include <linux/smp.h>
573 +#include <linux/irq.h>
578 + * The memory page with the code currently executing has been copied from
579 + * old_page to new_page. Jump there.
581 + * Note: flush_icache_range has already been called on the new page.
584 +static inline void jump_relocated(unsigned long old_page,unsigned long new_page)
588 + __asm__ __volatile__(
594 + "addl %1,%%esp\n\t"
598 + : "=&r" (tmp) : "r" (new_page-old_page));
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
608 + * (Other rules are possible, but need to be encoded in bootimg(8).)
611 +static inline void stop_paging(void)
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 */
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.
628 +#ifdef CONFIG_X86_PAE
629 + "movl %%cr4,%0\n\t"
630 + "andl $0xffffffdf,%0\n\t"
631 + "movl %0,%%cr4\n\t"
634 + : "=&r" (msw) : : "memory");
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.
644 +static inline int become_only_thread(void)
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.
661 +#define RESERVE_MIN_RELOC_STACK 256
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
670 +static inline void stack_on_page(void *page)
672 + __asm__ __volatile__(
675 + "movl %0,%%esp\n\t"
676 + "addl $0x1000,%%esp\n\t"
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.
686 +static inline void jump_to_kernel(void (*kernel_entry)(void))
688 + __asm__ __volatile__(
689 + "mov $0x90000,%%esi\n\t"
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
703 +#ifndef __ASM_CRASH_H
704 +#define __ASM_CRASH_H
706 +#define UPPER_MEM_BACKUP 0
707 +#define LOWER_MEM_FORWARD 0
708 +#define LOW_OFFSET 100
711 + * These two functions are inlined on alpha. That's why they appear
712 + * in the arch dependent include file.
714 +void crash_save_current_state(struct task_struct *);
715 +void crash_halt_or_reboot(int);
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
725 +/* linux/bootimg.h - Boot image, general definitions */
727 +/* Written 2000 by Werner Almesberger */
730 +#ifndef _LINUX_BOOTIMG_H
731 +#define _LINUX_BOOTIMG_H
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
744 + * Constraints on load_map:
745 + * - each load_map[] is the physical address of a page in RAM
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 */
759 +#define __bootimg __attribute__ ((__section__ (".bootimg")))
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 */
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.
779 + * Note that the definitions used here do not necessarily correspond to the
780 + * architecture-specific PTRS_PER_PTE, __pte_offset, etc.
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)
789 +extern char __bootimg_start,__bootimg_end; /* linker segment boundaries */
790 +extern unsigned long *unity_page; /* unity-mapped page for i386 */
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.
799 +extern struct bootimg_dsc bootimg_dsc;
801 +typedef void (*relocate_and_jump_t)(void);
803 +void relocate_and_jump(void);
804 +int boot_image(void);
806 +#endif /* __KERNEL__ */
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
816 +#ifndef __LINUX_CRASH_H
817 +#define __LINUX_CRASH_H
819 +/* defines for interfacing with user-space (ioctls, etc) */
820 +struct ioctl_getdump {
825 +#define CRASH_IOC_MAGIC 'C'
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)
832 +/* kernel-only part of crash.h */
834 +#include <asm/crash.h>
836 +#define CRASH_K_MINOR (1)
837 +#define CRASH_K_MAJOR (0)
840 + * Crash prototypes.
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);
850 + * Arch dependant crash.c funcs
852 +void crash_save_current_state(struct task_struct *);
853 +void crash_halt_or_reboot(int);
854 +inline void crash_save_regs(void);
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;
869 + * symbols not exported by linux header files
871 +extern void stop_this_cpu(void *);
873 +/* struct crash_map_hdr located at byte offset 0 */
874 +/* on-disk formats */
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)))
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
889 +#define CRASH_CPU_TIMEOUT 5000 /* 5 sec wait for other cpus to stop */
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);
895 +typedef int boolean_t;
901 +struct mem_crash_map_hdr {
902 + long magic[4]; /* identify crash dump */
903 + u_long map; /* location of map */
906 + u_long compr_units;
907 + u_long boot_reserved_start;
908 + u_long boot_reserved_end;
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 */
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 */
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 */
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
945 #define PG_active_cache 19
946 #define PG_fs_1 20 /* Filesystem specific */
947 +#ifdef CONFIG_MCL_COREDUMP
953 /* Make it prettier to test the above... */
954 #define UnlockPage(page) unlock_page(page)
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))
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
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.
982 #define LINUX_REBOOT_CMD_RESTART 0x01234567
984 #define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
985 #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
986 #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
988 +#ifdef CONFIG_MCL_COREDUMP
989 +#define LINUX_REBOOT_CMD_COREDUMP 0x9A8BCCDD
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
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 */
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
1019 #include <asm/smp.h>
1022 +#ifdef CONFIG_BOOTIMG
1023 +#include <linux/bootimg.h>
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 @@
1031 char * command_line;
1032 extern char saved_command_line[];
1033 +#if defined(CONFIG_BOOTIMG) && defined(CONFIG_X86_LOCAL_APIC)
1034 + unsigned long value;
1037 * Interrupts are still disabled. Do necessary setups, then
1040 + printk("start_kernel\n");
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.
1049 +#ifdef CONFIG_BOOTIMG
1050 + unity_page = alloc_bootmem_pages(PAGE_SIZE);
1051 + printk("unity_page addr: %p\n",unity_page);
1053 #ifdef CONFIG_MODULES
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
1063 + setup_local_APIC();
1065 + value = apic_read(APIC_LVT0);
1066 + apic_write_around(APIC_LVT0, value & ~APIC_LVT_MASKED);
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
1080 obj-$(CONFIG_PM) += pm.o
1081 obj-$(CONFIG_KALLSYMS) += kallsyms.o
1082 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
1084 +obj-$(CONFIG_BOOTIMG) += bootimg.o bootimg_pic.o
1085 +obj-$(CONFIG_MCL_COREDUMP) += crash.o
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
1096 +/* bootimg.c - Boot another (kernel) image */
1098 +/* Written 2000 by Werner Almesberger */
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>
1114 +#define DPRINTK_CONT(format,args...) printk(format,##args)
1116 +#define DPRINTK_CONT(format,args...)
1118 +#define DPRINTK(format,args...) DPRINTK_CONT(KERN_DEBUG format,##args)
1120 +unsigned long **bootimg_page_dir;
1122 +struct bootimg_dsc bootimg_dsc; /* communication with PIC */
1123 +unsigned long *unity_page; /* unity-mapped page for i386 */
1125 +static unsigned long bootimg_checksum(unsigned long **page_dir, int num_pages)
1127 + unsigned long checksum, *page;
1132 + for (i = 0; i < num_pages; i++) {
1133 + page = __va((unsigned long *)
1134 + page_dir[FROM_TABLE(i)][PAGE_NR(i)]);
1136 + for (j = 0; j < PAGES_PER_TABLE; j++)
1137 + checksum ^= page[j];
1139 + checksum ^= page_dir[TO_TABLE(i)][PAGE_NR(i)];
1145 +#ifdef CONFIG_X86_PAE
1147 +static unsigned long get_identity_mapped_page(void)
1151 + unsigned long phys_addr, page_base;
1153 + /* Set up a 2 Mb identity-mapped page. */
1155 + phys_addr = virt_to_phys(unity_page);
1156 + pgd = pgd_offset(current->active_mm, phys_addr);
1157 + pmd = pmd_offset(pgd, phys_addr);
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.
1162 + page_base = phys_addr & ~((1 << 21) - 1);
1164 + set_pmd(pmd, __pmd(page_base | _PAGE_PSE | _KERNPG_TABLE));
1165 + __flush_tlb_one(phys_addr);
1167 + return (unsigned long) unity_page;
1172 +static unsigned long get_identity_mapped_page(void)
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;
1182 +#if 0 /* Perhaps we'll need this in the future? */
1183 +static void unmap_identity_mapped_page(void)
1185 + set_pgd(pgd_offset(current->active_mm,virt_to_phys(unity_page)),__pgd(0));
1190 +static int fill_page_dir(unsigned long **page_dir,struct boot_image *image)
1194 + memset(page_dir,0,PAGE_SIZE);
1195 + for (i = 0; i < image->pages; i += PAGES_PER_TABLE) {
1196 + unsigned long **table;
1199 + table = page_dir+FROM_TABLE(i);
1200 + *table = (unsigned long *) get_free_page(GFP_KERNEL);
1201 + if (!*table) return -ENOMEM;
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;
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))
1213 + DPRINTK("page %d: to table %p @ %p\n",i,*table,table);
1214 + count+=2; /* 2 pages per loop */
1217 + for (i = 0; i < image->pages; i++) {
1218 + unsigned long page = get_free_page(GFP_KERNEL);
1221 + if (!page) return -ENOMEM;
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))
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)]);
1235 + DPRINTK("fill_page_dir: %d pages allocated\n", count);
1241 +static void free_page_dir(unsigned long **page_dir)
1245 + for (i = 0; i < PAGES_PER_TABLE/2; 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]));
1253 + for (i = 0; i < PAGES_PER_TABLE; i++)
1254 + if (page_dir[i]) {
1255 + free_page((unsigned long) *page_dir[i]);
1258 + DPRINTK("free_page_dir: %d pages freed\n", count);
1262 +static void convert_table_refs_to_phys(unsigned long **page_dir)
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]);
1278 +static int fill_bootimg_dsc(struct boot_image *image)
1280 + unsigned long scratch;
1281 + int error = -ENOMEM;
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");
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");
1294 + error = fill_page_dir(bootimg_page_dir,image);
1295 + if (error) goto out1;
1297 + if(!bootimg_dsc.scratch) {
1298 + scratch = get_free_page(GFP_KERNEL);
1299 + DPRINTK("get_free_page (scratch)\n");
1301 + scratch = 1; /* already allocated */
1303 + if (!scratch) goto out1;
1305 + * Not all architectures need the code to be identity-mapped, but it
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);
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;
1328 +extern char *panicmsg;
1331 + relocate_and_jump_t code;
1332 + unsigned long code_page;
1333 + int error = -ENOMEM;
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");
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);
1345 + bootimg_dsc.self = (unsigned long) code;
1346 + printk(KERN_INFO "Running boot code at 0x%p\n",code);
1349 + * The point of no return. Not even printk may work after a successful
1350 + * return from become_only_thread.
1354 + error = become_only_thread();
1355 + if (error) goto out3;
1358 + disable_IO_APIC();
1363 + convert_table_refs_to_phys((unsigned long **)__va(bootimg_dsc.page_dir));
1364 + stack_on_page(code);
1368 + panic("PIC code exec failed");
1370 + printk("boot_image() failed!\n");
1374 +/* changed from asmlinkage because we're called via an IOCTL on /dev/crash now */
1375 +int sys_bootimg(struct boot_image *user_dsc)
1377 + struct boot_image dsc;
1379 + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_MODULE)) return -EPERM;
1380 + if (&__bootimg_end-&__bootimg_start > PAGE_SIZE-RESERVE_MIN_RELOC_STACK)
1382 + printk(KERN_ERR "boot_image: PIC too large (%d bytes)\n",
1383 + &__bootimg_end-&__bootimg_start);
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);
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);
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
1404 +/* bootimg_pic.c - Boot image, position-independent code */
1406 +/* Written 2000 by Werner Almesberger */
1409 + * Strongly inspired by FiPaBoL designed mainly by Otfried Cheong and Roger
1410 + * Gammans, and written by the latter.
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.
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>
1427 +#include <asm/io.h>
1429 +#define copy_and_swap(from,to) \
1430 + ( { my_copy_page(from,to); \
1436 +static inline void my_copy_page(unsigned long from,unsigned long to)
1438 + unsigned long end = from+PAGE_SIZE;
1440 + do *((unsigned long *) to)++ = *((unsigned long *) from)++;
1441 + while (from != end);
1445 +void __bootimg relocate_and_jump(void)
1447 + struct bootimg_dsc dsc = bootimg_dsc;
1451 + for (i = 0; i < dsc.pages; i++) {
1452 + unsigned long from,to,tmp;
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);
1463 + else if (to == (unsigned long) dsc.page_dir)
1464 + copy_and_swap((unsigned long) dsc.page_dir,dsc.scratch);
1467 + * O((n^2-n)/2), sigh ...
1469 + unsigned long **table;
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);
1478 + if ((*table)[PAGE_NR(j)] == to) {
1479 + copy_and_swap((*table)[PAGE_NR(j)],
1483 + table = dsc.page_dir+TO_TABLE(j);
1484 + if (((unsigned long) *table) == to) {
1485 + copy_and_swap(*table,dsc.scratch);
1490 + my_copy_page(from,to);
1491 + dsc.scratch = from;
1493 + jump_to_kernel(dsc.jump_to);
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
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>
1518 +#ifdef CONFIG_BOOTIMG
1519 +#include <linux/bootimg.h>
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);
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);
1545 +#define CRASH_DEBUG 1
1547 +#ifdef CONFIG_BOOTIMG
1548 +extern int sys_bootimg(struct boot_image *);
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;
1557 +static u_long crash_cur_pfn;
1559 +static u_long src_pages_skipped = 0;
1560 +static u_long src_pages_saved = 0;
1561 +static u_long dest_pages_free = 0;
1563 +/* this information is saved from within panic() */
1564 +char *panicmsg = (char *)0;
1565 +int panic_processor = 0;
1566 +int crash_perform_sync = 0;
1568 +u_int console_crash = 0; /* should be moved to alpha branch */
1570 +// typedef struct task_struct *task_t;
1573 + * Threads active at time of panic:
1575 +volatile task_t *panic_threads[NR_CPUS];
1576 +volatile unsigned long panic_ksp[NR_CPUS];
1577 +unsigned long *panic_regs = NULL;
1579 +int panic_on_oops; /* for /proc/sys/kernel/panic_on_oops */
1581 +extern unsigned long max_low_pfn;
1583 +u_long crash_zalloc_start; // , crash_zalloc_end, crash_zalloc_cur;
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.
1593 +u_long crash_pages_needed(void)
1595 + /* one for the header */
1596 + return (1 + CRASH_ZALLOC_PAGES + CRASH_UNCOMPR_BUF_PAGES + CRASH_COMPR_BUF_PAGES);
1599 +void crash_init(u_long bootmap_va, u_long crash_va, u_long end_alloc_va)
1601 + struct mem_crash_map_hdr *header;
1604 + /* the default behavior is not NOT panic on a kernel OOPS */
1605 + panic_on_oops = 0;
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;
1619 + if (crash_va != end_alloc_va)
1620 + panic("crash_init inconsistency-1\n");
1623 + header = (struct mem_crash_map_hdr *)crash_dump_header;
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);
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");
1643 +printk("memset...");
1644 + memset(header, 0, sizeof(*header));
1648 + header->boot_reserved_start = bootmap_va;
1649 + header->boot_reserved_end = end_alloc_va;
1653 +void crash_mark_dump_reserved(void)
1655 + struct mem_crash_map_hdr *header;
1656 + struct mem_crash_map_entry *m;
1658 + header = (struct mem_crash_map_hdr *)crash_dump_header;
1659 + if (header->magic[0] != CRASH_MAGIC)
1661 + m = (struct mem_crash_map_entry *)header->map;
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);
1678 + if (crash_audit_maps()) {
1679 + header->magic[0] = 0;
1683 + m = (struct mem_crash_map_entry *)header->map;
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;
1691 + CRASH_MARK_BOOT_RESERVED(m->dest_page_va);
1696 +void save_core(void)
1701 + struct task_struct *tp;
1702 + struct mem_crash_map_hdr *header;
1705 + u_long src, dest, unc, cp, src_base, comp_pages;
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);
1716 + if (console_crash)
1717 + panic_threads[smp_processor_id()] = &init_task_union.task;
1719 + panic_threads[smp_processor_id()] = tp;
1721 + crash_wait_cpus();
1724 + printk("save_core: started on CPU%d\n", smp_processor_id());
1725 + if (!crash_dump_header) {
1726 + printk("save_core: not initialized\n");
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;
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);
1751 + init_dest_page_alloc();
1752 + header->map = map = crash_update_map(0, 0, 0, &header->map_pages);
1754 + printk("save_core: no dest pages\n");
1757 + crash_cur_pfn = 0;
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();
1769 + if (!crash_is_kseg(unc) || !crash_is_kseg(src)) {
1770 + printk("unc = 0x%lx, src = 0x%lx, i = %d\n", unc, src, i);
1774 + memcpy((void *)unc, (void *)src, PAGE_SIZE);
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,
1788 + comp_pages = (u_long) round_page(stream.total_out) / PAGE_SIZE;
1790 + printk("src_base = 0x%lx compressed data in 0x%lx pages\n", src_base,
1793 + cp = crash_compr_buf;
1796 + printk("\nsrc = %lx\n", src_base);
1802 + for (i = 0; i < comp_pages; i++) {
1803 + dest = crash_alloc_dest_page();
1804 + if (crash_debug) {
1805 + printk("%lx ", dest);
1809 + header->data_pages++;
1811 + printk("save_core: no dest pages\n");
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);
1820 + memcpy((void *)dest, (void *)cp, PAGE_SIZE);
1822 + map = crash_update_map(map, src_base, dest, &header->map_pages); /* links a new map page, if necessary */
1824 + printk("save_core: no map\n");
1828 + header->compr_units++;
1831 + if (crash_reset_stream(&stream))
1835 + map = crash_update_map(map, 0, 0, &header->map_pages);
1836 + header->magic[0] = CRASH_MAGIC;
1838 + if (crash_audit_maps()) {
1839 + header->magic[0] = 0;
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);
1850 +/* helper functions private to this file */
1851 +static int crash_reset_stream(z_stream * stream)
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);
1871 +static u_long crash_alloc_dest_page(void)
1875 + addr = crash_dest_free_list;
1877 + crash_dest_free_list = *(u_long *) addr;
1878 + dest_pages_free--;
1880 + printk("crash_alloc_dest_page: free list empty\n");
1884 +static void crash_free_dest_page(u_long dest)
1887 + printk("crash_free_dest_page: freeing addr 0\n");
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;
1897 + * Stolen from setup.c
1899 +#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
1901 +static void init_dest_page_alloc(void)
1905 + struct page *page;
1906 + struct mem_crash_map_hdr *header;
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))
1914 + page = mem_map + i;
1915 + if (PageLocked(page) || PageReserved(page))
1917 + if (PageFree(page) || PageAnon(page) || PageShm(page) || page->buffers)
1918 + crash_free_dest_page(va);
1921 + printk("init_dest_page_alloc: dest_pages_free = 0x%lx\n", dest_pages_free);
1924 +static int crash_is_dir_page(struct page *page) {
1925 + struct inode *tmp_inode;
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)))
1937 +static u_long crash_get_source_page(void)
1939 + struct page *page;
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))
1946 + src_pages_skipped++;
1949 + if (crash_cur_pfn == max_low_pfn)
1952 + va = (u_long) phys_to_virt(PFN_PHYS(crash_cur_pfn));
1953 + src_pages_saved++;
1958 +static u_long crash_update_map(u_long map, u_long src_base, u_long dest, u_long * pages)
1960 + struct mem_crash_map_entry *m;
1965 + return crash_alloc_dest_page();
1967 + m = (struct mem_crash_map_entry *)map;
1968 + m->src_va = src_base;
1969 + m->dest_page_va = dest;
1971 + if (crash_chksum_page(dest, &m->check_sum))
1974 + map += sizeof(struct mem_crash_map_entry);
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))
1980 + } else if ((map + 3 * sizeof(struct mem_crash_map_entry)) > (u_long) round_page(map)) {
1982 + map = m->dest_page_va = crash_alloc_dest_page();
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);
1987 + if (crash_chksum((u_long) m, &m->src_va))
1990 + printk("m = 0x%lx chksum = m->src_va = 0x%lx\n", (u_long) trunc_page(m),
1992 + if (crash_audit_map_page((u_long) m))
1999 +static int crash_chksum(u_long limit, u_long * sum_addr)
2004 + if (!crash_is_kseg(limit)) {
2005 + printk("bad addr = 0x%lx to crash_chksum\n", limit);
2009 + addr = (u_long *) trunc_page(limit);
2010 + for (; (u_long) addr < limit; addr++)
2016 +static int crash_chksum_page(u_long pg_addr, u_long * sum_addr)
2018 + u_long sum, limit;
2021 + if (!crash_is_kseg(pg_addr)) {
2022 + printk("bad addr = 0x%lx to crash_chksum_page\n", pg_addr);
2027 + addr = (u_long *) trunc_page(pg_addr);
2028 + limit = (u_long) addr + PAGE_SIZE;
2029 + for (; (u_long) addr < limit; addr++)
2035 +static int crash_audit_maps(void)
2038 + u_long *link_addr;
2039 + struct mem_crash_map_hdr *header;
2041 + header = (struct mem_crash_map_hdr *)crash_dump_header;
2042 + if (header->magic[0] != CRASH_MAGIC)
2045 + link_addr = &header->map;
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);
2055 + if (crash_audit_map_page(m)) {
2056 + printk("audit failed while on map page %ld\n", count);
2059 + if (!crash_link(m))
2061 + link_addr = crash_link(m);
2069 +static int crash_audit_map_page(u_long map)
2071 + struct mem_crash_map_entry *m;
2074 + if (!map || !crash_is_kseg(map)) {
2075 + printk("crash_audit_map_page: bad map = 0x%lx\n", map);
2078 + map = (u_long) trunc_page((u_long) map);
2079 + m = (struct mem_crash_map_entry *)map;
2081 + if ((m->src_va == -1) || (m->src_va == 0)) {
2083 + if (crash_chksum((u_long) m, &sum))
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);
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");
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);
2110 +static void crash_print_data_around(u_long p)
2115 + if (!crash_is_kseg(p)) {
2116 + printk("crash_print_data_around: p = 0x%lx not kseg\n", p);
2121 + for (i = 0; i < 40; i++)
2122 + printk("%lx\n", *a++);
2126 +static void crash_print_map_page(u_long map)
2128 + struct mem_crash_map_entry *m;
2132 + map = (u_long) trunc_page((u_long) map);
2133 + m = (struct mem_crash_map_entry *)map;
2135 + printk("%lx %lx %lx ", m->src_va, m->dest_page_va, m->check_sum);
2138 + if ((m->src_va == -1) || (m->src_va == 0)) {
2140 + printk("%lx %lx ", m->src_va, m->dest_page_va);
2141 + if (crash_chksum((u_long) m, &sum));
2143 + printk("\nchksum = 0x%lx\n", sum);
2149 +#endif /* CRASH_DEBUG */
2151 +static void crash_wait_cpus(void)
2156 + for (i = 0; i < smp_num_cpus; i++) {
2157 + if (i != smp_processor_id()) {
2158 + while (!panic_threads[i]) {
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.
2167 + printk("Unable to halt other CPUs, halting system.\n");
2168 + crash_halt_or_reboot(0);
2174 + crash_cleanup_smp_state();
2179 +static void *czalloc(void *arg, unsigned int items, unsigned int size)
2184 + nbytes = (u_long) (items * size);
2185 + nbytes = (u_long) round_page(nbytes);
2186 + if ((crash_zalloc_cur + nbytes) > crash_zalloc_end)
2188 + addr = crash_zalloc_cur;
2189 + crash_zalloc_cur += nbytes;
2190 + return ((void *)addr);
2193 +static void czfree(void *arg, void *ptr)
2195 + printk("zfree: ptr = 0x%lx\n", (u_long) ptr);
2199 +static boolean_t crash_is_kseg(u_long addr)
2203 + phys = virt_to_phys((void *)addr);
2204 + if (phys < PFN_PHYS(max_low_pfn))
2210 +static u_long *crash_link(u_long p)
2212 + struct mem_crash_map_entry *m;
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;
2223 +/* Call this after data written to disk. */
2224 +static int crash_free_crashmem(void)
2226 + struct mem_crash_map_hdr *header;
2227 + struct mem_crash_map_entry *m, *last_m;
2230 + printk("crash_free_crashmem: \n");
2232 + header = (struct mem_crash_map_hdr *)crash_dump_header;
2233 + if (crash_audit_maps()) {
2234 + header->magic[0] = 0;
2237 + m = (struct mem_crash_map_entry *)header->map;
2239 + for (; m->src_va; m++) {
2240 + if (m->src_va == -1) {
2242 + m = (struct mem_crash_map_entry *)m->dest_page_va;
2243 + crash_free_page((unsigned long)last_m);
2246 + crash_free_page(m->dest_page_va);
2249 + printk("crash_free_crashmem: 0x%lx freed\n",
2250 + (header->data_pages + header->map_pages) * PAGE_SIZE);
2251 + header->magic[0] = 0;
2255 +static void crash_free_page(u_long addr)
2257 + struct page *page;
2259 + page = virt_to_page(addr);
2260 + ClearPageReserved(page);
2261 + set_page_count(page, 1);
2262 + __free_page(page);
2265 +static int get_dump_helper(u_long kva, u_long buf)
2267 + struct page *page;
2268 + struct mem_crash_map_hdr *header;
2270 + header = (struct mem_crash_map_hdr *)crash_dump_header;
2271 + if (header->magic[0] != CRASH_MAGIC)
2275 + if (crash_audit_maps()) {
2276 + printk("get_dump_helper: audit failure\n");
2277 + header->magic[0] = 0;
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);
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");
2291 + page = virt_to_page(kva);
2292 + if (!PageReserved(page)) {
2293 + printk("not reserved: kva = 0x%lx\n", kva);
2296 + if (copy_to_user((char *)buf, (char *)trunc_page(kva), PAGE_SIZE)) {
2297 + printk("get_dump_helper: copy_to_user failed2\n");
2304 +static void free_dump_helper(void)
2306 + struct mem_crash_map_hdr *header;
2308 + header = (struct mem_crash_map_hdr *)crash_dump_header;
2309 + if (header->magic[0] != CRASH_MAGIC)
2312 + printk("free_dump_helper\n");
2313 + crash_free_crashmem();
2316 +static int crashdev_open(struct inode *inode, struct file *file)
2318 + /* always return success -- nothing to do here */
2322 +/* character device implementation */
2323 +static struct file_operations crashdev_fops = {
2324 + ioctl:crashdev_ioctl,
2325 + open:crashdev_open,
2328 +static struct miscdevice crash_miscdev = {
2329 + 190, "crash", &crashdev_fops
2332 +int crash_init_chrdev(void)
2336 + result = misc_register(&crash_miscdev);
2339 + printk(KERN_WARNING "crash: can't register crash device (c 10 190)\n");
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)
2351 + case CRASH_IOCFREEDUMP:
2352 + free_dump_helper();
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);
2363 + retval = get_dump_helper((u_long) ((struct ioctl_getdump *)arg)->kva,
2364 + (u_long) ((struct ioctl_getdump *)arg)->buf);
2367 +#ifdef CONFIG_BOOTIMG
2368 + case CRASH_IOCBOOTIMG:
2370 + printk("crashdev_ioctl: bootimg\n");
2372 + retval = sys_bootimg((struct boot_image *)arg);
2376 + case CRASH_IOCVERSION:
2378 + printk("crashdev_ioctl: version\n");
2379 + retval = CRASH_K_MINOR | (CRASH_K_MAJOR << 16);
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 @@
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.
2404 + if ((mod = (struct module *)vmalloc_32(size)) == NULL) {
2406 if ((mod = (struct module *)module_map(size)) == NULL) {
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
2420 #include <linux/vt_kern.h>
2421 #include <linux/pc_keyb.h>
2423 +#ifdef CONFIG_MCL_COREDUMP
2424 +#include <linux/crash.h>
2427 asmlinkage void sys_sync(void); /* it's really int */
2430 @@ -197,20 +201,43 @@
2431 unsigned long caller = (unsigned long) __builtin_return_address(0);
2434 +#ifdef CONFIG_MCL_COREDUMP
2435 + crash_save_regs();
2439 va_start(args, fmt);
2440 vsprintf(buf, fmt, args);
2442 printk(KERN_EMERG "Kernel panic: %s\n",buf);
2444 +#ifdef CONFIG_MCL_COREDUMP
2447 + panic_processor = smp_processor_id();
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)
2467 +#ifdef CONFIG_MCL_COREDUMP
2468 + smp_call_function((void *)smp_crash_funnel_cpu,0,0,0);
2469 + crash_save_current_state(current);
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
2483 #include <linux/nfs_fs.h>
2486 +#ifdef CONFIG_MCL_COREDUMP
2487 +#include <linux/crash.h>
2490 #if defined(CONFIG_SYSCTL)
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},
2497 +#ifdef CONFIG_MCL_COREDUMP
2498 + {KERN_PANIC_ON_OOPS, "panic_on_oops", &panic_on_oops, sizeof(int),
2499 + 0644, NULL, &proc_dointvec},
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
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
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
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 @@
2541 +#ifdef CONFIG_MCL_COREDUMP
2542 + set_bit(PG_anon, &page->flags);
2546 * Back out if somebody else faulted in this pte while we
2547 * released the page table lock.
2548 @@ -1470,6 +1474,9 @@
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);
2555 lru_cache_add(page);
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
2570 +#ifdef CONFIG_MCL_COREDUMP
2571 + struct page *pagemap;
2572 + int count = 1<<order;
2576 * Yes, think what happens when other parts of the kernel take
2577 @@ -163,6 +167,15 @@
2579 spin_lock(&zone->lock);
2581 +#ifdef CONFIG_MCL_COREDUMP
2584 + pagemap->flags |= (1<<PG_free);
2585 + pagemap->flags &= ~((1<<PG_anon)|(1<<PG_shm));
2590 zone->free_pages -= mask;
2592 while (mask + (1 << (MAX_ORDER-1))) {
2593 @@ -268,6 +281,16 @@
2594 zone->free_pages -= 1UL << order;
2596 page = expand(zone, page, index, order, curr_order, area);
2597 +#ifdef CONFIG_MCL_COREDUMP
2599 + struct page *pagemap = page;
2600 + int count = 1<<order;
2602 + pagemap->flags &= ~(1<<PG_free);
2604 + } while (--count);
2607 spin_unlock_irqrestore(&zone->lock, flags);
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
2622 +#include <linux/config.h>
2623 #include <linux/linkage.h>
2624 #include <asm/segment.h>
2631 +#ifdef CONFIG_BOOTIMG
2633 + * GDT is invalid if we're booted by bootimg, so reload it now
2635 + lgdt %cs:gdt_descr
2636 + ljmp $(__KERNEL_CS),$1f
2638 +gdt_table_limit = gdt_table_end - gdt_table - 1
2640 + .word gdt_table_limit
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 */
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 */
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 */
2669 + * The APM segments have byte granularity and their bases
2670 + * and limits are set at run time.
2672 + .quad 0x00409a0000000000 /* 0xa8 APM CS code */
2673 + .quad 0x00009a0000000000 /* 0xb0 APM CS 16 code (16 bit) */
2674 + .quad 0x0040920000000000 /* 0xb8 APM DS data */
2679 movl $(__KERNEL_DS),%eax
2687 popl %esi # discard the address
2688 popl %ebx # real mode pointer
2689 popl %esi # low_buffer_start
2690 @@ -124,5 +173,10 @@
2692 movl %ebx,%esi # Restore setup pointer
2694 +#ifdef CONFIG_BOOTIMG
2695 + movl $0x100000,%eax
2698 ljmp $(__KERNEL_CS), $0x100000
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
2710 * On entry, %esi points to the real-mode code as a 32-bit pointer.
2713 +#ifdef CONFIG_BOOTIMG
2715 + * GDT is invalid if we're booted by bootimg, so reload it now
2717 + lgdt %cs:_gdt_descr-__PAGE_OFFSET
2718 + ljmp $(__KERNEL_CS),$1f-__PAGE_OFFSET
2720 +gdt_limit = SYMBOL_NAME(cpu_gdt_table_end) - SYMBOL_NAME(cpu_gdt_table) - 1
2724 + .long SYMBOL_NAME(cpu_gdt_table)-__PAGE_OFFSET
2729 * Set segments to known values
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)
2738 .fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */