menu "Kernel hacking"
+config CRASH_DUMP
+ tristate "Crash dump support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ Say Y here to enable saving an image of system memory when a panic
+ or other error occurs. Dumps can also be forced with the SysRq+d
+ key if MAGIC_SYSRQ is enabled.
+
+config CRASH_DUMP_BLOCKDEV
+ tristate "Crash dump block device driver"
+ depends on CRASH_DUMP
+ help
+ Say Y to allow saving crash dumps directly to a disk device.
+
+config CRASH_DUMP_NETDEV
+ tristate "Crash dump network device driver"
+ depends on CRASH_DUMP
+ help
+ Say Y to allow saving crash dumps over a network device.
+
+config CRASH_DUMP_MEMDEV
+ bool "Crash dump staged memory driver"
+ depends on CRASH_DUMP
+ help
+ Say Y to allow intermediate saving crash dumps in spare
+ memory pages which would then be written out to disk
+ later.
+
+config CRASH_DUMP_SOFTBOOT
+ bool "Save crash dump across a soft reboot"
+ depends on CRASH_DUMP_MEMDEV
+ help
+ Say Y to allow a crash dump to be preserved in memory
+ pages across a soft reboot and written out to disk
+ thereafter. For this to work, CRASH_DUMP must be
+ configured as part of the kernel (not as a module).
+
+config CRASH_DUMP_COMPRESS_RLE
+ tristate "Crash dump RLE compression"
+ depends on CRASH_DUMP
+ help
+ Say Y to allow saving dumps with Run Length Encoding compression.
+
+config CRASH_DUMP_COMPRESS_GZIP
+ tristate "Crash dump GZIP compression"
+ select ZLIB_INFLATE
+ select ZLIB_DEFLATE
+ depends on CRASH_DUMP
+ help
+ Say Y to allow saving dumps with Gnu Zip compression.
+
config DEBUG_KERNEL
bool "Kernel debugging"
help
install: $(BOOTIMAGE)
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
+ if [ -f init/kerntypes.o ]; then cp init/kerntypes.o $(INSTALL_PATH)/Kerntypes; fi
#include <linux/tty.h>
#include <linux/highmem.h>
#include <linux/time.h>
+#include <linux/nmi.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/nmi.h>
#include <asm/ist.h>
+#include <asm/e820.h>
extern void dump_thread(struct pt_regs *, struct user *);
extern spinlock_t rtc_lock;
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL_GPL(empty_zero_page);
+
+#ifdef CONFIG_CRASH_DUMP_MODULE
+#ifdef CONFIG_SMP
+extern irq_desc_t irq_desc[NR_IRQS];
+extern unsigned long irq_affinity[NR_IRQS];
+extern void stop_this_cpu(void *);
+EXPORT_SYMBOL(irq_desc);
+EXPORT_SYMBOL(irq_affinity);
+EXPORT_SYMBOL(stop_this_cpu);
+EXPORT_SYMBOL(dump_send_ipi);
+#endif
+extern int pfn_is_ram(unsigned long);
+EXPORT_SYMBOL(pfn_is_ram);
+#ifdef ARCH_HAS_NMI_WATCHDOG
+EXPORT_SYMBOL(touch_nmi_watchdog);
+#endif
+#endif
#include <linux/module.h>
#include <linux/nmi.h>
#include <linux/sysdev.h>
+#include <linux/dump.h>
#include <asm/smp.h>
#include <asm/mtrr.h>
bust_spinlocks(1);
printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
show_registers(regs);
+ dump("NMI Watchdog detected LOCKUP", regs);
printk("console shuts up ...\n");
console_silent();
spin_unlock(&nmi_print_lock);
*/
#define LOWMEMSIZE() (0x9f000)
+unsigned long crashdump_addr = 0xdeadbeef;
+
static void __init parse_cmdline_early (char ** cmdline_p)
{
char c = ' ', *to = command_line, *from = saved_command_line;
if (c == ' ' && !memcmp(from, "highmem=", 8))
highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
+ if (c == ' ' && !memcmp(from, "crashdump=", 10))
+ crashdump_addr = memparse(from+10, &from);
+
c = *(from++);
if (!c)
break;
static char * __init machine_specific_memory_setup(void);
+#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
+extern void crashdump_reserve(void);
+#endif
+
/*
* Determine if we were loaded by an EFI loader. If so, then we have also been
* passed the efi memmap, systab, etc., so we should use these data structures
#endif
+#ifdef CONFIG_CRASH_DUMP_SOFTBOOT
+ crashdump_reserve(); /* Preserve crash dump state from prev boot */
+#endif
+
dmi_scan_machine();
#ifdef CONFIG_X86_GENERICARCH
#include <linux/mc146818rtc.h>
#include <linux/cache.h>
#include <linux/interrupt.h>
+#include <linux/dump.h>
#include <asm/mtrr.h>
#include <asm/tlbflush.h>
*/
cfg = __prepare_ICR(shortcut, vector);
+ if (vector == DUMP_VECTOR) {
+ /*
+ * Setup DUMP IPI to be delivered as an NMI
+ */
+ cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+ }
+
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
* program the ICR
*/
cfg = __prepare_ICR(0, vector);
-
+
+ if (vector == DUMP_VECTOR) {
+ /*
+ * Setup DUMP IPI to be delivered as an NMI
+ */
+ cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI;
+ }
/*
* Send the IPI. The write to APIC_ICR fires this off.
*/
on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
}
+void dump_send_ipi(void)
+{
+ send_IPI_allbutself(DUMP_VECTOR);
+}
+
/*
* this function sends a 'reschedule' IPI to another CPU.
* it goes straight through and wastes no time serializing
return 0;
}
-static void stop_this_cpu (void * dummy)
+void stop_this_cpu (void * dummy)
{
/*
* Remove this CPU:
local_irq_enable();
}
+EXPORT_SYMBOL(smp_send_stop);
+
/*
* Reschedule call back. Nothing to do,
* all the work is done automatically when
atomic_inc(&call_data->finished);
}
}
-
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
#include <linux/version.h>
+#include <linux/dump.h>
#ifdef CONFIG_EISA
#include <linux/ioport.h>
show_registers(regs);
if (netdump_func)
netdump_func(regs);
+ dump((char *)str, regs);
bust_spinlocks(0);
die_owner = -1;
spin_unlock_irq(&die_lock);
return 0;
}
+/* To enable modules to check if a page is in RAM */
+int pfn_is_ram(unsigned long pfn)
+{
+ return (page_is_ram(pfn));
+}
+
+
pte_t *kmap_pte;
EXPORT_SYMBOL(kmap_pte);
install: $(CONFIGURE) $(obj)/image
sh -x $(obj)/install.sh $(KERNELRELEASE) $(obj)/image \
- System.map Kerntypes "$(INSTALL_PATH)"
+ System.map init/kerntypes.o "$(INSTALL_PATH)"
# $1 - kernel version
# $2 - kernel image file
# $3 - kernel map file
-# $4 - default install path (blank if root directory)
+# $4 - kernel type file
+# $5 - default install path (blank if root directory)
#
# User may have a custom install script
# Default install - same as make zlilo
-if [ -f $4/vmlinuz ]; then
- mv $4/vmlinuz $4/vmlinuz.old
+if [ -f $5/vmlinuz ]; then
+ mv $5/vmlinuz $5/vmlinuz.old
fi
-if [ -f $4/System.map ]; then
- mv $4/System.map $4/System.old
+if [ -f $5/System.map ]; then
+ mv $5/System.map $5/System.old
fi
-cat $2 > $4/vmlinuz
-cp $3 $4/System.map
+if [ -f $5/Kerntypes ]; then
+ mv $5/Kerntypes $5/Kerntypes.old
+fi
+
+cat $2 > $5/vmlinuz
+cp $3 $5/System.map
+
+# copy the kernel type file if it exists
+if [ -f $4 ]; then
+ cp $4 $5/Kerntypes
+fi
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
+obj-$(CONFIG_CRASH_DUMP) += dump/
obj-y += firmware/
KM_SOFTIRQ1,
KM_NETDUMP,
KM_UNUSED,
- KM_TYPE_NR
+ KM_TYPE_NR,
+ KM_DUMP
};
#endif
#define INVALIDATE_TLB_VECTOR 0xfd
#define RESCHEDULE_VECTOR 0xfc
#define CALL_FUNCTION_VECTOR 0xfb
+#define DUMP_VECTOR 0xfa
#define THERMAL_APIC_VECTOR 0xf0
/*
extern cpumask_t cpu_sibling_map[];
extern void smp_flush_tlb(void);
+extern void dump_send_ipi(void);
extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
extern void smp_invalidate_rcv(void); /* Process an NMI */
extern void (*mtrr_hook) (void);
#define MICROCODE_MINOR 184
#define MWAVE_MINOR 219 /* ACP/Mwave Modem */
#define MPT_MINOR 220
+#define CRASH_DUMP_MINOR 230 /* LKCD */
#define MISC_DYNAMIC_MINOR 255
#define TUN_MINOR 200
extern int nr_threads;
extern int last_pid;
DECLARE_PER_CPU(unsigned long, process_counts);
+DECLARE_PER_CPU(struct runqueue, runqueues);
extern int nr_processes(void);
extern unsigned long nr_running(void);
extern unsigned long nr_uninterruptible(void);
void yield(void);
+/*
+ * These are the runqueue data structures:
+ */
+typedef struct runqueue runqueue_t;
+
+#ifdef CONFIG_CKRM_CPU_SCHEDULE
+#include <linux/ckrm_classqueue.h>
+#endif
+
+#ifdef CONFIG_CKRM_CPU_SCHEDULE
+
+/**
+ * if belong to different class, compare class priority
+ * otherwise compare task priority
+ */
+#define TASK_PREEMPTS_CURR(p, rq) \
+ (((p)->cpu_class != (rq)->curr->cpu_class) && ((rq)->curr != (rq)->idle))? class_preempts_curr((p),(rq)->curr) : ((p)->prio < (rq)->curr->prio)
+#else
+#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long))
+struct prio_array {
+ unsigned int nr_active;
+ unsigned long bitmap[BITMAP_SIZE];
+ struct list_head queue[MAX_PRIO];
+};
+#define rq_active(p,rq) (rq->active)
+#define rq_expired(p,rq) (rq->expired)
+#define ckrm_rebalance_tick(j,this_cpu) do {} while (0)
+#define TASK_PREEMPTS_CURR(p, rq) \
+ ((p)->prio < (rq)->curr->prio)
+#endif
+
+/*
+ * This is the main, per-CPU runqueue data structure.
+ *
+ * Locking rule: those places that want to lock multiple runqueues
+ * (such as the load balancing or the thread migration code), lock
+ * acquire operations must be ordered by ascending &runqueue.
+ */
+struct runqueue {
+ spinlock_t lock;
+
+ /*
+ * nr_running and cpu_load should be in the same cacheline because
+ * remote CPUs use both these fields when doing load calculation.
+ */
+ unsigned long nr_running;
+#if defined(CONFIG_SMP)
+ unsigned long cpu_load;
+#endif
+ unsigned long long nr_switches, nr_preempt;
+ unsigned long expired_timestamp, nr_uninterruptible;
+ unsigned long long timestamp_last_tick;
+ task_t *curr, *idle;
+ struct mm_struct *prev_mm;
+#ifdef CONFIG_CKRM_CPU_SCHEDULE
+ unsigned long ckrm_cpu_load;
+ struct classqueue_struct classqueue;
+#else
+ prio_array_t *active, *expired, arrays[2];
+#endif
+ int best_expired_prio;
+ atomic_t nr_iowait;
+
+#ifdef CONFIG_SMP
+ struct sched_domain *sd;
+
+ /* For active balancing */
+ int active_balance;
+ int push_cpu;
+
+ task_t *migration_thread;
+ struct list_head migration_queue;
+#endif
+ struct list_head hold_queue;
+ int idle_tokens;
+};
+
/*
* The default (Linux) execution domain.
*/
KERN_SPARC_SCONS_PWROFF=64, /* int: serial console power-off halt */
KERN_HZ_TIMER=65, /* int: hz timer on or off */
KERN_VSHELPER=66, /* string: path to vshelper policy agent */
+ KERN_DUMP=67, /* dir: dump parameters */
};
mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o
mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o
+extra-$(subst m,y,$(CONFIG_CRASH_DUMP)) += kerntypes.o
+CFLAGS_kerntypes.o := -gstabs
+
# files to be removed upon make clean
clean-files := ../include/linux/compile.h
enum system_states system_state;
EXPORT_SYMBOL(system_state);
+/*
+ * The kernel_magic value represents the address of _end, which allows
+ * namelist tools to "match" each other respectively. That way a tool
+ * that looks at /dev/mem can verify that it is using the right System.map
+ * file -- if kernel_magic doesn't equal the namelist value of _end,
+ * something's wrong.
+ */
+extern unsigned long _end;
+unsigned long *kernel_magic = &_end;
+
/*
* Boot command-line arguments
*/
#include <linux/uts.h>
#include <linux/utsname.h>
#include <linux/version.h>
+#include <linux/stringify.h>
#define version(a) Version_ ## a
#define version_string(a) version(a)
const char *linux_banner =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+const char *LINUX_COMPILE_VERSION_ID = __stringify(LINUX_COMPILE_VERSION_ID);
+LINUX_COMPILE_VERSION_ID_TYPE;
#include <linux/syscalls.h>
#include <linux/interrupt.h>
#include <linux/nmi.h>
+#ifdef CONFIG_KEXEC
+#include <linux/kexec.h>
+#endif
int panic_timeout;
int panic_on_oops;
int tainted;
+void (*dump_function_ptr)(const char *, const struct pt_regs *) = 0;
EXPORT_SYMBOL(panic_timeout);
+EXPORT_SYMBOL(dump_function_ptr);
struct notifier_block *panic_notifier_list;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
+
printk(KERN_EMERG "Kernel panic: %s\n",buf);
if (netdump_func)
BUG();
sys_sync();
bust_spinlocks(0);
+ notifier_call_chain(&panic_notifier_list, 0, buf);
+
#ifdef CONFIG_SMP
smp_send_stop();
#endif
- notifier_call_chain(&panic_notifier_list, 0, buf);
-
- if (panic_timeout > 0)
- {
+ if (panic_timeout > 0) {
int i;
/*
* 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);
+#ifdef CONFIG_KEXEC
+{
+ struct kimage *image;
+ image = xchg(&kexec_image, 0);
+ if (image) {
+ printk(KERN_EMERG "by starting a new kernel ..\n");
+ mdelay(panic_timeout*1000);
+ machine_kexec(image);
+ }
+ }
+#endif
for (i = 0; i < panic_timeout; i++) {
touch_nmi_watchdog();
mdelay(1000);
#define cpu_to_node_mask(cpu) (cpu_online_map)
#endif
+/* used to soft spin in sched while dump is in progress */
+unsigned long dump_oncpu;
+EXPORT_SYMBOL(dump_oncpu);
+
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
* to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
#define task_hot(p, now, sd) ((now) - (p)->timestamp < (sd)->cache_hot_time)
-/*
- * These are the runqueue data structures:
- */
-typedef struct runqueue runqueue_t;
-
-#ifdef CONFIG_CKRM_CPU_SCHEDULE
-#include <linux/ckrm_classqueue.h>
-#endif
-
-#ifdef CONFIG_CKRM_CPU_SCHEDULE
-
-/**
- * if belong to different class, compare class priority
- * otherwise compare task priority
- */
-#define TASK_PREEMPTS_CURR(p, rq) \
- (((p)->cpu_class != (rq)->curr->cpu_class) && ((rq)->curr != (rq)->idle))? class_preempts_curr((p),(rq)->curr) : ((p)->prio < (rq)->curr->prio)
-#else
-#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long))
-struct prio_array {
- unsigned int nr_active;
- unsigned long bitmap[BITMAP_SIZE];
- struct list_head queue[MAX_PRIO];
-};
-#define rq_active(p,rq) (rq->active)
-#define rq_expired(p,rq) (rq->expired)
-#define ckrm_rebalance_tick(j,this_cpu) do {} while (0)
-#define TASK_PREEMPTS_CURR(p, rq) \
- ((p)->prio < (rq)->curr->prio)
-#endif
-
-/*
- * This is the main, per-CPU runqueue data structure.
- *
- * Locking rule: those places that want to lock multiple runqueues
- * (such as the load balancing or the thread migration code), lock
- * acquire operations must be ordered by ascending &runqueue.
- */
-struct runqueue {
- spinlock_t lock;
-
- /*
- * nr_running and cpu_load should be in the same cacheline because
- * remote CPUs use both these fields when doing load calculation.
- */
- unsigned long nr_running;
-#if defined(CONFIG_SMP)
- unsigned long cpu_load;
-#endif
- unsigned long long nr_switches, nr_preempt;
- unsigned long expired_timestamp, nr_uninterruptible;
- unsigned long long timestamp_last_tick;
- task_t *curr, *idle;
- struct mm_struct *prev_mm;
-#ifdef CONFIG_CKRM_CPU_SCHEDULE
- unsigned long ckrm_cpu_load;
- struct classqueue_struct classqueue;
-#else
- prio_array_t *active, *expired, arrays[2];
-#endif
- int best_expired_prio;
- atomic_t nr_iowait;
-
-#ifdef CONFIG_SMP
- struct sched_domain *sd;
-
- /* For active balancing */
- int active_balance;
- int push_cpu;
-
- task_t *migration_thread;
- struct list_head migration_queue;
-#endif
- struct list_head hold_queue;
- int idle_tokens;
-};
-
-static DEFINE_PER_CPU(struct runqueue, runqueues);
+DEFINE_PER_CPU(struct runqueue, runqueues);
#define for_each_domain(cpu, domain) \
for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent)
100*max_load <= sd->imbalance_pct*this_load)
goto out_balanced;
+ /*
+ * If crash dump is in progress, this other cpu's
+ * need to wait until it completes.
+ * NB: this code is optimized away for kernels without
+ * dumping enabled.
+ */
+ if (unlikely(dump_oncpu))
+ goto dump_scheduling_disabled;
+
/*
* We're trying to get all the cpus to the average_load, so we don't
* want to push ourselves above the average load, nor do we wish to
preempt_enable_no_resched();
if (test_thread_flag(TIF_NEED_RESCHED))
goto need_resched;
+
+ return;
+
+ dump_scheduling_disabled:
+ /* allow scheduling only if this is the dumping cpu */
+ if (dump_oncpu != smp_processor_id()+1) {
+ while (dump_oncpu)
+ cpu_relax();
+ }
+ return;
}
EXPORT_SYMBOL(schedule);
*/
unsigned long max_low_pfn;
unsigned long min_low_pfn;
+EXPORT_SYMBOL(min_low_pfn);
unsigned long max_pfn;
EXPORT_SYMBOL(max_pfn); /* This is exported so
EXPORT_SYMBOL(totalram_pages);
EXPORT_SYMBOL(nr_swap_pages);
+#ifdef CONFIG_CRASH_DUMP_MODULE
+/* This symbol has to be exported to use 'for_each_pgdat' macro by modules. */
+EXPORT_SYMBOL(pgdat_list);
+#endif
+
/*
* Used by page_zone() to look up the address of the struct zone whose
* id is encoded in the upper bits of page->flags
page->mapcount = 0;
}
-#ifndef CONFIG_HUGETLB_PAGE
+#if !defined(CONFIG_HUGETLB_PAGE) && !defined(CONFIG_CRASH_DUMP) \
+ && !defined(CONFIG_CRASH_DUMP_MODULE)
#define prep_compound_page(page, order) do { } while (0)
#define destroy_compound_page(page, order) do { } while (0)
#else
UTS_LEN=64
UTS_TRUNCATE="sed -e s/\(.\{1,$UTS_LEN\}\).*/\1/"
-
+LINUX_COMPILE_VERSION_ID="__linux_compile_version_id__`hostname | tr -c '[0-9A-Za-z\n]' '__'`_`LANG=C date | tr -c '[0-9A-Za-z\n]' '_'`"
# Generate a temporary compile.h
( echo /\* This file is auto generated, version $VERSION \*/
fi
echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
+ echo \#define LINUX_COMPILE_VERSION_ID $LINUX_COMPILE_VERSION_ID
+ echo \#define LINUX_COMPILE_VERSION_ID_TYPE typedef char* "$LINUX_COMPILE_VERSION_ID""_t"
) > .tmpcompile
# Only replace the real compile.h if the new one is different,