You can subscribe to this list here.
2005 |
Jan
|
Feb
|
Mar
|
Apr
(147) |
May
(104) |
Jun
(587) |
Jul
(83) |
Aug
(270) |
Sep
(1) |
Oct
(133) |
Nov
(353) |
Dec
(129) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2006 |
Jan
(15) |
Feb
(31) |
Mar
(32) |
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(22) |
Dec
|
From: Itsuro O. <od...@us...> - 2006-11-22 01:30:36
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv22290/kernel Added Files: Makefile minik_dump_ex.c panic.c Log Message: support 2.6.17 (caution: only i386 done) --- NEW FILE: minik_dump_ex.c --- /* * kernel/minik_dump_ex.c * * $Id: minik_dump_ex.c,v 1.1 2006/11/22 01:30:32 odaodab Exp $ * * Portions Copyright (C) 2004 NTT DATA CORPORATION. * Portions Copyright (C) 2004 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation (version 2 of the License). * * Mkdump is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/config.h> #include <linux/stddef.h> #include <linux/mm.h> #include <linux/swap.h> #include <linux/interrupt.h> #include <linux/pagemap.h> #include <linux/bootmem.h> #include <linux/compiler.h> #include <linux/module.h> #include <linux/suspend.h> #include <linux/pagevec.h> #include <linux/blkdev.h> #include <linux/slab.h> #include <linux/notifier.h> #include <linux/topology.h> #include <linux/sysctl.h> #include <linux/cpu.h> #include <linux/kernel.h> #include <linux/reboot.h> #include <linux/mkexec_dump.h> #include <asm/e820.h> /* * Export Symbols for mkexec */ EXPORT_SYMBOL(__pte_alloc_kernel); EXPORT_SYMBOL(bust_spinlocks); EXPORT_SYMBOL(machine_restart); /* * call dump function hook */ void (*do_dump_func)(char *, struct pt_regs *) = NULL; void do_dump(char *panic_str, struct pt_regs *regs) { if (do_dump_func) { (*do_dump_func)(panic_str, regs); } } EXPORT_SYMBOL(do_dump_func); EXPORT_SYMBOL(do_dump); --- NEW FILE: panic.c --- /* * linux/kernel/panic.c * * Copyright (C) 1991, 1992 Linus Torvalds */ /* * This function is used through-out the kernel (including mm and fs) * to indicate a major problem. */ #include <linux/config.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/reboot.h> #include <linux/notifier.h> #include <linux/init.h> #include <linux/sysrq.h> #include <linux/interrupt.h> #include <linux/nmi.h> #include <linux/kexec.h> int panic_on_oops; int tainted; static int pause_on_oops; static int pause_on_oops_flag; static DEFINE_SPINLOCK(pause_on_oops_lock); int panic_timeout; ATOMIC_NOTIFIER_HEAD(panic_notifier_list); EXPORT_SYMBOL(panic_notifier_list); static int __init panic_setup(char *str) { panic_timeout = simple_strtoul(str, NULL, 0); return 1; } __setup("panic=", panic_setup); static long no_blink(long time) { return 0; } /* Returns how long it waited in ms */ long (*panic_blink)(long time); EXPORT_SYMBOL(panic_blink); /** * panic - halt the system * @fmt: The text string to print * * Display a message, then perform cleanups. * * This function never returns. */ NORET_TYPE void panic(const char * fmt, ...) { long i; static char buf[1024]; va_list args; #if defined(CONFIG_S390) unsigned long caller = (unsigned long) __builtin_return_address(0); #endif /* * It's possible to come here directly from a panic-assertion and not * have preempt disabled. Some functions called from here want * preempt to be disabled. No point enabling it later though... */ preempt_disable(); bust_spinlocks(1); va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf); do_dump(buf, NULL); bust_spinlocks(0); /* * If we have crashed and we have a crash kernel loaded let it handle * everything else. * Do we want to call this before we try to display a message? */ crash_kexec(NULL); #ifdef CONFIG_SMP /* * Note smp_send_stop is the usual smp shutdown function, which * unfortunately means it may not be hardened to work in a panic * situation. */ smp_send_stop(); #endif atomic_notifier_call_chain(&panic_notifier_list, 0, buf); if (!panic_blink) panic_blink = no_blink; if (panic_timeout > 0) { /* * Delay timeout seconds before rebooting the machine. * We can't use the "normal" timers since we just panicked.. */ printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout); for (i = 0; i < panic_timeout*1000; ) { touch_nmi_watchdog(); i += panic_blink(i); mdelay(1); i++; } /* This will not be a clean reboot, with everything * shutting down. But if there is a chance of * rebooting the system it will be rebooted. */ emergency_restart(); } #ifdef __sparc__ { extern int stop_a_enabled; /* Make sure the user can actually press Stop-A (L1-A) */ stop_a_enabled = 1; printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n"); } #endif #if defined(CONFIG_S390) disabled_wait(caller); #endif local_irq_enable(); for (i = 0;;) { touch_softlockup_watchdog(); i += panic_blink(i); mdelay(1); i++; } } EXPORT_SYMBOL(panic); /** * print_tainted - return a string to represent the kernel taint state. * * 'P' - Proprietary module has been loaded. * 'F' - Module has been forcibly loaded. * 'S' - SMP with CPUs not designed for SMP. * 'R' - User forced a module unload. * 'M' - Machine had a machine check experience. * 'B' - System has hit bad_page. * * The string is overwritten by the next call to print_taint(). */ const char *print_tainted(void) { static char buf[20]; if (tainted) { snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c", tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', tainted & TAINT_FORCED_MODULE ? 'F' : ' ', tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', tainted & TAINT_FORCED_RMMOD ? 'R' : ' ', tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', tainted & TAINT_BAD_PAGE ? 'B' : ' '); } else snprintf(buf, sizeof(buf), "Not tainted"); return(buf); } void add_taint(unsigned flag) { tainted |= flag; } EXPORT_SYMBOL(add_taint); static int __init pause_on_oops_setup(char *str) { pause_on_oops = simple_strtoul(str, NULL, 0); return 1; } __setup("pause_on_oops=", pause_on_oops_setup); static void spin_msec(int msecs) { int i; for (i = 0; i < msecs; i++) { touch_nmi_watchdog(); mdelay(1); } } /* * It just happens that oops_enter() and oops_exit() are identically * implemented... */ static void do_oops_enter_exit(void) { unsigned long flags; static int spin_counter; if (!pause_on_oops) return; spin_lock_irqsave(&pause_on_oops_lock, flags); if (pause_on_oops_flag == 0) { /* This CPU may now print the oops message */ pause_on_oops_flag = 1; } else { /* We need to stall this CPU */ if (!spin_counter) { /* This CPU gets to do the counting */ spin_counter = pause_on_oops; do { spin_unlock(&pause_on_oops_lock); spin_msec(MSEC_PER_SEC); spin_lock(&pause_on_oops_lock); } while (--spin_counter); pause_on_oops_flag = 0; } else { /* This CPU waits for a different one */ while (spin_counter) { spin_unlock(&pause_on_oops_lock); spin_msec(1); spin_lock(&pause_on_oops_lock); } } } spin_unlock_irqrestore(&pause_on_oops_lock, flags); } /* * Return true if the calling CPU is allowed to print oops-related info. This * is a bit racy.. */ int oops_may_print(void) { return pause_on_oops_flag == 0; } /* * Called when the architecture enters its oops handler, before it prints * anything. If this is the first CPU to oops, and it's oopsing the first time * then let it proceed. * * This is all enabled by the pause_on_oops kernel boot option. We do all this * to ensure that oopses don't scroll off the screen. It has the side-effect * of preventing later-oopsing CPUs from mucking up the display, too. * * It turns out that the CPU which is allowed to print ends up pausing for the * right duration, whereas all the other CPUs pause for twice as long: once in * oops_enter(), once in oops_exit(). */ void oops_enter(void) { do_oops_enter_exit(); } /* * Called when the architecture exits its oops handler, after printing * everything. */ void oops_exit(void) { do_oops_enter_exit(); } --- NEW FILE: Makefile --- # # Makefile for the linux kernel. # obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ exit.o itimer.o time.o softirq.o resource.o \ sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o pid.o \ rcupdate.o extable.o params.o posix-timers.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o obj-$(CONFIG_FUTEX) += futex.o ifeq ($(CONFIG_COMPAT),y) obj-$(CONFIG_FUTEX) += futex_compat.o endif obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += cpu.o spinlock.o obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_OBSOLETE_INTERMODULE) += intermodule.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += power/ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_CPUSETS) += cpuset.o obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_SYSFS) += ksysfs.o obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ obj-$(CONFIG_SECCOMP) += seccomp.o obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_DUMP_MKEXEC) += minik_dump_ex.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <al...@li...>, the -fno-omit-frame-pointer is # needed for x86 only. Why this used to be enabled for all architectures is beyond # me. I suspect most platforms don't need this, but until we know that for sure # I turn this off for IA-64 only. Andreas Schwab says it's also needed on m68k # to get a correct value for the wait-channel (WCHAN in ps). --davidm CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer endif $(obj)/configs.o: $(obj)/config_data.h # config_data.h contains the same information as ikconfig.h but gzipped. # Info from config_data can be extracted from /proc/config* targets += config_data.gz $(obj)/config_data.gz: .config FORCE $(call if_changed,gzip) quiet_cmd_ikconfiggz = IKCFG $@ cmd_ikconfiggz = (echo "static const char kernel_config_data[] = MAGIC_START"; cat $< | scripts/bin2c; echo "MAGIC_END;") > $@ targets += config_data.h $(obj)/config_data.h: $(obj)/config_data.gz FORCE $(call if_changed,ikconfiggz) |
From: Itsuro O. <od...@us...> - 2006-11-22 01:30:35
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include/asm-i386 In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv22290/include/asm-i386 Added Files: apic.h io_apic.h mkexec_export.h Log Message: support 2.6.17 (caution: only i386 done) --- NEW FILE: mkexec_export.h --- /* * include/asm-i386/mkexec_export.h * * $Id: mkexec_export.h,v 1.1 2006/11/22 01:30:32 odaodab Exp $ * * Portions Copyright (C) 2004 NTT DATA CORPORATION. * Portions Copyright (C) 2004 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation (version 2 of the License). * * Mkdump is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ASM_MKEXEC_EXPORT_H_ #define _ASM_MKEXEC_EXPORT_H_ #ifdef CONFIG_DUMP_MKEXEC struct crashmem { unsigned long base_pa; unsigned long size_bytes; }; /* Save the state of all the other CPUs. */ void mkdump_send_nmi(void); #endif /* CONFIG_DUMP_MKEXEC */ #endif /* _ASM_MKEXEC_EXPORT_H_ */ --- NEW FILE: io_apic.h --- #ifndef __ASM_IO_APIC_H #define __ASM_IO_APIC_H #include <linux/config.h> #include <linux/spinlock.h> #include <asm/types.h> #include <asm/mpspec.h> /* * Intel IO-APIC support for SMP and UP systems. * * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar */ #ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_PCI_MSI static inline int use_pci_vector(void) {return 1;} static inline void disable_edge_ioapic_vector(unsigned int vector) { } static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { } static inline void end_edge_ioapic_vector (unsigned int vector) { } #define startup_level_ioapic startup_level_ioapic_vector #define shutdown_level_ioapic mask_IO_APIC_vector #define enable_level_ioapic unmask_IO_APIC_vector #define disable_level_ioapic mask_IO_APIC_vector #define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_vector #define end_level_ioapic end_level_ioapic_vector #define set_ioapic_affinity set_ioapic_affinity_vector #define startup_edge_ioapic startup_edge_ioapic_vector #define shutdown_edge_ioapic disable_edge_ioapic_vector #define enable_edge_ioapic unmask_IO_APIC_vector #define disable_edge_ioapic disable_edge_ioapic_vector #define ack_edge_ioapic ack_edge_ioapic_vector #define end_edge_ioapic end_edge_ioapic_vector #else static inline int use_pci_vector(void) {return 0;} static inline void disable_edge_ioapic_irq(unsigned int irq) { } static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { } static inline void end_edge_ioapic_irq (unsigned int irq) { } #define startup_level_ioapic startup_level_ioapic_irq #define shutdown_level_ioapic mask_IO_APIC_irq #define enable_level_ioapic unmask_IO_APIC_irq #define disable_level_ioapic mask_IO_APIC_irq #define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq #define end_level_ioapic end_level_ioapic_irq #define set_ioapic_affinity set_ioapic_affinity_irq #define startup_edge_ioapic startup_edge_ioapic_irq #define shutdown_edge_ioapic disable_edge_ioapic_irq #define enable_edge_ioapic unmask_IO_APIC_irq #define disable_edge_ioapic disable_edge_ioapic_irq #define ack_edge_ioapic ack_edge_ioapic_irq #define end_edge_ioapic end_edge_ioapic_irq #endif #define IO_APIC_BASE(idx) \ ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \ + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK))) /* * The structure of the IO-APIC: */ union IO_APIC_reg_00 { u32 raw; struct { u32 __reserved_2 : 14, LTS : 1, delivery_type : 1, __reserved_1 : 8, ID : 8; } __attribute__ ((packed)) bits; }; union IO_APIC_reg_01 { u32 raw; struct { u32 version : 8, __reserved_2 : 7, PRQ : 1, entries : 8, __reserved_1 : 8; } __attribute__ ((packed)) bits; }; union IO_APIC_reg_02 { u32 raw; struct { u32 __reserved_2 : 24, arbitration : 4, __reserved_1 : 4; } __attribute__ ((packed)) bits; }; union IO_APIC_reg_03 { u32 raw; struct { u32 boot_DT : 1, __reserved_1 : 31; } __attribute__ ((packed)) bits; }; /* * # of IO-APICs and # of IRQ routing registers */ extern int nr_ioapics; extern int nr_ioapic_registers[MAX_IO_APICS]; enum ioapic_irq_destination_types { dest_Fixed = 0, dest_LowestPrio = 1, dest_SMI = 2, dest__reserved_1 = 3, dest_NMI = 4, dest_INIT = 5, dest__reserved_2 = 6, dest_ExtINT = 7 }; struct IO_APIC_route_entry { __u32 vector : 8, delivery_mode : 3, /* 000: FIXED * 001: lowest prio * 111: ExtINT */ dest_mode : 1, /* 0: physical, 1: logical */ delivery_status : 1, polarity : 1, irr : 1, trigger : 1, /* 0: edge, 1: level */ mask : 1, /* 0: enabled, 1: disabled */ __reserved_2 : 15; union { struct { __u32 __reserved_1 : 24, physical_dest : 4, __reserved_2 : 4; } physical; struct { __u32 __reserved_1 : 24, logical_dest : 8; } logical; } dest; } __attribute__ ((packed)); /* * MP-BIOS irq configuration table structures: */ /* I/O APIC entries */ extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; /* # of MP IRQ source entries */ extern int mp_irq_entries; /* MP IRQ source entries */ extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* non-0 if default (table-less) MP configuration */ extern int mpc_default_type; static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) { *IO_APIC_BASE(apic) = reg; return *(IO_APIC_BASE(apic)+4); } static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) { *IO_APIC_BASE(apic) = reg; *(IO_APIC_BASE(apic)+4) = value; } /* * Re-write a value: to be used for read-modify-write * cycles where the read already set up the index register. * * Older SiS APIC requires we rewrite the index regiser */ extern int sis_apic_bug; static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) { if (sis_apic_bug) *IO_APIC_BASE(apic) = reg; *(IO_APIC_BASE(apic)+4) = value; } /* 1 if "noapic" boot option passed */ extern int skip_ioapic_setup; /* * If we use the IO-APIC for IRQ routing, disable automatic * assignment of PCI IRQ's. */ #define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs) #ifdef CONFIG_ACPI extern int io_apic_get_unique_id (int ioapic, int apic_id); extern int io_apic_get_version (int ioapic); extern int io_apic_get_redir_entries (int ioapic); extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low); extern int timer_uses_ioapic_pin_0; #endif /* CONFIG_ACPI */ extern int (*ioapic_renumber_irq)(int ioapic, int irq); #else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 #endif extern int assign_irq_vector(int irq); extern int ioapic_mkexec_restore(void); extern spinlock_t ioapic_lock; #endif --- NEW FILE: apic.h --- #ifndef __ASM_APIC_H #define __ASM_APIC_H #include <linux/config.h> #include <linux/pm.h> #include <asm/fixmap.h> #include <asm/apicdef.h> #include <asm/processor.h> #include <asm/system.h> #define Dprintk(x...) /* * Debugging macros */ #define APIC_QUIET 0 #define APIC_VERBOSE 1 #define APIC_DEBUG 2 extern int enable_local_apic; extern int apic_verbosity; static inline void lapic_disable(void) { enable_local_apic = -1; clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); } static inline void lapic_enable(void) { enable_local_apic = 1; } /* * Define the default level of output to be very little * This can be turned up by using apic=verbose for more * information and apic=debug for _lots_ of information. * apic_verbosity is defined in apic.c */ #define apic_printk(v, s, a...) do { \ if ((v) <= apic_verbosity) \ printk(s, ##a); \ } while (0) #ifdef CONFIG_X86_LOCAL_APIC /* * Basic functions accessing APICs. */ static __inline void apic_write(unsigned long reg, unsigned long v) { *((volatile unsigned long *)(APIC_BASE+reg)) = v; } static __inline void apic_write_atomic(unsigned long reg, unsigned long v) { xchg((volatile unsigned long *)(APIC_BASE+reg), v); } static __inline unsigned long apic_read(unsigned long reg) { return *((volatile unsigned long *)(APIC_BASE+reg)); } static __inline__ void apic_wait_icr_idle(void) { while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY ) cpu_relax(); } int get_physical_broadcast(void); #ifdef CONFIG_X86_GOOD_APIC # define FORCE_READ_AROUND_WRITE 0 # define apic_read_around(x) # define apic_write_around(x,y) apic_write((x),(y)) #else # define FORCE_READ_AROUND_WRITE 1 # define apic_read_around(x) apic_read(x) # define apic_write_around(x,y) apic_write_atomic((x),(y)) #endif static inline void ack_APIC_irq(void) { /* * ack_APIC_irq() actually gets compiled as a single instruction: * - a single rmw on Pentium/82489DX * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC) * ... yummie. */ /* Docs say use 0 for future compatibility */ apic_write_around(APIC_EOI, 0); } extern void (*wait_timer_tick)(void); extern int get_maxlvt(void); extern void clear_local_APIC(void); extern void connect_bsp_APIC (void); extern void disconnect_bsp_APIC (int virt_wire_setup); extern void disable_local_APIC (void); extern void lapic_shutdown (void); extern int verify_local_APIC (void); extern void cache_APIC_registers (void); extern void sync_Arb_IDs (void); extern void init_bsp_APIC (void); extern void setup_local_APIC (void); extern void init_apic_mappings (void); extern void smp_local_timer_interrupt (struct pt_regs * regs); extern void setup_boot_APIC_clock (void); extern void setup_secondary_APIC_clock (void); extern void setup_apic_nmi_watchdog (void); extern int reserve_lapic_nmi(void); extern void release_lapic_nmi(void); extern void disable_timer_nmi_watchdog(void); extern void enable_timer_nmi_watchdog(void); extern void nmi_watchdog_tick (struct pt_regs * regs); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); extern int lapic_mkexec_restore(void); extern void enable_NMI_through_LVT0 (void * dummy); extern unsigned int nmi_watchdog; #define NMI_NONE 0 #define NMI_IO_APIC 1 #define NMI_LOCAL_APIC 2 #define NMI_INVALID 3 extern int disable_timer_pin_1; void smp_send_timer_broadcast_ipi(struct pt_regs *regs); void switch_APIC_timer_to_ipi(void *cpumask); void switch_ipi_to_APIC_timer(void *cpumask); #define ARCH_APICTIMER_STOPS_ON_C3 1 extern int timer_over_8254; extern int modern_apic(void); #else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown(void) { } static inline int lapic_mkexec_restore(void) { return 0; } #endif /* !CONFIG_X86_LOCAL_APIC */ #endif /* __ASM_APIC_H */ |
From: Itsuro O. <od...@us...> - 2006-11-22 01:30:35
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/drivers/char In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv22290/drivers/char Added Files: sysrq.c Log Message: support 2.6.17 (caution: only i386 done) --- NEW FILE: sysrq.c --- /* -*- linux-c -*- * * $Id: sysrq.c,v 1.1 2006/11/22 01:30:32 odaodab Exp $ * * Linux Magic System Request Key Hacks * * (c) 1997 Martin Mares <mj...@at...> * based on ideas by Pavel Machek <pa...@at...> * * (c) 2000 Crutcher Dunnavant <cru...@da...> * overhauled to use key registration * based upon discusions in irc://irc.openprojects.net/#kernelnewbies */ #include <linux/config.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/tty.h> #include <linux/mount.h> #include <linux/kdev_t.h> #include <linux/major.h> #include <linux/reboot.h> #include <linux/sysrq.h> #include <linux/kbd_kern.h> #include <linux/quotaops.h> #include <linux/smp_lock.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/suspend.h> #include <linux/writeback.h> #include <linux/buffer_head.h> /* for fsync_bdev() */ #include <linux/swap.h> #include <linux/spinlock.h> #include <linux/vt_kern.h> #include <linux/workqueue.h> #include <linux/kexec.h> #include <asm/ptrace.h> /* Whether we react on sysrq keys or just ignore them */ int sysrq_enabled = 1; static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { int i; i = key - '0'; console_loglevel = 7; printk("Loglevel set to %d\n", i); console_loglevel = i; } static struct sysrq_key_op sysrq_loglevel_op = { .handler = sysrq_handle_loglevel, .help_msg = "loglevel0-8", .action_msg = "Changing Loglevel", .enable_mask = SYSRQ_ENABLE_LOG, }; #ifdef CONFIG_VT static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { if (tty) do_SAK(tty); reset_vc(vc_cons[fg_console].d); } static struct sysrq_key_op sysrq_SAK_op = { .handler = sysrq_handle_SAK, .help_msg = "saK", .action_msg = "SAK", .enable_mask = SYSRQ_ENABLE_KEYBOARD, }; #else #define sysrq_SAK_op (*(struct sysrq_key_op *)0) #endif #ifdef CONFIG_VT static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { struct kbd_struct *kbd = &kbd_table[fg_console]; if (kbd) kbd->kbdmode = VC_XLATE; } static struct sysrq_key_op sysrq_unraw_op = { .handler = sysrq_handle_unraw, .help_msg = "unRaw", .action_msg = "Keyboard mode set to XLATE", .enable_mask = SYSRQ_ENABLE_KEYBOARD, }; #else #define sysrq_unraw_op (*(struct sysrq_key_op *)0) #endif /* CONFIG_VT */ #ifdef CONFIG_KEXEC || CONFIG_DUMP_MKEXEC static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { do_dump("Sysrq", pt_regs); crash_kexec(pt_regs); } static struct sysrq_key_op sysrq_crashdump_op = { .handler = sysrq_handle_crashdump, .help_msg = "Crashdump", .action_msg = "Trigger a crashdump", .enable_mask = SYSRQ_ENABLE_DUMP, }; #else #define sysrq_crashdump_op (*(struct sysrq_key_op *)0) #endif static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { local_irq_enable(); emergency_restart(); } static struct sysrq_key_op sysrq_reboot_op = { .handler = sysrq_handle_reboot, .help_msg = "reBoot", .action_msg = "Resetting", .enable_mask = SYSRQ_ENABLE_BOOT, }; static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { emergency_sync(); } static struct sysrq_key_op sysrq_sync_op = { .handler = sysrq_handle_sync, .help_msg = "Sync", .action_msg = "Emergency Sync", .enable_mask = SYSRQ_ENABLE_SYNC, }; static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { emergency_remount(); } static struct sysrq_key_op sysrq_mountro_op = { .handler = sysrq_handle_mountro, .help_msg = "Unmount", .action_msg = "Emergency Remount R/O", .enable_mask = SYSRQ_ENABLE_REMOUNT, }; #ifdef CONFIG_DEBUG_MUTEXES static void sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { mutex_debug_show_all_locks(); } static struct sysrq_key_op sysrq_showlocks_op = { .handler = sysrq_handle_showlocks, .help_msg = "show-all-locks(D)", .action_msg = "Show Locks Held", }; #else #define sysrq_showlocks_op (*(struct sysrq_key_op *)0) #endif static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { if (pt_regs) show_regs(pt_regs); } static struct sysrq_key_op sysrq_showregs_op = { .handler = sysrq_handle_showregs, .help_msg = "showPc", .action_msg = "Show Regs", .enable_mask = SYSRQ_ENABLE_DUMP, }; static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { show_state(); } static struct sysrq_key_op sysrq_showstate_op = { .handler = sysrq_handle_showstate, .help_msg = "showTasks", .action_msg = "Show State", .enable_mask = SYSRQ_ENABLE_DUMP, }; static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { show_mem(); } static struct sysrq_key_op sysrq_showmem_op = { .handler = sysrq_handle_showmem, .help_msg = "showMem", .action_msg = "Show Memory", .enable_mask = SYSRQ_ENABLE_DUMP, }; /* * Signal sysrq helper function. Sends a signal to all user processes. */ static void send_sig_all(int sig) { struct task_struct *p; for_each_process(p) { if (p->mm && p->pid != 1) /* Not swapper, init nor kernel thread */ force_sig(sig, p); } } static void sysrq_handle_term(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { send_sig_all(SIGTERM); console_loglevel = 8; } static struct sysrq_key_op sysrq_term_op = { .handler = sysrq_handle_term, .help_msg = "tErm", .action_msg = "Terminate All Tasks", .enable_mask = SYSRQ_ENABLE_SIGNAL, }; static void moom_callback(void *ignored) { out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0); } static DECLARE_WORK(moom_work, moom_callback, NULL); static void sysrq_handle_moom(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { schedule_work(&moom_work); } static struct sysrq_key_op sysrq_moom_op = { .handler = sysrq_handle_moom, .help_msg = "Full", .action_msg = "Manual OOM execution", }; static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { send_sig_all(SIGKILL); console_loglevel = 8; } static struct sysrq_key_op sysrq_kill_op = { .handler = sysrq_handle_kill, .help_msg = "kIll", .action_msg = "Kill All Tasks", .enable_mask = SYSRQ_ENABLE_SIGNAL, }; static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { normalize_rt_tasks(); } static struct sysrq_key_op sysrq_unrt_op = { .handler = sysrq_handle_unrt, .help_msg = "Nice", .action_msg = "Nice All RT Tasks", .enable_mask = SYSRQ_ENABLE_RTNICE, }; /* Key Operations table and lock */ static DEFINE_SPINLOCK(sysrq_key_table_lock); static struct sysrq_key_op *sysrq_key_table[36] = { &sysrq_loglevel_op, /* 0 */ &sysrq_loglevel_op, /* 1 */ &sysrq_loglevel_op, /* 2 */ &sysrq_loglevel_op, /* 3 */ &sysrq_loglevel_op, /* 4 */ &sysrq_loglevel_op, /* 5 */ &sysrq_loglevel_op, /* 6 */ &sysrq_loglevel_op, /* 7 */ &sysrq_loglevel_op, /* 8 */ &sysrq_loglevel_op, /* 9 */ /* * Don't use for system provided sysrqs, it is handled specially on * sparc and will never arrive */ NULL, /* a */ &sysrq_reboot_op, /* b */ &sysrq_crashdump_op, /* c */ &sysrq_showlocks_op, /* d */ &sysrq_term_op, /* e */ &sysrq_moom_op, /* f */ NULL, /* g */ NULL, /* h */ &sysrq_kill_op, /* i */ NULL, /* j */ &sysrq_SAK_op, /* k */ NULL, /* l */ &sysrq_showmem_op, /* m */ &sysrq_unrt_op, /* n */ /* This will often be registered as 'Off' at init time */ NULL, /* o */ &sysrq_showregs_op, /* p */ NULL, /* q */ &sysrq_unraw_op, /* r */ &sysrq_sync_op, /* s */ &sysrq_showstate_op, /* t */ &sysrq_mountro_op, /* u */ /* May be assigned at init time by SMP VOYAGER */ NULL, /* v */ NULL, /* w */ NULL, /* x */ NULL, /* y */ NULL /* z */ }; /* key2index calculation, -1 on invalid index */ static int sysrq_key_table_key2index(int key) { int retval; if ((key >= '0') && (key <= '9')) retval = key - '0'; else if ((key >= 'a') && (key <= 'z')) retval = key + 10 - 'a'; else retval = -1; return retval; } /* * get and put functions for the table, exposed to modules. */ struct sysrq_key_op *__sysrq_get_key_op(int key) { struct sysrq_key_op *op_p = NULL; int i; i = sysrq_key_table_key2index(key); if (i != -1) op_p = sysrq_key_table[i]; return op_p; } static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p) { int i = sysrq_key_table_key2index(key); if (i != -1) sysrq_key_table[i] = op_p; } /* * This is the non-locking version of handle_sysrq. It must/can only be called * by sysrq key handlers, as they are inside of the lock */ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask) { struct sysrq_key_op *op_p; int orig_log_level; int i; unsigned long flags; spin_lock_irqsave(&sysrq_key_table_lock, flags); orig_log_level = console_loglevel; console_loglevel = 7; printk(KERN_INFO "SysRq : "); op_p = __sysrq_get_key_op(key); if (op_p) { /* * Should we check for enabled operations (/proc/sysrq-trigger * should not) and is the invoked operation enabled? */ if (!check_mask || sysrq_enabled == 1 || (sysrq_enabled & op_p->enable_mask)) { printk("%s\n", op_p->action_msg); console_loglevel = orig_log_level; op_p->handler(key, pt_regs, tty); } else { printk("This sysrq operation is disabled.\n"); } } else { printk("HELP : "); /* Only print the help msg once per handler */ for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) { if (sysrq_key_table[i]) { int j; for (j = 0; sysrq_key_table[i] != sysrq_key_table[j]; j++) ; if (j != i) continue; printk("%s ", sysrq_key_table[i]->help_msg); } } printk("\n"); console_loglevel = orig_log_level; } spin_unlock_irqrestore(&sysrq_key_table_lock, flags); } /* * This function is called by the keyboard handler when SysRq is pressed * and any other keycode arrives. */ void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { if (!sysrq_enabled) return; __handle_sysrq(key, pt_regs, tty, 1); } EXPORT_SYMBOL(handle_sysrq); static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, struct sysrq_key_op *remove_op_p) { int retval; unsigned long flags; spin_lock_irqsave(&sysrq_key_table_lock, flags); if (__sysrq_get_key_op(key) == remove_op_p) { __sysrq_put_key_op(key, insert_op_p); retval = 0; } else { retval = -1; } spin_unlock_irqrestore(&sysrq_key_table_lock, flags); return retval; } int register_sysrq_key(int key, struct sysrq_key_op *op_p) { return __sysrq_swap_key_ops(key, op_p, NULL); } EXPORT_SYMBOL(register_sysrq_key); int unregister_sysrq_key(int key, struct sysrq_key_op *op_p) { return __sysrq_swap_key_ops(key, NULL, op_p); } EXPORT_SYMBOL(unregister_sysrq_key); |
From: Itsuro O. <od...@us...> - 2006-11-22 01:30:35
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386/mm In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv22290/arch/i386/mm Added Files: fault.c Log Message: support 2.6.17 (caution: only i386 done) --- NEW FILE: fault.c --- /* * linux/arch/i386/mm/fault.c * * Copyright (C) 1995 Linus Torvalds */ #include <linux/signal.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/types.h> #include <linux/ptrace.h> #include <linux/mman.h> #include <linux/mm.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/tty.h> #include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/highmem.h> #include <linux/module.h> #include <linux/kprobes.h> #include <asm/system.h> #include <asm/uaccess.h> #include <asm/desc.h> #include <asm/kdebug.h> extern void die(const char *,struct pt_regs *,long); /* * Unlock any spinlocks which will prevent us from getting the * message out */ void bust_spinlocks(int yes) { int loglevel_save = console_loglevel; if (yes) { oops_in_progress = 1; return; } #ifdef CONFIG_VT unblank_screen(); #endif oops_in_progress = 0; /* * OK, the message is on the console. Now we call printk() * without oops_in_progress set so that printk will give klogd * a poke. Hold onto your hats... */ console_loglevel = 15; /* NMI oopser may have shut the console up */ printk(" "); console_loglevel = loglevel_save; } /* * Return EIP plus the CS segment base. The segment limit is also * adjusted, clamped to the kernel/user address space (whichever is * appropriate), and returned in *eip_limit. * * The segment is checked, because it might have been changed by another * task between the original faulting instruction and here. * * If CS is no longer a valid code segment, or if EIP is beyond the * limit, or if it is a kernel address when CS is not a kernel segment, * then the returned value will be greater than *eip_limit. * * This is slow, but is very rarely executed. */ static inline unsigned long get_segment_eip(struct pt_regs *regs, unsigned long *eip_limit) { unsigned long eip = regs->eip; unsigned seg = regs->xcs & 0xffff; u32 seg_ar, seg_limit, base, *desc; /* The standard kernel/user address space limit. */ *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg; /* Unlikely, but must come before segment checks. */ if (unlikely((regs->eflags & VM_MASK) != 0)) return eip + (seg << 4); /* By far the most common cases. */ if (likely(seg == __USER_CS || seg == __KERNEL_CS)) return eip; /* Check the segment exists, is within the current LDT/GDT size, that kernel/user (ring 0..3) has the appropriate privilege, that it's a code segment, and get the limit. */ __asm__ ("larl %3,%0; lsll %3,%1" : "=&r" (seg_ar), "=r" (seg_limit) : "0" (0), "rm" (seg)); if ((~seg_ar & 0x9800) || eip > seg_limit) { *eip_limit = 0; return 1; /* So that returned eip > *eip_limit. */ } /* Get the GDT/LDT descriptor base. When you look for races in this code remember that LDT and other horrors are only used in user space. */ if (seg & (1<<2)) { /* Must lock the LDT while reading it. */ down(¤t->mm->context.sem); desc = current->mm->context.ldt; desc = (void *)desc + (seg & ~7); } else { /* Must disable preemption while reading the GDT. */ desc = (u32 *)get_cpu_gdt_table(get_cpu()); desc = (void *)desc + (seg & ~7); } /* Decode the code segment base from the descriptor */ base = get_desc_base((unsigned long *)desc); if (seg & (1<<2)) { up(¤t->mm->context.sem); } else put_cpu(); /* Adjust EIP and segment limit, and clamp at the kernel limit. It's legitimate for segments to wrap at 0xffffffff. */ seg_limit += base; if (seg_limit < *eip_limit && seg_limit >= base) *eip_limit = seg_limit; return eip + base; } /* * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch. * Check that here and ignore it. */ static int __is_prefetch(struct pt_regs *regs, unsigned long addr) { unsigned long limit; unsigned long instr = get_segment_eip (regs, &limit); int scan_more = 1; int prefetch = 0; int i; for (i = 0; scan_more && i < 15; i++) { unsigned char opcode; unsigned char instr_hi; unsigned char instr_lo; if (instr > limit) break; if (__get_user(opcode, (unsigned char __user *) instr)) break; instr_hi = opcode & 0xf0; instr_lo = opcode & 0x0f; instr++; switch (instr_hi) { case 0x20: case 0x30: /* Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes. */ scan_more = ((instr_lo & 7) == 0x6); break; case 0x60: /* 0x64 thru 0x67 are valid prefixes in all modes. */ scan_more = (instr_lo & 0xC) == 0x4; break; case 0xF0: /* 0xF0, 0xF2, and 0xF3 are valid prefixes */ scan_more = !instr_lo || (instr_lo>>1) == 1; break; case 0x00: /* Prefetch instruction is 0x0F0D or 0x0F18 */ scan_more = 0; if (instr > limit) break; if (__get_user(opcode, (unsigned char __user *) instr)) break; prefetch = (instr_lo == 0xF) && (opcode == 0x0D || opcode == 0x18); break; default: scan_more = 0; break; } } return prefetch; } static inline int is_prefetch(struct pt_regs *regs, unsigned long addr, unsigned long error_code) { if (unlikely(boot_cpu_data.x86_vendor == X86_VENDOR_AMD && boot_cpu_data.x86 >= 6)) { /* Catch an obscure case of prefetch inside an NX page. */ if (nx_enabled && (error_code & 16)) return 0; return __is_prefetch(regs, addr); } return 0; } static noinline void force_sig_info_fault(int si_signo, int si_code, unsigned long address, struct task_struct *tsk) { siginfo_t info; info.si_signo = si_signo; info.si_errno = 0; info.si_code = si_code; info.si_addr = (void __user *)address; force_sig_info(si_signo, &info, tsk); } fastcall void do_invalid_op(struct pt_regs *, unsigned long); static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) { unsigned index = pgd_index(address); pgd_t *pgd_k; pud_t *pud, *pud_k; pmd_t *pmd, *pmd_k; pgd += index; pgd_k = init_mm.pgd + index; if (!pgd_present(*pgd_k)) return NULL; /* * set_pgd(pgd, *pgd_k); here would be useless on PAE * and redundant with the set_pmd() on non-PAE. As would * set_pud. */ pud = pud_offset(pgd, address); pud_k = pud_offset(pgd_k, address); if (!pud_present(*pud_k)) return NULL; pmd = pmd_offset(pud, address); pmd_k = pmd_offset(pud_k, address); if (!pmd_present(*pmd_k)) return NULL; if (!pmd_present(*pmd)) set_pmd(pmd, *pmd_k); else BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); return pmd_k; } /* * Handle a fault on the vmalloc or module mapping area * * This assumes no large pages in there. */ static inline int vmalloc_fault(unsigned long address) { unsigned long pgd_paddr; pmd_t *pmd_k; pte_t *pte_k; /* * Synchronize this task's top level page-table * with the 'reference' page table. * * Do _not_ use "current" here. We might be inside * an interrupt in the middle of a task switch.. */ pgd_paddr = read_cr3(); pmd_k = vmalloc_sync_one(__va(pgd_paddr), address); if (!pmd_k) return -1; pte_k = pte_offset_kernel(pmd_k, address); if (!pte_present(*pte_k)) return -1; return 0; } /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. * * error_code: * bit 0 == 0 means no page found, 1 means protection fault * bit 1 == 0 means read, 1 means write * bit 2 == 0 means kernel, 1 means user-mode * bit 3 == 1 means use of reserved bit detected * bit 4 == 1 means fault was an instruction fetch */ fastcall void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long address; unsigned long page; int write, si_code; /* get the address */ address = read_cr2(); tsk = current; /* We may have invalid '*current' due to a i386 stack overflow. */ if (!virt_addr_valid(tsk)) { printk("do_page_fault: Discarding invalid 'current' struct task_struct * = 0x%p\n", tsk); tsk = NULL; } si_code = SEGV_MAPERR; /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. * * NOTE! We MUST NOT take any locks for this case. We may * be in an interrupt or a critical region, and should * only copy the information from the master page table, * nothing more. * * This verifies that the fault happens in kernel space * (error_code & 4) == 0, and that the fault was not a * protection error (error_code & 9) == 0. */ if (unlikely(address >= TASK_SIZE)) { if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) return; if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, SIGSEGV) == NOTIFY_STOP) return; /* * Don't take the mm semaphore here. If we fixup a prefetch * fault we could otherwise deadlock. */ goto bad_area_nosemaphore; } if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, SIGSEGV) == NOTIFY_STOP) return; /* It's safe to allow irq's after cr2 has been saved and the vmalloc fault has been handled. */ if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) local_irq_enable(); if (tsk) mm = tsk->mm; if (mm && !virt_addr_valid(mm)) { printk("do_page_fault: Discarding invalid current->mm struct mm_struct * = 0x%p\n", mm); mm = NULL; } /* * If we're in an interrupt, have no user context or are running in an * atomic region then we must not take the fault.. */ if (in_atomic() || !mm) goto bad_area_nosemaphore; /* When running in the kernel we expect faults to occur only to * addresses in user space. All other faults represent errors in the * kernel and should generate an OOPS. Unfortunatly, in the case of an * erroneous fault occuring in a code path which already holds mmap_sem * we will deadlock attempting to validate the fault against the * address space. Luckily the kernel only validly references user * space from well defined areas of code, which are listed in the * exceptions table. * * As the vast majority of faults will be valid we will only perform * the source reference check when there is a possibilty of a deadlock. * Attempt to lock the address space, if we cannot we then validate the * source. If this is invalid we can skip the address space check, * thus avoiding the deadlock. */ if (!down_read_trylock(&mm->mmap_sem)) { if ((error_code & 4) == 0 && !search_exception_tables(regs->eip)) goto bad_area_nosemaphore; down_read(&mm->mmap_sem); } vma = find_vma(mm, address); if (!vma) goto bad_area; if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; if (error_code & 4) { /* * accessing the stack below %esp is always a bug. * The "+ 32" is there due to some instructions (like * pusha) doing post-decrement on the stack and that * doesn't show up until later.. */ if (address + 32 < regs->esp) goto bad_area; } if (expand_stack(vma, address)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: si_code = SEGV_ACCERR; write = 0; switch (error_code & 3) { default: /* 3: write, present */ #ifdef TEST_VERIFY_AREA if (regs->cs == KERNEL_CS) printk("WP fault at %08lx\n", regs->eip); #endif /* fall through */ case 2: /* write, not present */ if (!(vma->vm_flags & VM_WRITE)) goto bad_area; write++; break; case 1: /* read, present */ goto bad_area; case 0: /* read, not present */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. */ switch (handle_mm_fault(mm, vma, address, write)) { case VM_FAULT_MINOR: tsk->min_flt++; break; case VM_FAULT_MAJOR: tsk->maj_flt++; break; case VM_FAULT_SIGBUS: goto do_sigbus; case VM_FAULT_OOM: goto out_of_memory; default: BUG(); } /* * Did it hit the DOS screen memory VA from vm86 mode? */ if (regs->eflags & VM_MASK) { unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT; if (bit < 32) tsk->thread.screen_bitmap |= 1 << bit; } up_read(&mm->mmap_sem); return; /* * Something tried to access memory that isn't in our memory map.. * Fix it, but check if it's kernel or user first.. */ bad_area: up_read(&mm->mmap_sem); bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { /* * Valid to do another page fault here because this one came * from user space. */ if (is_prefetch(regs, address, error_code)) return; tsk->thread.cr2 = address; /* Kernel addresses are always protection faults */ tsk->thread.error_code = error_code | (address >= TASK_SIZE); tsk->thread.trap_no = 14; force_sig_info_fault(SIGSEGV, si_code, address, tsk); return; } #ifdef CONFIG_X86_F00F_BUG /* * Pentium F0 0F C7 C8 bug workaround. */ if (boot_cpu_data.f00f_bug) { unsigned long nr; nr = (address - idt_descr.address) >> 3; if (nr == 6) { do_invalid_op(regs, 0); return; } } #endif no_context: /* Are we prepared to handle this kernel fault? */ if (fixup_exception(regs)) return; /* * Valid to do another page fault here, because if this fault * had been triggered by is_prefetch fixup_exception would have * handled it. */ if (is_prefetch(regs, address, error_code)) return; /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ bust_spinlocks(1); if (oops_may_print()) { #ifdef CONFIG_X86_PAE if (error_code & 16) { pte_t *pte = lookup_address(address); if (pte && pte_present(*pte) && !pte_exec_kernel(*pte)) printk(KERN_CRIT "kernel tried to execute " "NX-protected page - exploit attempt? " "(uid: %d)\n", current->uid); } #endif if (address < PAGE_SIZE) printk(KERN_ALERT "BUG: unable to handle kernel NULL " "pointer dereference"); else printk(KERN_ALERT "BUG: unable to handle kernel paging" " request"); printk(" at virtual address %08lx\n",address); printk(KERN_ALERT " printing eip:\n"); printk("%08lx\n", regs->eip); } page = read_cr3(); page = ((unsigned long *) __va(page))[address >> 22]; if (oops_may_print()) printk(KERN_ALERT "*pde = %08lx\n", page); /* * We must not directly access the pte in the highpte * case, the page table might be allocated in highmem. * And lets rather not kmap-atomic the pte, just in case * it's allocated already. */ #ifndef CONFIG_HIGHPTE if ((page & 1) && oops_may_print()) { page &= PAGE_MASK; address &= 0x003ff000; page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; printk(KERN_ALERT "*pte = %08lx\n", page); } #endif tsk->thread.cr2 = address; tsk->thread.trap_no = 14; tsk->thread.error_code = error_code; die("Oops", regs, error_code); bust_spinlocks(0); do_exit(SIGKILL); /* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ out_of_memory: up_read(&mm->mmap_sem); if (tsk->pid == 1) { yield(); down_read(&mm->mmap_sem); goto survive; } printk("VM: killing process %s\n", tsk->comm); if (error_code & 4) do_exit(SIGKILL); goto no_context; do_sigbus: up_read(&mm->mmap_sem); /* Kernel mode? Handle exceptions or die */ if (!(error_code & 4)) goto no_context; /* User space => ok to do another page fault */ if (is_prefetch(regs, address, error_code)) return; tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk); } #ifndef CONFIG_X86_PAE void vmalloc_sync_all(void) { /* * Note that races in the updates of insync and start aren't * problematic: insync can only get set bits added, and updates to * start are only improving performance (without affecting correctness * if undone). */ static DECLARE_BITMAP(insync, PTRS_PER_PGD); static unsigned long start = TASK_SIZE; unsigned long address; BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK); for (address = start; address >= TASK_SIZE; address += PGDIR_SIZE) { if (!test_bit(pgd_index(address), insync)) { unsigned long flags; struct page *page; spin_lock_irqsave(&pgd_lock, flags); for (page = pgd_list; page; page = (struct page *)page->index) if (!vmalloc_sync_one(page_address(page), address)) { BUG_ON(page != pgd_list); break; } spin_unlock_irqrestore(&pgd_lock, flags); if (!page) set_bit(pgd_index(address), insync); } if (address == start && test_bit(pgd_index(address), insync)) start = address + PGDIR_SIZE; } } #endif |
From: Itsuro O. <od...@us...> - 2006-11-22 01:30:35
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv22290/arch/i386/kernel Added Files: Makefile apic.c doublefault.c io_apic.c irq.c minik_dump.c smp.c traps.c Log Message: support 2.6.17 (caution: only i386 done) --- NEW FILE: apic.c --- /* * Local APIC handling, local APIC timers * * (c) 1999, 2000 Ingo Molnar <mi...@re...> * * Fixes * Maciej W. Rozycki : Bits for genuine 82489DX APICs; * thanks to Eric Gilmore * and Rolf G. Tews * for testing these extensively. * Maciej W. Rozycki : Various updates and fixes. * Mikael Pettersson : Power Management for UP-APIC. * Pavel Machek and * Mikael Pettersson : PM converted to driver model. */ #include <linux/config.h> #include <linux/init.h> [...1375 lines suppressed...] * Hack: In case of kdump, after a crash, kernel might be booting * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid * might be zero if read from MP tables. Get it from LAPIC. */ #ifdef CONFIG_CRASH_DUMP boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); #endif phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); setup_local_APIC(); #ifdef CONFIG_X86_IO_APIC if (smp_found_config) if (!skip_ioapic_setup && nr_ioapics) setup_IO_APIC(); #endif setup_boot_APIC_clock(); return 0; } --- NEW FILE: Makefile --- # # Makefile for the linux kernel. # extra-y := head.o init_task.o vmlinux.lds obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ pci-dma.o i386_ksyms.o i387.o bootflag.o \ quirks.o i8237.o topology.o alternative.o obj-y += cpu/ obj-y += timers/ obj-y += acpi/ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o smpboot.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_MODULES) += module.o obj-y += sysenter.o vsyscall.o obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_HPET_TIMER) += time_hpet.o obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_DOUBLEFAULT) += doublefault.o obj-$(CONFIG_VM86) += vm86.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_DUMP_MKEXEC) += minik_dump.o EXTRA_AFLAGS := -traditional obj-$(CONFIG_SCx200) += scx200.o # vsyscall.o contains the vsyscall DSO images as __initdata. # We must build both images before we can assemble it. # Note: kbuild does not track this dependency due to usage of .incbin $(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so) targets += vsyscall-note.o vsyscall.lds # The DSO images are built using a special linker script. quiet_cmd_syscall = SYSCALL $@ cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \ -Wl,-T,$(filter-out FORCE,$^) -o $@ export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH) vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags) SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags) $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \ $(obj)/vsyscall-%.so: $(src)/vsyscall.lds \ $(obj)/vsyscall-%.o $(obj)/vsyscall-note.o FORCE $(call if_changed,syscall) # We also create a special relocatable object that should mirror the symbol # table and layout of the linked DSO. With ld -R we can then refer to # these symbols in the kernel code rather than hand-coded addresses. extra-y += vsyscall-syms.o $(obj)/built-in.o: $(obj)/vsyscall-syms.o $(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o SYSCFLAGS_vsyscall-syms.o = -r $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \ $(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE $(call if_changed,syscall) --- NEW FILE: traps.c --- /* * linux/arch/i386/traps.c * * Copyright (C) 1991, 1992 Linus Torvalds * * Pentium III FXSR, SSE support * Gareth Hughes <ga...@va...>, May 2000 */ /* * 'Traps.c' handles hardware traps and faults after we have saved some * state in 'asm.s'. */ #include <linux/config.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/timer.h> [...1180 lines suppressed...] set_in_cr4(X86_CR4_OSXMMEXCPT); printk("done.\n"); } set_system_gate(SYSCALL_VECTOR,&system_call); /* * Should be a barrier for any external CPU state. */ cpu_init(); trap_init_hook(); } static int __init kstack_setup(char *s) { kstack_depth_to_print = simple_strtoul(s, NULL, 0); return 1; } __setup("kstack=", kstack_setup); --- NEW FILE: io_apic.c --- /* * Intel IO-APIC support for multi-Pentium hosts. * * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo * * Many thanks to Stig Venaas for trying out countless experimental * patches and reporting/debugging problems patiently! * * (c) 1999, Multiple IO-APIC support, developed by * Ken-ichi Yaku <ya...@cs...> and * Hidemi Kishimoto <kis...@cs...>, * further tested and cleaned up by Zach Brown <za...@re...> * and Ingo Molnar <mi...@re...> * * Fixes * Maciej W. Rozycki : Bits for genuine 82489DX APICs; * thanks to Eric Gilmore * and Rolf G. Tews * for testing these extensively [...2719 lines suppressed...] apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry " "(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic, mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low); ioapic_register_intr(irq, entry.vector, edge_level); if (!ioapic && (irq < 16)) disable_8259A_irq(irq); spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS); spin_unlock_irqrestore(&ioapic_lock, flags); return 0; } #endif /* CONFIG_ACPI */ --- NEW FILE: minik_dump.c --- /* * arch/i386/kernel/minik_dump.c * * $Id: minik_dump.c,v 1.1 2006/11/22 01:30:31 odaodab Exp $ * * Portions Copyright (C) 2004 NTT DATA CORPORATION. * Portions Copyright (C) 2004 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation (version 2 of the License). * * Mkdump is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/config.h> #include <linux/stddef.h> #include <linux/mm.h> #include <linux/swap.h> #include <linux/interrupt.h> #include <linux/pagemap.h> #include <linux/bootmem.h> #include <linux/compiler.h> #include <linux/module.h> #include <linux/suspend.h> #include <linux/pagevec.h> #include <linux/blkdev.h> #include <linux/slab.h> #include <linux/notifier.h> #include <linux/topology.h> #include <linux/sysctl.h> #include <linux/cpu.h> #include <linux/kernel.h> #include <linux/sort.h> #include <asm/e820.h> #include <asm/apic.h> #include <asm/io_apic.h> #include <asm/setup.h> #include <asm/mkexec_export.h> /* Prevent parameters to be called "minik_dump_i386_ex.crashmem" etc. */ #undef MODULE_PARAM_PREFIX #define MODULE_PARAM_PREFIX "" struct crashmem *crashmem_dma, *crashmem_main; struct crashmem *crashmem_get(int isdma) { return isdma ? crashmem_dma : crashmem_main; } EXPORT_SYMBOL(crashmem_get); static void __init crashmem_free(struct crashmem *crashmem) { if (!crashmem) return; if (crashmem->base_pa) free_bootmem(crashmem->base_pa, crashmem->size_bytes); free_bootmem(__pa(crashmem),sizeof(*crashmem)); } /* Allocated one memory type for minik. */ static int __init crashmem_set(const char *val_stringc, struct kernel_param *kp) { struct crashmem **crashmem_pointer = kp->arg; struct crashmem *crashmem; unsigned long long val_ull; unsigned long val_ul; char *val_string = (char *)val_stringc; const char *name = kp->name; void *base_va; int is_dma = (crashmem_pointer == &crashmem_dma); val_ull = memparse(val_string, &val_string); if (!val_ull || !val_string || *val_string || val_ull != (val_ul=val_ull)) { printk("mkexec: Error parsing '%s' memory size: %s\n", name, val_stringc); return 0; } val_ul = PFN_UP(val_ul) << PAGE_SHIFT; crashmem_free(*crashmem_pointer); *crashmem_pointer = NULL; crashmem = alloc_bootmem_low(sizeof(*crashmem)); if (!crashmem) { printk("mkexec: Error allocating memory!\n"); return 0; } crashmem->base_pa = 0; /* '0x400000' to get PSE targettable pages to prevent their split for R/O settings. * Current 'PMD_SIZE' may be just 2MB if PAE. */ base_va = __alloc_bootmem(val_ul, 0x400000, (is_dma ? 0 : __pa(MAX_DMA_ADDRESS))); if (!base_va) { printk("mkexec: Error allocating chunk of 0x%lx bytes of memory %s!\n", val_ul, name); crashmem_free(crashmem); return 0; } crashmem->base_pa = __pa(base_va); crashmem->size_bytes = val_ul; *crashmem_pointer = crashmem; printk("mkexec: Allocated 0x%lx of %s memory @0x%lx\n", val_ul, name, crashmem->base_pa); return 0; } /* FIXME: Make it readable/writable by: driverfs */ module_param_call(crashdma, crashmem_set, NULL, &crashmem_dma, 0); module_param_call(crashmain, crashmem_set, NULL, &crashmem_main, 0); /* * Export Symbols for mkexec (i386 specific) */ #ifdef CONFIG_X86_LOCAL_APIC EXPORT_SYMBOL(lapic_mkexec_restore); #endif #ifdef CONFIG_X86_IO_APIC EXPORT_SYMBOL(ioapic_mkexec_restore); EXPORT_SYMBOL(ioapic_lock); #endif EXPORT_SYMBOL(e820); EXPORT_SYMBOL(__PAGE_KERNEL_EXEC); EXPORT_SYMBOL(saved_command_line); #ifdef CONFIG_X86_PAE EXPORT_SYMBOL(__supported_pte_mask); #endif #ifdef CONFIG_SMP EXPORT_SYMBOL(mkdump_send_nmi); #endif #ifdef CONFIG_X86_GENERICARCH EXPORT_SYMBOL(genapic); #endif --- NEW FILE: doublefault.c --- #include <linux/mm.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/init_task.h> #include <linux/fs.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/processor.h> #include <asm/desc.h> #define DOUBLEFAULT_STACKSIZE (1024) static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000) static void doublefault_fn(void) { struct Xgt_desc_struct gdt_desc = {0, 0}; unsigned long gdt, tss; struct tss_struct *t = NULL; store_gdt(&gdt_desc); gdt = gdt_desc.address; printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); if (ptr_ok(gdt)) { gdt += GDT_ENTRY_TSS << 3; tss = *(u16 *)(gdt+2); tss += *(u8 *)(gdt+4) << 16; tss += *(u8 *)(gdt+7) << 24; printk("double fault, tss at %08lx\n", tss); if (ptr_ok(tss)) { t = (struct tss_struct *)tss; printk("eip = %08lx, esp = %08lx\n", t->eip, t->esp); printk("eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", t->eax, t->ebx, t->ecx, t->edx); printk("esi = %08lx, edi = %08lx\n", t->esi, t->edi); } } #ifdef CONFIG_DUMP_MKEXEC /* FIXME: breakpoint() of KGDB hangs here. */ { struct pt_regs pt_regs; if (t) { pt_regs.ebx=t->ebx; pt_regs.ecx=t->ecx; pt_regs.edx=t->edx; pt_regs.esi=t->esi; pt_regs.edi=t->edi; pt_regs.ebp=t->eax; pt_regs.xds=(t->__dsh<<16) | t->ds; pt_regs.xes=(t->__esh<<16) | t->es; /* FIXME: Meaning? Not set by minik/LKCD get_current_regs(). */ pt_regs.orig_eax=0; pt_regs.eip=t->eip; pt_regs.xcs=(t->__csh<<16) | t->cs; pt_regs.eflags=t->eflags; pt_regs.esp=t->esp; pt_regs.xss=(t->__ssh<<16) | t->ss; } do_dump("double fault - kernel stack overflow?", (!t ? NULL : &pt_regs)); } #endif /* CONFIG_DUMP_MKEXEC */ for (;;) /* nothing */; } struct tss_struct doublefault_tss __cacheline_aligned = { .esp0 = STACK_START, .ss0 = __KERNEL_DS, .ldt = 0, .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, .eip = (unsigned long) doublefault_fn, .eflags = X86_EFLAGS_SF | 0x2, /* 0x2 bit is always set */ .esp = STACK_START, .es = __USER_DS, .cs = __KERNEL_CS, .ss = __KERNEL_DS, .ds = __USER_DS, .__cr3 = __pa(swapper_pg_dir) }; --- NEW FILE: irq.c --- /* * linux/arch/i386/kernel/irq.c * * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar * * This file contains the lowest level x86-specific interrupt * entry, irq-stacks and irq statistics code. All the remaining * irq logic is done by the generic kernel/irq/ code and * by the x86-specific irq controller code. (e.g. i8259.c and * io_apic.c.) */ #include <asm/uaccess.h> #include <linux/module.h> #include <linux/seq_file.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> #include <linux/notifier.h> #include <linux/cpu.h> #include <linux/delay.h> #include <linux/mkexec_dump.h> DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp; EXPORT_PER_CPU_SYMBOL(irq_stat); #ifndef CONFIG_X86_LOCAL_APIC /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves. */ void ack_bad_irq(unsigned int irq) { printk("unexpected IRQ trap at vector %02x\n", irq); } #endif #ifdef CONFIG_4KSTACKS /* * per-CPU IRQ handling contexts (thread information and stack) */ union irq_ctx { struct thread_info tinfo; u32 stack[THREAD_SIZE/sizeof(u32)]; }; static union irq_ctx *hardirq_ctx[NR_CPUS]; static union irq_ctx *softirq_ctx[NR_CPUS]; #endif /* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). */ fastcall unsigned int do_IRQ(struct pt_regs *regs) { /* high bits used in ret_from_ code */ int irq = regs->orig_eax & 0xff; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; u32 *isp; #endif irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW /* Debugging check for stack overflow: is there less than 1KB free? */ { long esp; __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (THREAD_SIZE - 1)); if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) { printk("do_IRQ: stack overflow: %ld\n", esp - sizeof(struct thread_info)); do_dump("do_IRQ: stack overflow", regs); dump_stack(); } } #endif #ifdef CONFIG_4KSTACKS curctx = (union irq_ctx *) current_thread_info(); irqctx = hardirq_ctx[smp_processor_id()]; /* * this is where we switch to the IRQ stack. However, if we are * already using the IRQ stack (because we interrupted a hardirq * handler) we can't do that and just have to keep using the * current stack (which is the irq stack already after all) */ if (curctx != irqctx) { int arg1, arg2, ebx; /* build the stack frame on the IRQ stack */ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); irqctx->tinfo.task = curctx->tinfo.task; irqctx->tinfo.previous_esp = current_stack_pointer; asm volatile( " xchgl %%ebx,%%esp \n" " call __do_IRQ \n" " movl %%ebx,%%esp \n" : "=a" (arg1), "=d" (arg2), "=b" (ebx) : "0" (irq), "1" (regs), "2" (isp) : "memory", "cc", "ecx" ); } else #endif __do_IRQ(irq, regs); irq_exit(); return 1; } #ifdef CONFIG_4KSTACKS /* * These should really be __section__(".bss.page_aligned") as well, but * gcc's 3.0 and earlier don't handle that correctly. */ static char softirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); static char hardirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); /* * allocate per-cpu stacks for hardirq and for softirq processing */ void irq_ctx_init(int cpu) { union irq_ctx *irqctx; if (hardirq_ctx[cpu]) return; irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE]; irqctx->tinfo.task = NULL; irqctx->tinfo.exec_domain = NULL; irqctx->tinfo.cpu = cpu; irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); hardirq_ctx[cpu] = irqctx; irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE]; irqctx->tinfo.task = NULL; irqctx->tinfo.exec_domain = NULL; irqctx->tinfo.cpu = cpu; irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); softirq_ctx[cpu] = irqctx; printk("CPU %u irqstacks, hard=%p soft=%p\n", cpu,hardirq_ctx[cpu],softirq_ctx[cpu]); } void irq_ctx_exit(int cpu) { hardirq_ctx[cpu] = NULL; } extern asmlinkage void __do_softirq(void); asmlinkage void do_softirq(void) { unsigned long flags; struct thread_info *curctx; union irq_ctx *irqctx; u32 *isp; if (in_interrupt()) return; local_irq_save(flags); if (local_softirq_pending()) { curctx = current_thread_info(); irqctx = softirq_ctx[smp_processor_id()]; irqctx->tinfo.task = curctx->task; irqctx->tinfo.previous_esp = current_stack_pointer; /* build the stack frame on the softirq stack */ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); asm volatile( " xchgl %%ebx,%%esp \n" " call __do_softirq \n" " movl %%ebx,%%esp \n" : "=b"(isp) : "0"(isp) : "memory", "cc", "edx", "ecx", "eax" ); } local_irq_restore(flags); } EXPORT_SYMBOL(do_softirq); #endif /* * Interrupt statistics: */ atomic_t irq_err_count; /* * /proc/interrupts printing: */ int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; struct irqaction * action; unsigned long flags; if (i == 0) { seq_printf(p, " "); for_each_online_cpu(j) seq_printf(p, "CPU%d ",j); seq_putc(p, '\n'); } if (i < NR_IRQS) { spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) goto skip; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif seq_printf(p, " %14s", irq_desc[i].handler->typename); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { seq_printf(p, "NMI: "); for_each_online_cpu(j) seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); #ifdef CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); for_each_online_cpu(j) seq_printf(p, "%10u ", per_cpu(irq_stat,j).apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); #if defined(CONFIG_X86_IO_APIC) seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); #endif } return 0; } #ifdef CONFIG_HOTPLUG_CPU #include <mach_apic.h> void fixup_irqs(cpumask_t map) { unsigned int irq; static int warned; for (irq = 0; irq < NR_IRQS; irq++) { cpumask_t mask; if (irq == 2) continue; cpus_and(mask, irq_affinity[irq], map); if (any_online_cpu(mask) == NR_CPUS) { printk("Breaking affinity for irq %i\n", irq); mask = map; } if (irq_desc[irq].handler->set_affinity) irq_desc[irq].handler->set_affinity(irq, mask); else if (irq_desc[irq].action && !(warned++)) printk("Cannot set affinity for irq %i\n", irq); } #if 0 barrier(); /* Ingo Molnar says: "after the IO-APIC masks have been redirected [note the nop - the interrupt-enable boundary on x86 is two instructions from sti] - to flush out pending hardirqs and IPIs. After this point nothing is supposed to reach this CPU." */ __asm__ __volatile__("sti; nop; cli"); barrier(); #else /* That doesn't seem sufficient. Give it 1ms. */ local_irq_enable(); mdelay(1); local_irq_disable(); #endif } #endif --- NEW FILE: smp.c --- /* * Intel SMP support routines. * * (c) 1995 Alan Cox, Building #3 <al...@re...> * (c) 1998-99, 2000 Ingo Molnar <mi...@re...> * * This code is released under the GNU General Public License version 2 or * later. */ #include <linux/init.h> #include <linux/mm.h> #include <linux/delay.h> #include <linux/spinlock.h> #include <linux/smp_lock.h> #include <linux/kernel_stat.h> #include <linux/mc146818rtc.h> #include <linux/cache.h> #include <linux/interrupt.h> #include <linux/cpu.h> #include <linux/module.h> #include <asm/mtrr.h> #include <asm/tlbflush.h> #include <mach_apic.h> /* * Some notes on x86 processor bugs affecting SMP operation: * * Pentium, Pentium Pro, II, III (and all CPUs) have bugs. * The Linux implications for SMP are handled as follows: * * Pentium III / [Xeon] * None of the E1AP-E3AP errata are visible to the user. * * E1AP. see PII A1AP * E2AP. see PII A2AP * E3AP. see PII A3AP * * Pentium II / [Xeon] * None of the A1AP-A3AP errata are visible to the user. * * A1AP. see PPro 1AP * A2AP. see PPro 2AP * A3AP. see PPro 7AP * * Pentium Pro * None of 1AP-9AP errata are visible to the normal user, * except occasional delivery of 'spurious interrupt' as trap #15. * This is very rare and a non-problem. * * 1AP. Linux maps APIC as non-cacheable * 2AP. worked around in hardware * 3AP. fixed in C0 and above steppings microcode update. * Linux does not use excessive STARTUP_IPIs. * 4AP. worked around in hardware * 5AP. symmetric IO mode (normal Linux operation) not affected. * 'noapic' mode has vector 0xf filled out properly. * 6AP. 'noapic' mode might be affected - fixed in later steppings * 7AP. We do not assume writes to the LVT deassering IRQs * 8AP. We do not enable low power mode (deep sleep) during MP bootup * 9AP. We do not use mixed mode * * Pentium * There is a marginal case where REP MOVS on 100MHz SMP * machines with B stepping processors can fail. XXX should provide * an L1cache=Writethrough or L1cache=off option. * * B stepping CPUs may hang. There are hardware work arounds * for this. We warn about it in case your board doesn't have the work * arounds. Basically thats so I can tell anyone with a B stepping * CPU and SMP problems "tough". * * Specific items [From Pentium Processor Specification Update] * * 1AP. Linux doesn't use remote read * 2AP. Linux doesn't trust APIC errors * 3AP. We work around this * 4AP. Linux never generated 3 interrupts of the same priority * to cause a lost local interrupt. * 5AP. Remote read is never used * 6AP. not affected - worked around in hardware * 7AP. not affected - worked around in hardware * 8AP. worked around in hardware - we get explicit CS errors if not * 9AP. only 'noapic' mode affected. Might generate spurious * interrupts, we log only the first one and count the * rest silently. * 10AP. not affected - worked around in hardware * 11AP. Linux reads the APIC between writes to avoid this, as per * the documentation. Make sure you preserve this as it affects * the C stepping chips too. * 12AP. not affected - worked around in hardware * 13AP. not affected - worked around in hardware * 14AP. we always deassert INIT during bootup * 15AP. not affected - worked around in hardware * 16AP. not affected - worked around in hardware * 17AP. not affected - worked around in hardware * 18AP. not affected - worked around in hardware * 19AP. not affected - worked around in BIOS * * If this sounds worrying believe me these bugs are either ___RARE___, * or are signal timing bugs worked around in hardware and there's * about nothing of note with C stepping upwards. */ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, }; /* * the following functions deal with sending IPIs between CPUs. * * We use 'broadcast', CPU->CPU IPIs and self-IPIs too. */ static inline int __prepare_ICR (unsigned int shortcut, int vector) { return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; } static inline int __prepare_ICR2 (unsigned int mask) { return SET_APIC_DEST_FIELD(mask); } void __send_IPI_shortcut(unsigned int shortcut, int vector) { /* * Subtle. In the case of the 'never do double writes' workaround * we have to lock out interrupts to be safe. As we don't care * of the value read we use an atomic rmw access to avoid costly * cli/sti. Otherwise we use an even cheaper single atomic write * to the APIC. */ unsigned int cfg; /* * Wait for idle. */ apic_wait_icr_idle(); /* * No need to touch the target chip field */ cfg = __prepare_ICR(shortcut, vector); /* * Send the IPI. The write to APIC_ICR fires this off. */ apic_write_around(APIC_ICR, cfg); } void fastcall send_IPI_self(int vector) { __send_IPI_shortcut(APIC_DEST_SELF, vector); } /* * This is only used on smaller machines. */ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) { unsigned long mask = cpus_addr(cpumask)[0]; unsigned long cfg; unsigned long flags; local_irq_save(flags); WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]); /* * Wait for idle. */ apic_wait_icr_idle(); /* * prepare target chip field */ cfg = __prepare_ICR2(mask); apic_write_around(APIC_ICR2, cfg); /* * program the ICR */ cfg = __prepare_ICR(0, vector); /* * Send the IPI. The write to APIC_ICR fires this off. */ apic_write_around(APIC_ICR, cfg); local_irq_restore(flags); } void send_IPI_mask_sequence(cpumask_t mask, int vector) { unsigned long cfg, flags; unsigned int query_cpu; /* * Hack. The clustered APIC addressing mode doesn't allow us to send * to an arbitrary mask, so I do a unicasts to each CPU instead. This * should be modified to do 1 message per cluster ID - mbligh */ local_irq_save(flags); for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) { if (cpu_isset(query_cpu, mask)) { /* * Wait for idle. */ apic_wait_icr_idle(); /* * prepare target chip field */ cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu)); apic_write_around(APIC_ICR2, cfg); /* * program the ICR */ cfg = __prepare_ICR(0, vector); /* * Send the IPI. The write to APIC_ICR fires this off. */ apic_write_around(APIC_ICR, cfg); } } local_irq_restore(flags); } #include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */ /* * Smarter SMP flushing macros. * c/o Linus Torvalds. * * These mean you can really definitely utterly forget about * writing to user space from interrupts. (Its not allowed anyway). * * Optimizations Manfred Spraul <ma...@co...> */ static cpumask_t flush_cpumask; static struct mm_struct * flush_mm; static unsigned long flush_va; static DEFINE_SPINLOCK(tlbstate_lock); #define FLUSH_ALL 0xffffffff /* * We cannot call mmdrop() because we are in interrupt context, * instead update mm->cpu_vm_mask. * * We need to reload %cr3 since the page tables may be going * away from under us.. */ static inline void leave_mm (unsigned long cpu) { if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) BUG(); cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask); load_cr3(swapper_pg_dir); } /* * * The flush IPI assumes that a thread switch happens in this order: * [cpu0: the cpu that switches] * 1) switch_mm() either 1a) or 1b) * 1a) thread switch to a different mm * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask); * Stop ipi delivery for the old mm. This is not synchronized with * the other cpus, but smp_invalidate_interrupt ignore flush ipis * for the wrong mm, and in the worst case we perform a superflous * tlb flush. * 1a2) set cpu_tlbstate to TLBSTATE_OK * Now the smp_invalidate_interrupt won't call leave_mm if cpu0 * was in lazy tlb mode. * 1a3) update cpu_tlbstate[].active_mm * Now cpu0 accepts tlb flushes for the new mm. * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask); * Now the other cpus will send tlb flush ipis. * 1a4) change cr3. * 1b) thread switch without mm change * cpu_tlbstate[].active_mm is correct, cpu0 already handles * flush ipis. * 1b1) set cpu_tlbstate to TLBSTATE_OK * 1b2) test_and_set the cpu bit in cpu_vm_mask. * Atomically set the bit [other cpus will start sending flush ipis], * and test the bit. * 1b3) if the bit was 0: leave_mm was called, flush the tlb. * 2) switch %%esp, ie current * * The interrupt must handle 2 special cases: * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm. * - the cpu performs speculative tlb reads, i.e. even if the cpu only * runs in kernel space, the cpu could load tlb entries for user space * pages. * * The good news is that cpu_tlbstate is local to each cpu, no * write/read ordering problems. */ /* * TLB flush IPI: * * 1) Flush the tlb entries if the cpu uses the mm that's being flushed. * 2) Leave the mm if we are in the lazy tlb mode. */ fastcall void smp_invalidate_interrupt(struct pt_regs *regs) { unsigned long cpu; cpu = get_cpu(); if (!cpu_isset(cpu, flush_cpumask)) goto out; /* * This was a BUG() but until someone can quote me the * line from the intel manual that guarantees an IPI to * multiple CPUs is retried _only_ on the erroring CPUs * its staying as a return * * BUG(); */ if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) { if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) { if (flush_va == FLUSH_ALL) local_flush_tlb(); else __flush_tlb_one(flush_va); } else leave_mm(cpu); } ack_APIC_irq(); smp_mb__before_clear_bit(); cpu_clear(cpu, flush_cpumask); smp_mb__after_clear_bit(); out: put_cpu_no_resched(); } static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, unsigned long va) { /* * A couple of (to be removed) sanity checks: * * - current CPU must not be in mask * - mask must exist :) */ BUG_ON(cpus_empty(cpumask)); BUG_ON(cpu_isset(smp_processor_id(), cpumask)); BUG_ON(!mm); /* If a CPU which we ran on has gone down, OK. */ cpus_and(cpumask, cpumask, cpu_online_map); if (cpus_empty(cpumask)) return; /* * i'm not happy about this global shared spinlock in the * MM hot path, but we'll see how contended it is. * Temporarily this turns IRQs off, so that lockups are * detected by the NMI watchdog. */ spin_lock(&tlbstate_lock); flush_mm = mm; flush_va = va; #if NR_CPUS <= BITS_PER_LONG atomic_set_mask(cpumask, &flush_cpumask); #else { int k; unsigned long *flush_mask = (unsigned long *)&flush_cpumask; unsigned long *cpu_mask = (unsigned long *)&cpumask; for (k = 0; k < BITS_TO_LONGS(NR_CPUS); ++k) atomic_set_mask(cpu_mask[k], &flush_mask[k]); } #endif /* * We have to send the IPI only to * CPUs affected. */ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR); while (!cpus_empty(flush_cpumask)) /* nothing. lockup detection does not belong here */ mb(); flush_mm = NULL; flush_va = 0; spin_unlock(&tlbstate_lock); } void flush_tlb_current_task(void) { struct mm_struct *mm = current->mm; cpumask_t cpu_mask; preempt_disable(); cpu_mask = mm->cpu_vm_mask; cpu_clear(smp_processor_id(), cpu_mask); local_flush_tlb(); if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } void flush_tlb_mm (struct mm_struct * mm) { cpumask_t cpu_mask; preempt_disable(); cpu_mask = mm->cpu_vm_mask; cpu_clear(smp_processor_id(), cpu_mask); if (current->active_mm == mm) { if (current->mm) local_flush_tlb(); else leave_mm(smp_processor_id()); } if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) { struct mm_struct *mm = vma->vm_mm; cpumask_t cpu_mask; preempt_disable(); cpu_mask = mm->cpu_vm_mask; cpu_clear(smp_processor_id(), cpu_mask); if (current->active_mm == mm) { if(current->mm) __flush_tlb_one(va); else leave_mm(smp_processor_id()); } if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, va); preempt_enable(); } EXPORT_SYMBOL(flush_tlb_page); static void do_flush_tlb_all(void* info) { unsigned long cpu = smp_processor_id(); __flush_tlb_all(); if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY) leave_mm(cpu); } void flush_tlb_all(void) { on_each_cpu(do_flush_tlb_all, NULL, 1, 1); } /* * this function sends a 'reschedule' IPI to another CPU. * it goes straight through and wastes no time serializing * anything. Worst case is that we lose a reschedule ... */ void smp_send_reschedule(int cpu) { WARN_ON(cpu_is_offline(cpu)); send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); } /* * Structure and data for smp_call_function(). This is designed to minimise * static memory requirements. It also looks cleaner. */ static DEFINE_SPINLOCK(call_lock); struct call_data_struct { void (*func) (void *info); void *info; atomic_t started; atomic_t finished; int wait; }; void lock_ipi_call_lock(void) { spin_lock_irq(&call_lock); } void unlock_ipi_call_lock(void) { spin_unlock_irq(&call_lock); } static struct call_data_struct *call_data; /** * smp_call_function(): Run a function on all other CPUs. * @func: The function to run. This must be fast and non-blocking. * @info: An arbitrary pointer to pass to the function. * @nonatomic: currently unused. * @wait: If true, wait (atomically) until function has completed on other CPUs. * * Returns 0 on success, else a negative status code. Does not return until * remote CPUs are nearly ready to execute <<func>> or are or have executed. * * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wait) { struct call_data_struct data; int cpus; /* Holding any lock stops cpus from going down. */ spin_lock(&call_lock); cpus = num_online_cpus() - 1; if (!cpus) { spin_unlock(&call_lock); return 0; } /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); data.func = func; data.info = info; atomic_set(&data.started, 0); data.wait = wait; if (wait) atomic_set(&data.finished, 0); call_data = &data; mb(); /* Send a message to all other CPUs and wait for them to respond */ send_IPI_allbutself(CALL_FUNCTION_VECTOR); /* Wait for response */ while (atomic_read(&data.started) != cpus) cpu_relax(); if (wait) while (atomic_read(&data.finished) != cpus) cpu_relax(); spin_unlock(&call_lock); return 0; } EXPORT_SYMBOL(smp_call_function); void stop_this_cpu (void * dummy) { /* * Remove this CPU: */ cpu_clear(smp_processor_id(), cpu_online_map); local_irq_disable(); disable_local_APIC(); if (cpu_data[smp_processor_id()].hlt_works_ok) for(;;) halt(); for (;;); } /* * this function calls the 'stop' function on all other CPUs in the system. */ void smp_send_stop(void) { smp_call_function(stop_this_cpu, NULL, 1, 0); local_irq_disable(); disable_local_APIC(); local_irq_enable(); } /* * Reschedule call back. Nothing to do, * all the work is done automatically when * we return from the interrupt. */ fastcall void smp_reschedule_interrupt(struct pt_regs *regs) { ack_APIC_irq(); } fastcall void smp_call_function_interrupt(struct pt_regs *regs) { void (*func) (void *info) = call_data->func; void *info = call_data->info; int wait = call_data->wait; ack_APIC_irq(); /* * Notify initiating CPU that I've grabbed the data and am * about to execute the function */ mb(); atomic_inc(&call_data->started); /* * At this point the info structure may be out of scope unless wait==1 */ irq_enter(); (*func)(info); irq_exit(); if (wait) { mb(); atomic_inc(&call_data->finished); } } #ifdef CONFIG_DUMP_MKEXEC /* Save the state of all the other CPUs. */ /* * Do not move the function to mkexec-module as send_IPI_allbutself() * requires machine type specific SYMBOL_EXPORT()s. */ void mkdump_send_nmi(void) { send_IPI_allbutself(APIC_DM_NMI); } EXPORT_SYMBOL(stop_this_cpu); #endif /* CONFIG_DUMP_MKEXEC */ |
From: Itsuro O. <od...@us...> - 2006-11-22 01:30:35
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include/linux In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv22290/include/linux Added Files: mkexec_dump.h Log Message: support 2.6.17 (caution: only i386 done) --- NEW FILE: mkexec_dump.h --- /* * include/linux/mkexec_dump.h * * $Id: mkexec_dump.h,v 1.1 2006/11/22 01:30:32 odaodab Exp $ * * Portions Copyright (C) 2004 NTT DATA CORPORATION. * Portions Copyright (C) 2004 VA Linux Systems Japan K.K. * * This file is part of Mkdump. * * Mkdump is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation (version 2 of the License). * * Mkdump is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Mkdump; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LINUX_MKEXEC_DUMP_H_ #define _LINUX_MKEXEC_DUMP_H_ #include <linux/ptrace.h> #ifdef CONFIG_DUMP_MKEXEC extern void (*do_dump_func)(char *, struct pt_regs *); extern void do_dump(char *panic_str, struct pt_regs *regs); #else /* CONFIG_DUMP_MKEXEC */ static inline void do_dump(char *panic_str, struct pt_regs *regs) {} #endif /* CONFIG_DUMP_MKEXEC */ #endif /* _LINUX_MKEXEC_DUMP_H_ */ |
From: Itsuro O. <od...@us...> - 2006-11-22 01:30:34
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386 In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv22290/arch/i386 Added Files: Kconfig Log Message: support 2.6.17 (caution: only i386 done) --- NEW FILE: Kconfig --- # # For a description of the syntax of this configuration file, # see Documentation/kbuild/kconfig-language.txt. # mainmenu "Linux Kernel Configuration" config X86_32 bool default y help This is Linux's home port. Linux was originally native to the Intel 386, and runs on all the later x86 processors including the Intel 486, 586, Pentiums, and various instruction-set-compatible chips by AMD, Cyrix, and others. config SEMAPHORE_SLEEPERS bool default y [...1101 lines suppressed...] default y config X86_HT bool depends on SMP && !(X86_VISWS || X86_VOYAGER) default y config X86_BIOS_REBOOT bool depends on !(X86_VISWS || X86_VOYAGER) default y config X86_TRAMPOLINE bool depends on X86_SMP || (X86_VOYAGER && SMP) default y config KTIME_SCALAR bool default y |
From: Itsuro O. <od...@us...> - 2006-11-22 01:25:59
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include/linux In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv20683/linux Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include/linux added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:25:40
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include/asm-i386 In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv20658/asm-i386 Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include/asm-i386 added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:21:49
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18972/2.6.17/arch/i386/kernel Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386/kernel added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:21:49
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/drivers/char In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18972/2.6.17/drivers/char Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/drivers/char added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:21:49
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386 In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18972/2.6.17/arch/i386 Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386 added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:21:48
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386/mm In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18972/2.6.17/arch/i386/mm Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch/i386/mm added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:20:18
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18462/2.6.17/include Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/include added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:20:18
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18462/2.6.17/kernel Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/kernel added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:20:18
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/drivers In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18462/2.6.17/drivers Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/drivers added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:20:17
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18462/2.6.17/arch Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17/arch added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 01:19:30
|
Update of /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17 In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv18076/2.6.17 Log Message: Directory /cvsroot/mkdump/mkexecpatch/2.0/linus/2.6.17 added to the repository |
From: Itsuro O. <od...@us...> - 2006-11-22 00:29:14
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv28946/arch/i386/kernel Modified Files: machine_mkexec.c minik_dump.c Log Message: fix for support newer linux kernel version (2.6.17) Index: minik_dump.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel/minik_dump.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** minik_dump.c 14 Feb 2006 05:50:28 -0000 1.2 --- minik_dump.c 22 Nov 2006 00:29:07 -0000 1.3 *************** *** 67,71 **** } } ! pgdat = pgdat_list; i = 0; if (avoid_pfn && avoid_pfn < pfn_pgdat(pgdat) + size_pgdat(pgdat)) { --- 67,71 ---- } } ! pgdat = first_pgdat(); i = 0; if (avoid_pfn && avoid_pfn < pfn_pgdat(pgdat) + size_pgdat(pgdat)) { Index: machine_mkexec.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel/machine_mkexec.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** machine_mkexec.c 14 Feb 2006 05:50:28 -0000 1.2 --- machine_mkexec.c 22 Nov 2006 00:29:07 -0000 1.3 *************** *** 40,44 **** --- 40,46 ---- dir = pgd_offset(&init_mm, addr); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) spin_lock(&init_mm.page_table_lock); + #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) *************** *** 53,57 **** --- 55,63 ---- goto out; } + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) pte = pte_alloc_kernel(&init_mm, pmd, addr); + #else + pte = pte_alloc_kernel(pmd, addr); + #endif if (pte == NULL) { error = -ENOMEM; *************** *** 65,69 **** --- 71,77 ---- #endif out: + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) spin_unlock(&init_mm.page_table_lock); + #endif return error; |
From: Itsuro O. <od...@us...> - 2006-11-22 00:29:14
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/include/linux In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv28946/include/linux Modified Files: mkexec_ex.h Log Message: fix for support newer linux kernel version (2.6.17) Index: mkexec_ex.h =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/include/linux/mkexec_ex.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** mkexec_ex.h 14 Feb 2006 05:30:26 -0000 1.1 --- mkexec_ex.h 22 Nov 2006 00:29:08 -0000 1.2 *************** *** 60,63 **** --- 60,64 ---- /* for pgdat_list member imcompatibility: 2.4 version */ + #define first_pgdat() (pgdat_list) #define next_pgdat(p) (p->node_next) #define size_pgdat(p) (p->node_size) *************** *** 67,74 **** /* for pgdat_list member imcompatibility: 2.6 version */ - #define next_pgdat(p) (p->pgdat_next) #define size_pgdat(p) (p->node_spanned_pages) #define pfn_pgdat(p) (p->node_start_pfn) #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ --- 68,83 ---- /* for pgdat_list member imcompatibility: 2.6 version */ #define size_pgdat(p) (p->node_spanned_pages) #define pfn_pgdat(p) (p->node_start_pfn) + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) + #define first_pgdat() (pgdat_list) + #define next_pgdat(p) (p->pgdat_next) + #else + /* >= 2.6.17 */ + #define first_pgdat() first_online_pgdat() + #define next_pgdat(p) next_online_pgdat(p) + #endif + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ |
From: Itsuro O. <od...@us...> - 2006-11-22 00:29:14
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv28946/arch/x86_64/kernel Modified Files: minik_dump.c Log Message: fix for support newer linux kernel version (2.6.17) Index: minik_dump.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/x86_64/kernel/minik_dump.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** minik_dump.c 14 Feb 2006 05:50:28 -0000 1.2 --- minik_dump.c 22 Nov 2006 00:29:07 -0000 1.3 *************** *** 66,70 **** } } ! pgdat = pgdat_list; i = 0; if (avoid_pfn && avoid_pfn < pfn_pgdat(pgdat) + size_pgdat(pgdat)) { --- 66,70 ---- } } ! pgdat = first_pgdat(); i = 0; if (avoid_pfn && avoid_pfn < pfn_pgdat(pgdat) + size_pgdat(pgdat)) { |
From: Itsuro O. <od...@us...> - 2006-11-22 00:29:14
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv28946/kernel Modified Files: mkexec_main.c Log Message: fix for support newer linux kernel version (2.6.17) Index: mkexec_main.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/kernel/mkexec_main.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** mkexec_main.c 13 Jun 2006 00:44:51 -0000 1.4 --- mkexec_main.c 22 Nov 2006 00:29:08 -0000 1.5 *************** *** 489,493 **** pages_system = 3; /* dump header pages */ ! for (pgdat = pgdat_list; pgdat; pgdat = next_pgdat(pgdat)) { pages_system += size_pgdat(pgdat); } --- 489,493 ---- pages_system = 3; /* dump header pages */ ! for (pgdat = first_pgdat(); pgdat; pgdat = next_pgdat(pgdat)) { pages_system += size_pgdat(pgdat); } |
From: Itsuro O. <od...@us...> - 2006-06-13 00:44:56
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv4504/kernel Modified Files: mkexec_main.c Log Message: bug fix: bug: crash if mini kernel is "Initial RAM disk (initrd) suppor" on and not use initrd. Index: mkexec_main.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/kernel/mkexec_main.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** mkexec_main.c 9 Mar 2006 23:47:58 -0000 1.3 --- mkexec_main.c 13 Jun 2006 00:44:51 -0000 1.4 *************** *** 256,260 **** image->segment[0].mem = (void *)0x90000; /* setup */ image->segment[1].mem = (void *)0x100000; /* kernel 1MB */ - image->segment[2].mem = (void *)0x800000; /* initrd 8MB */ return 0; --- 256,259 ---- *************** *** 384,387 **** --- 383,387 ---- } + image->segment[2].mem = (void *)0x800000; /* initrd 8MB */ image->segment[2].bufsz = image->segment[2].memsz = file_size; image->nr_segments = 3; /* XXX */ |
From: Itsuro O. <od...@us...> - 2006-06-13 00:44:56
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv4504/arch/i386/kernel Modified Files: mkexec-vmlinux.c Log Message: bug fix: bug: crash if mini kernel is "Initial RAM disk (initrd) suppor" on and not use initrd. Index: mkexec-vmlinux.c =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/arch/i386/kernel/mkexec-vmlinux.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** mkexec-vmlinux.c 9 Mar 2006 23:47:59 -0000 1.3 --- mkexec-vmlinux.c 13 Jun 2006 00:44:51 -0000 1.4 *************** *** 291,295 **** real_mode->loader_type = LOADER_TYPE_UNKNOWN; /* The ramdisk */ ! if (image->minik_type == MINIK_V3) { real_mode->initrd_start = image->segment[2].mem; real_mode->initrd_size = image->segment[2].memsz; --- 291,295 ---- real_mode->loader_type = LOADER_TYPE_UNKNOWN; /* The ramdisk */ ! if (image->nr_segments == 3) { real_mode->initrd_start = image->segment[2].mem; real_mode->initrd_size = image->segment[2].memsz; |
From: Itsuro O. <od...@us...> - 2006-03-28 00:43:47
|
Update of /cvsroot/mkdump/mkexec/3.0/2.6 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7814 Modified Files: README Added Files: README-v3 Log Message: for v3 Index: README =================================================================== RCS file: /cvsroot/mkdump/mkexec/3.0/2.6/README,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** README 24 Mar 2006 01:36:56 -0000 1.2 --- README 28 Mar 2006 00:43:43 -0000 1.3 *************** *** 5,10 **** http://mkdump.sourceforge.net ! *** This document describes the part of the backword compatibility of ! version 2 update 1. *** Contents of this package --- 5,15 ---- http://mkdump.sourceforge.net ! Note ! ---- ! ! This document describes the part of the backword compatibility of version 2 update 1. ! See README-v3 for version 3. ! If you have not used the mkdump yet, use version 3. ! Contents of this package *************** *** 58,62 **** +-----------+---------------+--------+ +--------+-------+ +---------+ ! for vanilla 2.4.27, use the version 1.0 of mkdump at this moment. --- 63,67 ---- +-----------+---------------+--------+ +--------+-------+ +---------+ ! for vanilla 2.4.27, use the version 1.0 of mkdump. *************** *** 160,164 **** # mkdir /usr/src/modules # cd /usr/src/modules ! # tar -xf mkexec-module-2.1.tar 2) Edit the Makefile --- 165,169 ---- # mkdir /usr/src/modules # cd /usr/src/modules ! # tar -xf mkexec-module-3.0.tar 2) Edit the Makefile *************** *** 291,295 **** ex. # cd /usr/local/src/ ! # tar xf mkdutils-2.1.tar 2) Make --- 296,300 ---- ex. # cd /usr/local/src/ ! # tar xf mkdutils-3.0.tar 2) Make *************** *** 311,338 **** the /etc/mkdump/mkdump environment file. ! 3) mkd_chk ! ! check the dump device whether the dump was captured or not. ! this command is used in mkd_save internaly. ! ! 4) /etc/mkdump/mkdump see mkdump-config-sample. ! 5) mkd_conv ! There are dump format conversion tools. ! "mini kernel dump" only offers the dump capturing function. ! You can use any analisys tool by converting the dump format. ! This directory includes three tools. ! - mkd2lkcd_i386 ! mkdump format to lkcd format (for i386) ! - mkd2lkcd_x86_64 ! mkdump format to lkcd format (for x86_64) ! - elf2lkcd_i386 ! vmcore format to lkcd format (for i386) ! These codes also intend to explain the mkdump format and to ! show the format conversion is easy task. Note: we use "crash" command rather than "lcrash" command. --- 316,331 ---- the /etc/mkdump/mkdump environment file. ! 3) /etc/mkdump/mkdump see mkdump-config-sample. ! 4) mkd_conv ! This is a dump format conversion and save tool. It converts to the LKCD format. ! mkd_conv file1 file2 ! file1: the dump partition (ex. /dev/hda7) ! file2: the output file ! for other functions see the souorce code. Note: we use "crash" command rather than "lcrash" command. --- NEW FILE: README-v3 --- README for Mini Kernel Dump (version 3) ------------------------------------------------ See the following URL for more information about MKDUMP. http://mkdump.sourceforge.net Note ---- The followings are main changes from version 2 update 1. * now a mini kernel is loaded to the standard address. * the dump output part of a mini kernel can be a kernel module. * initrd is supported. Contents of this package ------------------------ x. README-v3 (this file) a. mkexec kernel module mkexec-module-3.0.tar b. mkexec kernel patch b-1) mkexec-patch-2.6.12-2.1 b-2) mkexec-patch-deb-2.6.8-2.1 c. mini kernel module minik-module-3.0.tar d. mkdump utilities mkdutils-3.0.tar * support architecture: i386, x86_64 * the following combinations are available = for vanilla kernel +-----------+---------------+--------+ +--------+-------+ +---------+ | mkexec | mkexec | mkexec | | mini | minik | | utility | | kernel | patch | module | | kernel | module| | | +-----------+---------------+--------+ +--------+-------+ +---------+ | 2.6.12 | b-1 | a | | 2.6.x | c | | d | +-----------+---------------+--------+ +--------+-------+ +---------+ = for Red Hat +-----------+---------------+--------+ +--------+-------+ +---------+ | 2.4.21-20 | no need | | | | | | | | or later | | a | | 2.6.x | c | | d | +-----------+---------------+ | | | | | | | 2.6.9-x | no need | | | | | | | +-----------+---------------+--------+ +--------+-------+ +---------+ = for debian +-----------+---------------+--------+ +--------+-------+ +---------+ | 2.6.8-16 | b-2 | a | | 2.6.x | c | | d | +-----------+---------------+--------+ +--------+-------+ +---------+ note: we use 2.6.9 or later for a mini kernel. Installation ------------ Mini Kernel Dump consists of three parts: * minik - Mini Kernel Patch to build a special Linux kernel version to dump all the memory to a device. * mkexecpatch - MKEXEC kernel Hook and support functions to be able to load "mkexec-module". This patch must be applied to your standard running Linux kernel to be able to dump its faults. * mkexec-module - MKEXEC kernel module to load Mini Kernel Load this Linux kernel module to "mkexecpatch"-ed Linux kernel to be able to use the dumping functionality. This module will enable you to load 'minik - Mini Kernel' into memory and automatically launch it when needed. Build Mini Kernel ----------------- 1) Extract the source ex. # mkdir /usr/src/modules # cd /usr/src/modules # tar -xf minik-module-3.0.tar A: build as a kernel module 2) Edit the Makefile.base # cd /usr/src/modules/minik # vi kernel/Makefile.base Change "KDIR", "KVER" for your environment. 3) make # make; make install B: static link 2) copy minik_dump.c to the target source tree # cp kernel/minik_dump.c <kernel-src>/init 3) chage <kernel-src>/init/Makefile add "minik_dump.o" the following line. -------------------------------------------------------------------------- obj-y := main.o version.o mounts.o initramfs.o minik_dump.o ^^^^^^^^^^^^ ------------------------------------------------------------------------- 4) make # cd <kernel-src> # make Note: * The mini kernel should be as small as possible. ex. the network should not be configured. * Do not use "bzImage" for mkexec, use: arch/[i386|x86_64]/boot/compressed/vmlinux.bin Build MKEXEC kernel ------------------- Note: for RHEL3/4 this is not necessary. 1) Prepare the target kernel ex. # cd /usr/src # tar -xjf linux-2.6.12.tar.bz2 # mv linux-2.6.12 linux-mkexec 2) Apply the patch ex. # cd /usr/src/linux-mkexec # patch -p4 < mkexec-patch-2.6.12-2.1 3) Configuration # make menuconfig Turn on CONFIG_DUMP_MKEXEC: * 2.6.12 + mkexec-patch-2.6.12-2.1 Select "Mini Kernel - mkexec" in the "Processor type and features" * other no need 4) Build ex. # make bzImage; make modules; make modules_install; make install Build MKEXEC Kernel Module -------------------------- 1) Extract the source ex. # mkdir /usr/src/modules # cd /usr/src/modules # tar -xf mkexec-module-3.0.tar 2) Edit the Makefile # cd /usr/src/modules/mkexec # vi kernel/Makefile Change "ARCH", "KTYPE", "KVER", "TOPDIR" and "THISDIR" for your environment. ex. ARCH = x86_64 # specify "i386" or "x86_64" KTYPE = 24 # specify "24" for kernel 2.4 or "26" for kernel 2.6 TOPDIR = /usr/src/linux-mkexec # specify the top directory of mkexec kernel THISDIR = /usr/src/modules/mkexec/kernel # specify the directory this Makefile exists KVER = 2.6.12-mkexec # specify the kernel suffix (=> /lib/modules/$(KVER)) 3) Make symbolic link # ln -s asm-i386 include/asm # for i386 or # ln -s asm-x86_64 include/asm # for x86_64 4) Make # make Make initrd image ---------------- For example, on RHEL4: simply execute the following command # mkinitrd mkinitrd --with=mkdump initrd.img 2.6.12 For other distribution see the document for that system. Run Mini Kernel Dump -------------------- 1) Load the MKEXEC module # insmod /usr/src/modules/mkexec/kernel/mkexec.o # for kernel 2.4 or # insmod /usr/src/modules/mkexec/kernel/mkexec.ko # for kernel 2.6 2) Load the Mini kernel Set the dump device: ex. # echo "0x800012" > /proc/mkexec/dumpdev Specify the device number of the dump device. Bits 20..31 are block device major number, bits 0..19 are block device minor. Check the device number of your device by command like: ls -l /dev/sda4 Set the boot parameters of the mini kernel: ex. # echo "console=tty0 console=ttyS0,115200n8r" > /proc/mkexec/parameter * for RHEL3/4, the following parameters must be specified "lpj=" and "no-hlt" ex. # echo "lpj=2367488 no-hlt" > /proc/mkexec/parameter * the following parameters are available for the mini kernel mkdump_reboot: specifies action after dump done mkdump_reboot=reboot (default) =halt =poweroff =off note: working poweroff is hardware dependent dump_delay: specifies wait time before dump start (for waiting completion of device driver initialization) dump_delay=second (default == 0) ex. # echo "mkdump_reboot=halt dump_delay=5" > /proc/mkexec/parameter Set the path name of the mini kernel: ex. # echo "/usr/src/linux-minik/arch/i386/boot/compress/vmlinux.bin" > /proc/mkexec/path Set the amount of memory the mini kernel uses: ex. # echo 16 > /proc/mkexec/mem # reserve 16MB of memory This is necessary only for RHEL3 i386. This must be multiple of 4. Set the path name of initrd image: ex. # echo "/boot/initrd-minik.img" > /proc/mkexec/initrd Load the mini kernel image: # echo 9 > /proc/mkexec/stats Note: the "mkd_load" utility make above tasks easy. Start the Mini Kernel --------------------- If BUG(), panic() or nmi_watchdog occurs the Mini Dump kernel will be launched. Manual capturing dump: echo 2 >/proc/mkexec/stats Note: for x86_64, /proc/sys/kernel/panic_on_oops should turn on. # echo 1 > /proc/sys/kernel/panic_on_oops *** utilities for the mkdump *** Installation ------------ 1) Extract the source ex. # cd /usr/local/src/ # tar xf mkdutils-3.0.tar 2) Make # cd /usr/local/src/mkdutils # make Contents of this package ------------------------ 1) mkd_load load and setup the mkdump according to the /etc/mkdump/mkdump environment file. 2) mkd_save save the dump from the dump device to a permanent directory according to the /etc/mkdump/mkdump environment file. 3) /etc/mkdump/mkdump see mkdump-config-sample. 4) mkd_conv This is a dump format conversion and save tool. It converts to the LKCD format. mkd_conv file1 file2 file1: the dump partition (ex. /dev/hda7) file2: the output file for other functions see the souorce code. Note: we use "crash" command rather than "lcrash" command. Remark ------ these programs are offered as sample programs. there is nowarranty for these programs. -- Portions Copyright (C) 2004-2005 NTT DATA CORPORATION. Portions Copyright (C) 2004-2005 VA Linux Systems Japan K.K. |