source: trunk/target/linux/generic/patches-2.6.32/931-crashlog.patch @ 22305

Last change on this file since 22305 was 22305, checked in by nbd, 6 years ago

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

File size: 6.1 KB
  • new file include/linux/crashlog.h

    - +  
     1#ifndef __CRASHLOG_H 
     2#define __CRASHLOG_H 
     3 
     4#ifdef CONFIG_CRASHLOG 
     5void __init crashlog_init_mem(struct bootmem_data *bdata); 
     6#else 
     7static inline void crashlog_init_mem(struct bootmem_data *bdata) 
     8{ 
     9} 
     10#endif 
     11 
     12#endif 
  • init/Kconfig

    a b config NET_NS 
    710710          Allow user space to create what appear to be multiple instances 
    711711          of the network stack. 
    712712 
     713config CRASHLOG 
     714        bool "Crash logging" 
     715 
    713716config BLK_DEV_INITRD 
    714717        bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" 
    715718        depends on BROKEN || !FRV 
  • kernel/Makefile

    a b obj-$(CONFIG_SMP) += sched_cpupri.o 
    9696obj-$(CONFIG_SLOW_WORK) += slow-work.o 
    9797obj-$(CONFIG_SLOW_WORK_DEBUG) += slow-work-debugfs.o 
    9898obj-$(CONFIG_PERF_EVENTS) += perf_event.o 
     99obj-$(CONFIG_CRASHLOG) += crashlog.o 
    99100 
    100101ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) 
    101102# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is 
  • new file kernel/crashlog.c

    - +  
     1/* 
     2 * Crash information logger 
     3 * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org> 
     4 * 
     5 * Based on ramoops.c 
     6 *   Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com> 
     7 * 
     8 * This program is free software; you can redistribute it and/or 
     9 * modify it under the terms of the GNU General Public License 
     10 * version 2 as published by the Free Software Foundation. 
     11 * 
     12 * This program is distributed in the hope that it will be useful, but 
     13 * WITHOUT ANY WARRANTY; without even the implied warranty of 
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     15 * General Public License for more details. 
     16 * 
     17 * You should have received a copy of the GNU General Public License 
     18 * along with this program; if not, write to the Free Software 
     19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 
     20 * 02110-1301 USA 
     21 * 
     22 */ 
     23 
     24#include <linux/module.h> 
     25#include <linux/bootmem.h> 
     26#include <linux/debugfs.h> 
     27#include <linux/crashlog.h> 
     28#include <linux/kmsg_dump.h> 
     29#include <linux/module.h> 
     30#include <linux/pfn.h> 
     31#include <asm/io.h> 
     32 
     33#define CRASHLOG_PAGES  4 
     34#define CRASHLOG_SIZE   (CRASHLOG_PAGES * PAGE_SIZE) 
     35#define CRASHLOG_MAGIC  0xa1eedead 
     36 
     37/* 
     38 * Start the log at 1M before the end of RAM, as some boot loaders like 
     39 * to use the end of the RAM for stack usage and other things 
     40 * If this fails, fall back to using the last part. 
     41 */ 
     42#define CRASHLOG_OFFSET (1024 * 1024) 
     43 
     44struct crashlog_data { 
     45        u32 magic; 
     46        u32 len; 
     47        u8 data[]; 
     48}; 
     49 
     50static struct debugfs_blob_wrapper crashlog_blob; 
     51static unsigned long crashlog_addr = 0; 
     52static struct crashlog_data *crashlog_buf; 
     53static struct kmsg_dumper dump; 
     54static bool first = true; 
     55 
     56extern struct list_head *crashlog_modules; 
     57 
     58void __init crashlog_init_mem(bootmem_data_t *bdata) 
     59{ 
     60        unsigned long addr; 
     61 
     62        if (crashlog_addr) 
     63                return; 
     64 
     65        addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET; 
     66        if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) { 
     67                printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr); 
     68                bdata->node_low_pfn -= CRASHLOG_PAGES; 
     69                addr = PFN_PHYS(bdata->node_low_pfn); 
     70        } 
     71        crashlog_addr = addr; 
     72} 
     73 
     74static void __init crashlog_copy(void) 
     75{ 
     76        if (crashlog_buf->magic != CRASHLOG_MAGIC) 
     77                return; 
     78 
     79        if (!crashlog_buf->len || crashlog_buf->len > 
     80            CRASHLOG_SIZE - sizeof(*crashlog_buf)) 
     81                return; 
     82 
     83        crashlog_blob.size = crashlog_buf->len; 
     84        crashlog_blob.data = kmemdup(crashlog_buf->data, 
     85                crashlog_buf->len, GFP_KERNEL); 
     86 
     87        debugfs_create_blob("crashlog", 0700, NULL, &crashlog_blob); 
     88} 
     89 
     90static int get_maxlen(void) 
     91{ 
     92        return CRASHLOG_SIZE - sizeof(*crashlog_buf) - crashlog_buf->len; 
     93} 
     94 
     95static void crashlog_printf(const char *fmt, ...) 
     96{ 
     97        va_list args; 
     98        int len = get_maxlen(); 
     99 
     100        if (!len) 
     101                return; 
     102 
     103        va_start(args, fmt); 
     104        crashlog_buf->len += vsnprintf( 
     105                &crashlog_buf->data[crashlog_buf->len], 
     106                len, fmt, args); 
     107        va_end(args); 
     108} 
     109 
     110static void crashlog_do_dump(struct kmsg_dumper *dumper, 
     111                enum kmsg_dump_reason reason, const char *s1, unsigned long l1, 
     112                const char *s2, unsigned long l2) 
     113{ 
     114        unsigned long s1_start, s2_start; 
     115        unsigned long l1_cpy, l2_cpy; 
     116        struct timeval tv; 
     117        struct module *m; 
     118        char *buf; 
     119        int len; 
     120 
     121        if (!first) 
     122                crashlog_printf("\n===================================\n"); 
     123 
     124        do_gettimeofday(&tv); 
     125        crashlog_printf("Time: %lu.%lu\n", 
     126                (long)tv.tv_sec, (long)tv.tv_usec); 
     127 
     128        if (first) { 
     129                crashlog_printf("Modules:"); 
     130                list_for_each_entry(m, crashlog_modules, list) { 
     131                        crashlog_printf("\t%s@%p+%x", m->name, 
     132                        m->module_core, m->core_size, 
     133                        m->module_init, m->init_size); 
     134                } 
     135                crashlog_printf("\n"); 
     136                first = false; 
     137        } 
     138 
     139        buf = (char *)&crashlog_buf->data[crashlog_buf->len]; 
     140        len = get_maxlen(); 
     141 
     142        l2_cpy = min(l2, (unsigned long)len); 
     143        l1_cpy = min(l1, (unsigned long)len - l2_cpy); 
     144 
     145        s2_start = l2 - l2_cpy; 
     146        s1_start = l1 - l1_cpy; 
     147 
     148        memcpy(buf, s1 + s1_start, l1_cpy); 
     149        memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy); 
     150        crashlog_buf->len += l1_cpy + l2_cpy; 
     151} 
     152 
     153 
     154int __init crashlog_init_fs(void) 
     155{ 
     156        if (!crashlog_addr) 
     157                return -ENOMEM; 
     158 
     159        crashlog_buf = ioremap(crashlog_addr, CRASHLOG_SIZE); 
     160 
     161        crashlog_copy(); 
     162 
     163        crashlog_buf->magic = CRASHLOG_MAGIC; 
     164        crashlog_buf->len = 0; 
     165 
     166        dump.dump = crashlog_do_dump; 
     167        kmsg_dump_register(&dump); 
     168 
     169        return 0; 
     170} 
     171module_init(crashlog_init_fs); 
  • mm/bootmem.c

    a b  
    1313#include <linux/bootmem.h> 
    1414#include <linux/module.h> 
    1515#include <linux/kmemleak.h> 
     16#include <linux/crashlog.h> 
    1617 
    1718#include <asm/bug.h> 
    1819#include <asm/io.h> 
    static unsigned long __init free_all_boo 
    152153        if (!bdata->node_bootmem_map) 
    153154                return 0; 
    154155 
     156        crashlog_init_mem(bdata); 
    155157        start = bdata->node_min_pfn; 
    156158        end = bdata->node_low_pfn; 
    157159 
  • kernel/module.c

    a b EXPORT_TRACEPOINT_SYMBOL(module_get); 
    7979DEFINE_MUTEX(module_mutex); 
    8080EXPORT_SYMBOL_GPL(module_mutex); 
    8181static LIST_HEAD(modules); 
     82#ifdef CONFIG_CRASHLOG 
     83struct list_head *crashlog_modules = &modules; 
     84#endif 
    8285 
    8386/* Block module loading/unloading? */ 
    8487int modules_disabled = 0; 
Note: See TracBrowser for help on using the repository browser.