Date:2010-07-20 03:54:21 (13 years 8 months ago)
Author:nbd
Commit:5b42ce672e76f21235f8e27179d516fc0ff24f17
Message:kernel: add the new 'crashlog' feature, which tries to store kernel oops/panic logs in a fixed location in RAM to recover them after the reboot and make them available to user space using debugfs

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22305 3c298f89-4303-0410-b956-a3cf2f4a3e73
Files: target/linux/generic/config-2.6.32 (1 diff)
target/linux/generic/config-2.6.33 (1 diff)
target/linux/generic/config-2.6.34 (1 diff)
target/linux/generic/config-2.6.35 (1 diff)
target/linux/generic/patches-2.6.32/930-kmsg_dump_backport.patch (1 diff)
target/linux/generic/patches-2.6.32/931-crashlog.patch (1 diff)
target/linux/generic/patches-2.6.33/930-crashlog.patch (1 diff)
target/linux/generic/patches-2.6.34/930-crashlog.patch (1 diff)
target/linux/generic/patches-2.6.35/930-crashlog.patch (1 diff)

Change Details

target/linux/generic/config-2.6.32
352352# CONFIG_CPU_IDLE is not set
353353# CONFIG_CRAMFS is not set
354354# CONFIG_CRASH_DUMP is not set
355CONFIG_CRASHLOG=y
355356# CONFIG_CRC16 is not set
356357CONFIG_CRC32=y
357358# CONFIG_CRC7 is not set
target/linux/generic/config-2.6.33
357357# CONFIG_CPU_IDLE is not set
358358# CONFIG_CRAMFS is not set
359359# CONFIG_CRASH_DUMP is not set
360CONFIG_CRASHLOG=y
360361# CONFIG_CRC16 is not set
361362CONFIG_CRC32=y
362363# CONFIG_CRC7 is not set
target/linux/generic/config-2.6.34
360360# CONFIG_CPU_IDLE is not set
361361# CONFIG_CRAMFS is not set
362362# CONFIG_CRASH_DUMP is not set
363CONFIG_CRASHLOG=y
363364# CONFIG_CRC16 is not set
364365CONFIG_CRC32=y
365366# CONFIG_CRC7 is not set
target/linux/generic/config-2.6.35
367367# CONFIG_CPU_IDLE is not set
368368# CONFIG_CRAMFS is not set
369369# CONFIG_CRASH_DUMP is not set
370CONFIG_CRASHLOG=y
370371# CONFIG_CRC16 is not set
371372CONFIG_CRC32=y
372373# CONFIG_CRC7 is not set
target/linux/generic/patches-2.6.32/930-kmsg_dump_backport.patch
1--- /dev/null
2@@ -0,0 +1,44 @@
3+/*
4+ * linux/include/kmsg_dump.h
5+ *
6+ * Copyright (C) 2009 Net Insight AB
7+ *
8+ * Author: Simon Kagstrom <simon.kagstrom@netinsight.net>
9+ *
10+ * This file is subject to the terms and conditions of the GNU General Public
11+ * License. See the file COPYING in the main directory of this archive
12+ * for more details.
13+ */
14+#ifndef _LINUX_KMSG_DUMP_H
15+#define _LINUX_KMSG_DUMP_H
16+
17+#include <linux/list.h>
18+
19+enum kmsg_dump_reason {
20+ KMSG_DUMP_OOPS,
21+ KMSG_DUMP_PANIC,
22+};
23+
24+/**
25+ * struct kmsg_dumper - kernel crash message dumper structure
26+ * @dump: The callback which gets called on crashes. The buffer is passed
27+ * as two sections, where s1 (length l1) contains the older
28+ * messages and s2 (length l2) contains the newer.
29+ * @list: Entry in the dumper list (private)
30+ * @registered: Flag that specifies if this is already registered
31+ */
32+struct kmsg_dumper {
33+ void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason,
34+ const char *s1, unsigned long l1,
35+ const char *s2, unsigned long l2);
36+ struct list_head list;
37+ int registered;
38+};
39+
40+void kmsg_dump(enum kmsg_dump_reason reason);
41+
42+int kmsg_dump_register(struct kmsg_dumper *dumper);
43+
44+int kmsg_dump_unregister(struct kmsg_dumper *dumper);
45+
46+#endif /* _LINUX_KMSG_DUMP_H */
47--- a/kernel/panic.c
48@@ -10,6 +10,7 @@
49  */
50 #include <linux/debug_locks.h>
51 #include <linux/interrupt.h>
52+#include <linux/kmsg_dump.h>
53 #include <linux/kallsyms.h>
54 #include <linux/notifier.h>
55 #include <linux/module.h>
56@@ -74,6 +75,7 @@ NORET_TYPE void panic(const char * fmt,
57     dump_stack();
58 #endif
59
60+ kmsg_dump(KMSG_DUMP_PANIC);
61     /*
62      * If we have crashed and we have a crash kernel loaded let it handle
63      * everything else.
64@@ -339,6 +341,7 @@ void oops_exit(void)
65 {
66     do_oops_enter_exit();
67     print_oops_end_marker();
68+ kmsg_dump(KMSG_DUMP_OOPS);
69 }
70
71 #ifdef WANT_WARN_ON_SLOWPATH
72--- a/kernel/printk.c
73@@ -33,6 +33,7 @@
74 #include <linux/bootmem.h>
75 #include <linux/syscalls.h>
76 #include <linux/kexec.h>
77+#include <linux/kmsg_dump.h>
78
79 #include <asm/uaccess.h>
80
81@@ -1405,3 +1406,121 @@ bool printk_timed_ratelimit(unsigned lon
82 }
83 EXPORT_SYMBOL(printk_timed_ratelimit);
84 #endif
85+
86+static DEFINE_SPINLOCK(dump_list_lock);
87+static LIST_HEAD(dump_list);
88+
89+/**
90+ * kmsg_dump_register - register a kernel log dumper.
91+ * @dump: pointer to the kmsg_dumper structure
92+ *
93+ * Adds a kernel log dumper to the system. The dump callback in the
94+ * structure will be called when the kernel oopses or panics and must be
95+ * set. Returns zero on success and %-EINVAL or %-EBUSY otherwise.
96+ */
97+int kmsg_dump_register(struct kmsg_dumper *dumper)
98+{
99+ unsigned long flags;
100+ int err = -EBUSY;
101+
102+ /* The dump callback needs to be set */
103+ if (!dumper->dump)
104+ return -EINVAL;
105+
106+ spin_lock_irqsave(&dump_list_lock, flags);
107+ /* Don't allow registering multiple times */
108+ if (!dumper->registered) {
109+ dumper->registered = 1;
110+ list_add_tail(&dumper->list, &dump_list);
111+ err = 0;
112+ }
113+ spin_unlock_irqrestore(&dump_list_lock, flags);
114+
115+ return err;
116+}
117+EXPORT_SYMBOL_GPL(kmsg_dump_register);
118+
119+/**
120+ * kmsg_dump_unregister - unregister a kmsg dumper.
121+ * @dump: pointer to the kmsg_dumper structure
122+ *
123+ * Removes a dump device from the system. Returns zero on success and
124+ * %-EINVAL otherwise.
125+ */
126+int kmsg_dump_unregister(struct kmsg_dumper *dumper)
127+{
128+ unsigned long flags;
129+ int err = -EINVAL;
130+
131+ spin_lock_irqsave(&dump_list_lock, flags);
132+ if (dumper->registered) {
133+ dumper->registered = 0;
134+ list_del(&dumper->list);
135+ err = 0;
136+ }
137+ spin_unlock_irqrestore(&dump_list_lock, flags);
138+
139+ return err;
140+}
141+EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
142+
143+static const char const *kmsg_reasons[] = {
144+ [KMSG_DUMP_OOPS] = "oops",
145+ [KMSG_DUMP_PANIC] = "panic",
146+};
147+
148+static const char *kmsg_to_str(enum kmsg_dump_reason reason)
149+{
150+ if (reason >= ARRAY_SIZE(kmsg_reasons) || reason < 0)
151+ return "unknown";
152+
153+ return kmsg_reasons[reason];
154+}
155+
156+/**
157+ * kmsg_dump - dump kernel log to kernel message dumpers.
158+ * @reason: the reason (oops, panic etc) for dumping
159+ *
160+ * Iterate through each of the dump devices and call the oops/panic
161+ * callbacks with the log buffer.
162+ */
163+void kmsg_dump(enum kmsg_dump_reason reason)
164+{
165+ unsigned long end;
166+ unsigned chars;
167+ struct kmsg_dumper *dumper;
168+ const char *s1, *s2;
169+ unsigned long l1, l2;
170+ unsigned long flags;
171+
172+ /* Theoretically, the log could move on after we do this, but
173+ there's not a lot we can do about that. The new messages
174+ will overwrite the start of what we dump. */
175+ spin_lock_irqsave(&logbuf_lock, flags);
176+ end = log_end & LOG_BUF_MASK;
177+ chars = logged_chars;
178+ spin_unlock_irqrestore(&logbuf_lock, flags);
179+
180+ if (logged_chars > end) {
181+ s1 = log_buf + log_buf_len - logged_chars + end;
182+ l1 = logged_chars - end;
183+
184+ s2 = log_buf;
185+ l2 = end;
186+ } else {
187+ s1 = "";
188+ l1 = 0;
189+
190+ s2 = log_buf + end - logged_chars;
191+ l2 = logged_chars;
192+ }
193+
194+ if (!spin_trylock_irqsave(&dump_list_lock, flags)) {
195+ printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n",
196+ kmsg_to_str(reason));
197+ return;
198+ }
199+ list_for_each_entry(dumper, &dump_list, list)
200+ dumper->dump(dumper, reason, s1, l1, s2, l2);
201+ spin_unlock_irqrestore(&dump_list_lock, flags);
202+}
target/linux/generic/patches-2.6.32/931-crashlog.patch
1--- /dev/null
2@@ -0,0 +1,12 @@
3+#ifndef __CRASHLOG_H
4+#define __CRASHLOG_H
5+
6+#ifdef CONFIG_CRASHLOG
7+void __init crashlog_init_mem(struct bootmem_data *bdata);
8+#else
9+static inline void crashlog_init_mem(struct bootmem_data *bdata)
10+{
11+}
12+#endif
13+
14+#endif
15--- a/init/Kconfig
16@@ -710,6 +710,9 @@ config NET_NS
17       Allow user space to create what appear to be multiple instances
18       of the network stack.
19
20+config CRASHLOG
21+ bool "Crash logging"
22+
23 config BLK_DEV_INITRD
24     bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
25     depends on BROKEN || !FRV
26--- a/kernel/Makefile
27@@ -96,6 +96,7 @@ obj-$(CONFIG_SMP) += sched_cpupri.o
28 obj-$(CONFIG_SLOW_WORK) += slow-work.o
29 obj-$(CONFIG_SLOW_WORK_DEBUG) += slow-work-debugfs.o
30 obj-$(CONFIG_PERF_EVENTS) += perf_event.o
31+obj-$(CONFIG_CRASHLOG) += crashlog.o
32
33 ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
34 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
35--- /dev/null
36@@ -0,0 +1,171 @@
37+/*
38+ * Crash information logger
39+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
40+ *
41+ * Based on ramoops.c
42+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
43+ *
44+ * This program is free software; you can redistribute it and/or
45+ * modify it under the terms of the GNU General Public License
46+ * version 2 as published by the Free Software Foundation.
47+ *
48+ * This program is distributed in the hope that it will be useful, but
49+ * WITHOUT ANY WARRANTY; without even the implied warranty of
50+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
51+ * General Public License for more details.
52+ *
53+ * You should have received a copy of the GNU General Public License
54+ * along with this program; if not, write to the Free Software
55+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
56+ * 02110-1301 USA
57+ *
58+ */
59+
60+#include <linux/module.h>
61+#include <linux/bootmem.h>
62+#include <linux/debugfs.h>
63+#include <linux/crashlog.h>
64+#include <linux/kmsg_dump.h>
65+#include <linux/module.h>
66+#include <linux/pfn.h>
67+#include <asm/io.h>
68+
69+#define CRASHLOG_PAGES 4
70+#define CRASHLOG_SIZE (CRASHLOG_PAGES * PAGE_SIZE)
71+#define CRASHLOG_MAGIC 0xa1eedead
72+
73+/*
74+ * Start the log at 1M before the end of RAM, as some boot loaders like
75+ * to use the end of the RAM for stack usage and other things
76+ * If this fails, fall back to using the last part.
77+ */
78+#define CRASHLOG_OFFSET (1024 * 1024)
79+
80+struct crashlog_data {
81+ u32 magic;
82+ u32 len;
83+ u8 data[];
84+};
85+
86+static struct debugfs_blob_wrapper crashlog_blob;
87+static unsigned long crashlog_addr = 0;
88+static struct crashlog_data *crashlog_buf;
89+static struct kmsg_dumper dump;
90+static bool first = true;
91+
92+extern struct list_head *crashlog_modules;
93+
94+void __init crashlog_init_mem(bootmem_data_t *bdata)
95+{
96+ unsigned long addr;
97+
98+ if (crashlog_addr)
99+ return;
100+
101+ addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET;
102+ if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
103+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr);
104+ bdata->node_low_pfn -= CRASHLOG_PAGES;
105+ addr = PFN_PHYS(bdata->node_low_pfn);
106+ }
107+ crashlog_addr = addr;
108+}
109+
110+static void __init crashlog_copy(void)
111+{
112+ if (crashlog_buf->magic != CRASHLOG_MAGIC)
113+ return;
114+
115+ if (!crashlog_buf->len || crashlog_buf->len >
116+ CRASHLOG_SIZE - sizeof(*crashlog_buf))
117+ return;
118+
119+ crashlog_blob.size = crashlog_buf->len;
120+ crashlog_blob.data = kmemdup(crashlog_buf->data,
121+ crashlog_buf->len, GFP_KERNEL);
122+
123+ debugfs_create_blob("crashlog", 0700, NULL, &crashlog_blob);
124+}
125+
126+static int get_maxlen(void)
127+{
128+ return CRASHLOG_SIZE - sizeof(*crashlog_buf) - crashlog_buf->len;
129+}
130+
131+static void crashlog_printf(const char *fmt, ...)
132+{
133+ va_list args;
134+ int len = get_maxlen();
135+
136+ if (!len)
137+ return;
138+
139+ va_start(args, fmt);
140+ crashlog_buf->len += vsnprintf(
141+ &crashlog_buf->data[crashlog_buf->len],
142+ len, fmt, args);
143+ va_end(args);
144+}
145+
146+static void crashlog_do_dump(struct kmsg_dumper *dumper,
147+ enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
148+ const char *s2, unsigned long l2)
149+{
150+ unsigned long s1_start, s2_start;
151+ unsigned long l1_cpy, l2_cpy;
152+ struct timeval tv;
153+ struct module *m;
154+ char *buf;
155+ int len;
156+
157+ if (!first)
158+ crashlog_printf("\n===================================\n");
159+
160+ do_gettimeofday(&tv);
161+ crashlog_printf("Time: %lu.%lu\n",
162+ (long)tv.tv_sec, (long)tv.tv_usec);
163+
164+ if (first) {
165+ crashlog_printf("Modules:");
166+ list_for_each_entry(m, crashlog_modules, list) {
167+ crashlog_printf("\t%s@%p+%x", m->name,
168+ m->module_core, m->core_size,
169+ m->module_init, m->init_size);
170+ }
171+ crashlog_printf("\n");
172+ first = false;
173+ }
174+
175+ buf = (char *)&crashlog_buf->data[crashlog_buf->len];
176+ len = get_maxlen();
177+
178+ l2_cpy = min(l2, (unsigned long)len);
179+ l1_cpy = min(l1, (unsigned long)len - l2_cpy);
180+
181+ s2_start = l2 - l2_cpy;
182+ s1_start = l1 - l1_cpy;
183+
184+ memcpy(buf, s1 + s1_start, l1_cpy);
185+ memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
186+ crashlog_buf->len += l1_cpy + l2_cpy;
187+}
188+
189+
190+int __init crashlog_init_fs(void)
191+{
192+ if (!crashlog_addr)
193+ return -ENOMEM;
194+
195+ crashlog_buf = ioremap(crashlog_addr, CRASHLOG_SIZE);
196+
197+ crashlog_copy();
198+
199+ crashlog_buf->magic = CRASHLOG_MAGIC;
200+ crashlog_buf->len = 0;
201+
202+ dump.dump = crashlog_do_dump;
203+ kmsg_dump_register(&dump);
204+
205+ return 0;
206+}
207+module_init(crashlog_init_fs);
208--- a/mm/bootmem.c
209@@ -13,6 +13,7 @@
210 #include <linux/bootmem.h>
211 #include <linux/module.h>
212 #include <linux/kmemleak.h>
213+#include <linux/crashlog.h>
214
215 #include <asm/bug.h>
216 #include <asm/io.h>
217@@ -152,6 +153,7 @@ static unsigned long __init free_all_boo
218     if (!bdata->node_bootmem_map)
219         return 0;
220
221+ crashlog_init_mem(bdata);
222     start = bdata->node_min_pfn;
223     end = bdata->node_low_pfn;
224
225--- a/kernel/module.c
226@@ -79,6 +79,9 @@ EXPORT_TRACEPOINT_SYMBOL(module_get);
227 DEFINE_MUTEX(module_mutex);
228 EXPORT_SYMBOL_GPL(module_mutex);
229 static LIST_HEAD(modules);
230+#ifdef CONFIG_CRASHLOG
231+struct list_head *crashlog_modules = &modules;
232+#endif
233
234 /* Block module loading/unloading? */
235 int modules_disabled = 0;
target/linux/generic/patches-2.6.33/930-crashlog.patch
1--- /dev/null
2@@ -0,0 +1,12 @@
3+#ifndef __CRASHLOG_H
4+#define __CRASHLOG_H
5+
6+#ifdef CONFIG_CRASHLOG
7+void __init crashlog_init_mem(struct bootmem_data *bdata);
8+#else
9+static inline void crashlog_init_mem(struct bootmem_data *bdata)
10+{
11+}
12+#endif
13+
14+#endif
15--- a/init/Kconfig
16@@ -719,6 +719,9 @@ config NET_NS
17       Allow user space to create what appear to be multiple instances
18       of the network stack.
19
20+config CRASHLOG
21+ bool "Crash logging"
22+
23 config BLK_DEV_INITRD
24     bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
25     depends on BROKEN || !FRV
26--- a/kernel/Makefile
27@@ -100,6 +100,7 @@ obj-$(CONFIG_SLOW_WORK_DEBUG) += slow-wo
28 obj-$(CONFIG_PERF_EVENTS) += perf_event.o
29 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
30 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
31+obj-$(CONFIG_CRASHLOG) += crashlog.o
32
33 ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
34 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
35--- /dev/null
36@@ -0,0 +1,171 @@
37+/*
38+ * Crash information logger
39+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
40+ *
41+ * Based on ramoops.c
42+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
43+ *
44+ * This program is free software; you can redistribute it and/or
45+ * modify it under the terms of the GNU General Public License
46+ * version 2 as published by the Free Software Foundation.
47+ *
48+ * This program is distributed in the hope that it will be useful, but
49+ * WITHOUT ANY WARRANTY; without even the implied warranty of
50+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
51+ * General Public License for more details.
52+ *
53+ * You should have received a copy of the GNU General Public License
54+ * along with this program; if not, write to the Free Software
55+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
56+ * 02110-1301 USA
57+ *
58+ */
59+
60+#include <linux/module.h>
61+#include <linux/bootmem.h>
62+#include <linux/debugfs.h>
63+#include <linux/crashlog.h>
64+#include <linux/kmsg_dump.h>
65+#include <linux/module.h>
66+#include <linux/pfn.h>
67+#include <asm/io.h>
68+
69+#define CRASHLOG_PAGES 4
70+#define CRASHLOG_SIZE (CRASHLOG_PAGES * PAGE_SIZE)
71+#define CRASHLOG_MAGIC 0xa1eedead
72+
73+/*
74+ * Start the log at 1M before the end of RAM, as some boot loaders like
75+ * to use the end of the RAM for stack usage and other things
76+ * If this fails, fall back to using the last part.
77+ */
78+#define CRASHLOG_OFFSET (1024 * 1024)
79+
80+struct crashlog_data {
81+ u32 magic;
82+ u32 len;
83+ u8 data[];
84+};
85+
86+static struct debugfs_blob_wrapper crashlog_blob;
87+static unsigned long crashlog_addr = 0;
88+static struct crashlog_data *crashlog_buf;
89+static struct kmsg_dumper dump;
90+static bool first = true;
91+
92+extern struct list_head *crashlog_modules;
93+
94+void __init crashlog_init_mem(bootmem_data_t *bdata)
95+{
96+ unsigned long addr;
97+
98+ if (crashlog_addr)
99+ return;
100+
101+ addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET;
102+ if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
103+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr);
104+ bdata->node_low_pfn -= CRASHLOG_PAGES;
105+ addr = PFN_PHYS(bdata->node_low_pfn);
106+ }
107+ crashlog_addr = addr;
108+}
109+
110+static void __init crashlog_copy(void)
111+{
112+ if (crashlog_buf->magic != CRASHLOG_MAGIC)
113+ return;
114+
115+ if (!crashlog_buf->len || crashlog_buf->len >
116+ CRASHLOG_SIZE - sizeof(*crashlog_buf))
117+ return;
118+
119+ crashlog_blob.size = crashlog_buf->len;
120+ crashlog_blob.data = kmemdup(crashlog_buf->data,
121+ crashlog_buf->len, GFP_KERNEL);
122+
123+ debugfs_create_blob("crashlog", 0700, NULL, &crashlog_blob);
124+}
125+
126+static int get_maxlen(void)
127+{
128+ return CRASHLOG_SIZE - sizeof(*crashlog_buf) - crashlog_buf->len;
129+}
130+
131+static void crashlog_printf(const char *fmt, ...)
132+{
133+ va_list args;
134+ int len = get_maxlen();
135+
136+ if (!len)
137+ return;
138+
139+ va_start(args, fmt);
140+ crashlog_buf->len += vsnprintf(
141+ &crashlog_buf->data[crashlog_buf->len],
142+ len, fmt, args);
143+ va_end(args);
144+}
145+
146+static void crashlog_do_dump(struct kmsg_dumper *dumper,
147+ enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
148+ const char *s2, unsigned long l2)
149+{
150+ unsigned long s1_start, s2_start;
151+ unsigned long l1_cpy, l2_cpy;
152+ struct timeval tv;
153+ struct module *m;
154+ char *buf;
155+ int len;
156+
157+ if (!first)
158+ crashlog_printf("\n===================================\n");
159+
160+ do_gettimeofday(&tv);
161+ crashlog_printf("Time: %lu.%lu\n",
162+ (long)tv.tv_sec, (long)tv.tv_usec);
163+
164+ if (first) {
165+ crashlog_printf("Modules:");
166+ list_for_each_entry(m, crashlog_modules, list) {
167+ crashlog_printf("\t%s@%p+%x", m->name,
168+ m->module_core, m->core_size,
169+ m->module_init, m->init_size);
170+ }
171+ crashlog_printf("\n");
172+ first = false;
173+ }
174+
175+ buf = (char *)&crashlog_buf->data[crashlog_buf->len];
176+ len = get_maxlen();
177+
178+ l2_cpy = min(l2, (unsigned long)len);
179+ l1_cpy = min(l1, (unsigned long)len - l2_cpy);
180+
181+ s2_start = l2 - l2_cpy;
182+ s1_start = l1 - l1_cpy;
183+
184+ memcpy(buf, s1 + s1_start, l1_cpy);
185+ memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
186+ crashlog_buf->len += l1_cpy + l2_cpy;
187+}
188+
189+
190+int __init crashlog_init_fs(void)
191+{
192+ if (!crashlog_addr)
193+ return -ENOMEM;
194+
195+ crashlog_buf = ioremap(crashlog_addr, CRASHLOG_SIZE);
196+
197+ crashlog_copy();
198+
199+ crashlog_buf->magic = CRASHLOG_MAGIC;
200+ crashlog_buf->len = 0;
201+
202+ dump.dump = crashlog_do_dump;
203+ kmsg_dump_register(&dump);
204+
205+ return 0;
206+}
207+module_init(crashlog_init_fs);
208--- a/mm/bootmem.c
209@@ -13,6 +13,7 @@
210 #include <linux/bootmem.h>
211 #include <linux/module.h>
212 #include <linux/kmemleak.h>
213+#include <linux/crashlog.h>
214
215 #include <asm/bug.h>
216 #include <asm/io.h>
217@@ -176,6 +177,7 @@ static unsigned long __init free_all_boo
218     if (!bdata->node_bootmem_map)
219         return 0;
220
221+ crashlog_init_mem(bdata);
222     start = bdata->node_min_pfn;
223     end = bdata->node_low_pfn;
224
225--- a/kernel/module.c
226@@ -79,6 +79,9 @@ EXPORT_TRACEPOINT_SYMBOL(module_get);
227 DEFINE_MUTEX(module_mutex);
228 EXPORT_SYMBOL_GPL(module_mutex);
229 static LIST_HEAD(modules);
230+#ifdef CONFIG_CRASHLOG
231+struct list_head *crashlog_modules = &modules;
232+#endif
233
234 /* Block module loading/unloading? */
235 int modules_disabled = 0;
target/linux/generic/patches-2.6.34/930-crashlog.patch
1--- /dev/null
2@@ -0,0 +1,12 @@
3+#ifndef __CRASHLOG_H
4+#define __CRASHLOG_H
5+
6+#ifdef CONFIG_CRASHLOG
7+void __init crashlog_init_mem(struct bootmem_data *bdata);
8+#else
9+static inline void crashlog_init_mem(struct bootmem_data *bdata)
10+{
11+}
12+#endif
13+
14+#endif
15--- a/init/Kconfig
16@@ -715,6 +715,9 @@ config NET_NS
17       Allow user space to create what appear to be multiple instances
18       of the network stack.
19
20+config CRASHLOG
21+ bool "Crash logging"
22+
23 config BLK_DEV_INITRD
24     bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
25     depends on BROKEN || !FRV
26--- a/kernel/Makefile
27@@ -105,6 +105,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.
28 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
29 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
30 obj-$(CONFIG_PADATA) += padata.o
31+obj-$(CONFIG_CRASHLOG) += crashlog.o
32
33 ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
34 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
35--- /dev/null
36@@ -0,0 +1,171 @@
37+/*
38+ * Crash information logger
39+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
40+ *
41+ * Based on ramoops.c
42+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
43+ *
44+ * This program is free software; you can redistribute it and/or
45+ * modify it under the terms of the GNU General Public License
46+ * version 2 as published by the Free Software Foundation.
47+ *
48+ * This program is distributed in the hope that it will be useful, but
49+ * WITHOUT ANY WARRANTY; without even the implied warranty of
50+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
51+ * General Public License for more details.
52+ *
53+ * You should have received a copy of the GNU General Public License
54+ * along with this program; if not, write to the Free Software
55+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
56+ * 02110-1301 USA
57+ *
58+ */
59+
60+#include <linux/module.h>
61+#include <linux/bootmem.h>
62+#include <linux/debugfs.h>
63+#include <linux/crashlog.h>
64+#include <linux/kmsg_dump.h>
65+#include <linux/module.h>
66+#include <linux/pfn.h>
67+#include <asm/io.h>
68+
69+#define CRASHLOG_PAGES 4
70+#define CRASHLOG_SIZE (CRASHLOG_PAGES * PAGE_SIZE)
71+#define CRASHLOG_MAGIC 0xa1eedead
72+
73+/*
74+ * Start the log at 1M before the end of RAM, as some boot loaders like
75+ * to use the end of the RAM for stack usage and other things
76+ * If this fails, fall back to using the last part.
77+ */
78+#define CRASHLOG_OFFSET (1024 * 1024)
79+
80+struct crashlog_data {
81+ u32 magic;
82+ u32 len;
83+ u8 data[];
84+};
85+
86+static struct debugfs_blob_wrapper crashlog_blob;
87+static unsigned long crashlog_addr = 0;
88+static struct crashlog_data *crashlog_buf;
89+static struct kmsg_dumper dump;
90+static bool first = true;
91+
92+extern struct list_head *crashlog_modules;
93+
94+void __init crashlog_init_mem(bootmem_data_t *bdata)
95+{
96+ unsigned long addr;
97+
98+ if (crashlog_addr)
99+ return;
100+
101+ addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET;
102+ if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
103+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr);
104+ bdata->node_low_pfn -= CRASHLOG_PAGES;
105+ addr = PFN_PHYS(bdata->node_low_pfn);
106+ }
107+ crashlog_addr = addr;
108+}
109+
110+static void __init crashlog_copy(void)
111+{
112+ if (crashlog_buf->magic != CRASHLOG_MAGIC)
113+ return;
114+
115+ if (!crashlog_buf->len || crashlog_buf->len >
116+ CRASHLOG_SIZE - sizeof(*crashlog_buf))
117+ return;
118+
119+ crashlog_blob.size = crashlog_buf->len;
120+ crashlog_blob.data = kmemdup(crashlog_buf->data,
121+ crashlog_buf->len, GFP_KERNEL);
122+
123+ debugfs_create_blob("crashlog", 0700, NULL, &crashlog_blob);
124+}
125+
126+static int get_maxlen(void)
127+{
128+ return CRASHLOG_SIZE - sizeof(*crashlog_buf) - crashlog_buf->len;
129+}
130+
131+static void crashlog_printf(const char *fmt, ...)
132+{
133+ va_list args;
134+ int len = get_maxlen();
135+
136+ if (!len)
137+ return;
138+
139+ va_start(args, fmt);
140+ crashlog_buf->len += vsnprintf(
141+ &crashlog_buf->data[crashlog_buf->len],
142+ len, fmt, args);
143+ va_end(args);
144+}
145+
146+static void crashlog_do_dump(struct kmsg_dumper *dumper,
147+ enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
148+ const char *s2, unsigned long l2)
149+{
150+ unsigned long s1_start, s2_start;
151+ unsigned long l1_cpy, l2_cpy;
152+ struct timeval tv;
153+ struct module *m;
154+ char *buf;
155+ int len;
156+
157+ if (!first)
158+ crashlog_printf("\n===================================\n");
159+
160+ do_gettimeofday(&tv);
161+ crashlog_printf("Time: %lu.%lu\n",
162+ (long)tv.tv_sec, (long)tv.tv_usec);
163+
164+ if (first) {
165+ crashlog_printf("Modules:");
166+ list_for_each_entry(m, crashlog_modules, list) {
167+ crashlog_printf("\t%s@%p+%x", m->name,
168+ m->module_core, m->core_size,
169+ m->module_init, m->init_size);
170+ }
171+ crashlog_printf("\n");
172+ first = false;
173+ }
174+
175+ buf = (char *)&crashlog_buf->data[crashlog_buf->len];
176+ len = get_maxlen();
177+
178+ l2_cpy = min(l2, (unsigned long)len);
179+ l1_cpy = min(l1, (unsigned long)len - l2_cpy);
180+
181+ s2_start = l2 - l2_cpy;
182+ s1_start = l1 - l1_cpy;
183+
184+ memcpy(buf, s1 + s1_start, l1_cpy);
185+ memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
186+ crashlog_buf->len += l1_cpy + l2_cpy;
187+}
188+
189+
190+int __init crashlog_init_fs(void)
191+{
192+ if (!crashlog_addr)
193+ return -ENOMEM;
194+
195+ crashlog_buf = ioremap(crashlog_addr, CRASHLOG_SIZE);
196+
197+ crashlog_copy();
198+
199+ crashlog_buf->magic = CRASHLOG_MAGIC;
200+ crashlog_buf->len = 0;
201+
202+ dump.dump = crashlog_do_dump;
203+ kmsg_dump_register(&dump);
204+
205+ return 0;
206+}
207+module_init(crashlog_init_fs);
208--- a/mm/bootmem.c
209@@ -15,6 +15,7 @@
210 #include <linux/module.h>
211 #include <linux/kmemleak.h>
212 #include <linux/range.h>
213+#include <linux/crashlog.h>
214
215 #include <asm/bug.h>
216 #include <asm/io.h>
217@@ -226,6 +227,7 @@ static unsigned long __init free_all_boo
218     if (!bdata->node_bootmem_map)
219         return 0;
220
221+ crashlog_init_mem(bdata);
222     start = bdata->node_min_pfn;
223     end = bdata->node_low_pfn;
224
225--- a/kernel/module.c
226@@ -79,6 +79,9 @@ EXPORT_TRACEPOINT_SYMBOL(module_get);
227 DEFINE_MUTEX(module_mutex);
228 EXPORT_SYMBOL_GPL(module_mutex);
229 static LIST_HEAD(modules);
230+#ifdef CONFIG_CRASHLOG
231+struct list_head *crashlog_modules = &modules;
232+#endif
233
234 /* Block module loading/unloading? */
235 int modules_disabled = 0;
target/linux/generic/patches-2.6.35/930-crashlog.patch
1--- /dev/null
2@@ -0,0 +1,12 @@
3+#ifndef __CRASHLOG_H
4+#define __CRASHLOG_H
5+
6+#ifdef CONFIG_CRASHLOG
7+void __init crashlog_init_mem(struct bootmem_data *bdata);
8+#else
9+static inline void crashlog_init_mem(struct bootmem_data *bdata)
10+{
11+}
12+#endif
13+
14+#endif
15--- a/init/Kconfig
16@@ -749,6 +749,9 @@ config NET_NS
17       Allow user space to create what appear to be multiple instances
18       of the network stack.
19
20+config CRASHLOG
21+ bool "Crash logging"
22+
23 config BLK_DEV_INITRD
24     bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
25     depends on BROKEN || !FRV
26--- a/kernel/Makefile
27@@ -105,6 +105,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.
28 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
29 obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
30 obj-$(CONFIG_PADATA) += padata.o
31+obj-$(CONFIG_CRASHLOG) += crashlog.o
32
33 ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
34 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
35--- /dev/null
36@@ -0,0 +1,171 @@
37+/*
38+ * Crash information logger
39+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
40+ *
41+ * Based on ramoops.c
42+ * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
43+ *
44+ * This program is free software; you can redistribute it and/or
45+ * modify it under the terms of the GNU General Public License
46+ * version 2 as published by the Free Software Foundation.
47+ *
48+ * This program is distributed in the hope that it will be useful, but
49+ * WITHOUT ANY WARRANTY; without even the implied warranty of
50+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
51+ * General Public License for more details.
52+ *
53+ * You should have received a copy of the GNU General Public License
54+ * along with this program; if not, write to the Free Software
55+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
56+ * 02110-1301 USA
57+ *
58+ */
59+
60+#include <linux/module.h>
61+#include <linux/bootmem.h>
62+#include <linux/debugfs.h>
63+#include <linux/crashlog.h>
64+#include <linux/kmsg_dump.h>
65+#include <linux/module.h>
66+#include <linux/pfn.h>
67+#include <asm/io.h>
68+
69+#define CRASHLOG_PAGES 4
70+#define CRASHLOG_SIZE (CRASHLOG_PAGES * PAGE_SIZE)
71+#define CRASHLOG_MAGIC 0xa1eedead
72+
73+/*
74+ * Start the log at 1M before the end of RAM, as some boot loaders like
75+ * to use the end of the RAM for stack usage and other things
76+ * If this fails, fall back to using the last part.
77+ */
78+#define CRASHLOG_OFFSET (1024 * 1024)
79+
80+struct crashlog_data {
81+ u32 magic;
82+ u32 len;
83+ u8 data[];
84+};
85+
86+static struct debugfs_blob_wrapper crashlog_blob;
87+static unsigned long crashlog_addr = 0;
88+static struct crashlog_data *crashlog_buf;
89+static struct kmsg_dumper dump;
90+static bool first = true;
91+
92+extern struct list_head *crashlog_modules;
93+
94+void __init crashlog_init_mem(bootmem_data_t *bdata)
95+{
96+ unsigned long addr;
97+
98+ if (crashlog_addr)
99+ return;
100+
101+ addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET;
102+ if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
103+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr);
104+ bdata->node_low_pfn -= CRASHLOG_PAGES;
105+ addr = PFN_PHYS(bdata->node_low_pfn);
106+ }
107+ crashlog_addr = addr;
108+}
109+
110+static void __init crashlog_copy(void)
111+{
112+ if (crashlog_buf->magic != CRASHLOG_MAGIC)
113+ return;
114+
115+ if (!crashlog_buf->len || crashlog_buf->len >
116+ CRASHLOG_SIZE - sizeof(*crashlog_buf))
117+ return;
118+
119+ crashlog_blob.size = crashlog_buf->len;
120+ crashlog_blob.data = kmemdup(crashlog_buf->data,
121+ crashlog_buf->len, GFP_KERNEL);
122+
123+ debugfs_create_blob("crashlog", 0700, NULL, &crashlog_blob);
124+}
125+
126+static int get_maxlen(void)
127+{
128+ return CRASHLOG_SIZE - sizeof(*crashlog_buf) - crashlog_buf->len;
129+}
130+
131+static void crashlog_printf(const char *fmt, ...)
132+{
133+ va_list args;
134+ int len = get_maxlen();
135+
136+ if (!len)
137+ return;
138+
139+ va_start(args, fmt);
140+ crashlog_buf->len += vsnprintf(
141+ &crashlog_buf->data[crashlog_buf->len],
142+ len, fmt, args);
143+ va_end(args);
144+}
145+
146+static void crashlog_do_dump(struct kmsg_dumper *dumper,
147+ enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
148+ const char *s2, unsigned long l2)
149+{
150+ unsigned long s1_start, s2_start;
151+ unsigned long l1_cpy, l2_cpy;
152+ struct timeval tv;
153+ struct module *m;
154+ char *buf;
155+ int len;
156+
157+ if (!first)
158+ crashlog_printf("\n===================================\n");
159+
160+ do_gettimeofday(&tv);
161+ crashlog_printf("Time: %lu.%lu\n",
162+ (long)tv.tv_sec, (long)tv.tv_usec);
163+
164+ if (first) {
165+ crashlog_printf("Modules:");
166+ list_for_each_entry(m, crashlog_modules, list) {
167+ crashlog_printf("\t%s@%p+%x", m->name,
168+ m->module_core, m->core_size,
169+ m->module_init, m->init_size);
170+ }
171+ crashlog_printf("\n");
172+ first = false;
173+ }
174+
175+ buf = (char *)&crashlog_buf->data[crashlog_buf->len];
176+ len = get_maxlen();
177+
178+ l2_cpy = min(l2, (unsigned long)len);
179+ l1_cpy = min(l1, (unsigned long)len - l2_cpy);
180+
181+ s2_start = l2 - l2_cpy;
182+ s1_start = l1 - l1_cpy;
183+
184+ memcpy(buf, s1 + s1_start, l1_cpy);
185+ memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
186+ crashlog_buf->len += l1_cpy + l2_cpy;
187+}
188+
189+
190+int __init crashlog_init_fs(void)
191+{
192+ if (!crashlog_addr)
193+ return -ENOMEM;
194+
195+ crashlog_buf = ioremap(crashlog_addr, CRASHLOG_SIZE);
196+
197+ crashlog_copy();
198+
199+ crashlog_buf->magic = CRASHLOG_MAGIC;
200+ crashlog_buf->len = 0;
201+
202+ dump.dump = crashlog_do_dump;
203+ kmsg_dump_register(&dump);
204+
205+ return 0;
206+}
207+module_init(crashlog_init_fs);
208--- a/mm/bootmem.c
209@@ -15,6 +15,7 @@
210 #include <linux/module.h>
211 #include <linux/kmemleak.h>
212 #include <linux/range.h>
213+#include <linux/crashlog.h>
214
215 #include <asm/bug.h>
216 #include <asm/io.h>
217@@ -226,6 +227,7 @@ static unsigned long __init free_all_boo
218     if (!bdata->node_bootmem_map)
219         return 0;
220
221+ crashlog_init_mem(bdata);
222     start = bdata->node_min_pfn;
223     end = bdata->node_low_pfn;
224
225--- a/kernel/module.c
226@@ -84,6 +84,9 @@ static LIST_HEAD(modules);
227 #ifdef CONFIG_KGDB_KDB
228 struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
229 #endif /* CONFIG_KGDB_KDB */
230+#ifdef CONFIG_CRASHLOG
231+struct list_head *crashlog_modules = &modules;
232+#endif
233
234
235 /* Block module loading/unloading? */

Archive Download the corresponding diff file



interactive