source: trunk/target/linux/generic/patches-3.3/330-mips-add-crash-and-kdump-support.patch @ 29986

Last change on this file since 29986 was 29986, checked in by jogo, 5 years ago

kernel: add preliminary support for linux 3.3

Based on 3.3-rc2

File size: 15.5 KB
  • arch/mips/kernel/Makefile

    From eee16330c9de9adf7880cce9f1d32e13f89706bb Mon Sep 17 00:00:00 2001
    From: Wu Zhangjin <wuzhangjin@gmail.com>
    Date: Tue, 11 Jan 2011 13:16:47 +0000
    Subject: MIPS: Add crash and kdump support
    
    From: http://patchwork.linux-mips.org/patch/1025/
    
    Hello folks,
    
    Please find here MIPS crash and kdump patches.
    This is patch set of 3 patches:
    1. generic MIPS changes (kernel);
    2. MIPS Cavium Octeon board kexec/kdump code (kernel);
    3. Kexec user space MIPS changes.
    
    Patches were tested on the latest linux-mips@ git kernel and the latest
    kexec-tools git on Cavium Octeon 50xx board.
    
    I also made the same code working on RMI XLR/XLS boards for both
    mips32 and mips64 kernels.
    
    Best regards,
    Maxim Uvarov.
    
    ------
    [ Zhangjin: Several trivial building failure has been fixed.
    
    Note: the 2nd patch can not be cleanly applied, but may be a good
    reference for the other board development:
    
    	+ MIPS Cavium Octeon board kexec,kdump support
    	http://patchwork.linux-mips.org/patch/1026/
    
    And the 3rd patch has already been merged into the mainline kexec-tools:
    
    	+ some kexec MIPS improvements
    	http://patchwork.linux-mips.org/patch/1027/
    
    kexec-tools is available here:
    
    	+ http://horms.net/projects/kexec/
    	git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
    ]
    Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
    ---
    (limited to 'arch/mips/kernel')
    
    a b obj-$(CONFIG_I8253) += i8253.o 
    9797 
    9898obj-$(CONFIG_GPIO_TXX9)         += gpio_txx9.o 
    9999 
    100 obj-$(CONFIG_KEXEC)             += machine_kexec.o relocate_kernel.o 
     100obj-$(CONFIG_KEXEC)             += machine_kexec.o relocate_kernel.o crash.o 
     101obj-$(CONFIG_CRASH_DUMP)        += crash_dump.o 
    101102obj-$(CONFIG_EARLY_PRINTK)      += early_printk.o 
    102103obj-$(CONFIG_SPINLOCK_TEST)     += spinlock_test.o 
    103104obj-$(CONFIG_MIPS_MACHINE)      += mips_machine.o 
  • new file arch/mips/kernel/crash.c

    - +  
     1#include <linux/kernel.h> 
     2#include <linux/smp.h> 
     3#include <linux/reboot.h> 
     4#include <linux/kexec.h> 
     5#include <linux/bootmem.h> 
     6#include <linux/crash_dump.h> 
     7#include <linux/delay.h> 
     8#include <linux/init.h> 
     9#include <linux/irq.h> 
     10#include <linux/types.h> 
     11#include <linux/sched.h> 
     12 
     13#ifdef CONFIG_CRASH_DUMP 
     14unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; 
     15#endif 
     16 
     17/* This keeps a track of which one is crashing cpu. */ 
     18int crashing_cpu = -1; 
     19static cpumask_t cpus_in_crash = CPU_MASK_NONE; 
     20 
     21#ifdef CONFIG_SMP 
     22void crash_shutdown_secondary(void *ignore) 
     23{ 
     24        struct pt_regs *regs; 
     25        int cpu = smp_processor_id(); 
     26 
     27        regs = task_pt_regs(current); 
     28 
     29        if (!cpu_online(cpu)) 
     30                return; 
     31 
     32        local_irq_disable(); 
     33        if (!cpu_isset(cpu, cpus_in_crash)) 
     34                crash_save_cpu(regs, cpu); 
     35        cpu_set(cpu, cpus_in_crash); 
     36 
     37        while (!atomic_read(&kexec_ready_to_reboot)) 
     38                cpu_relax(); 
     39        relocated_kexec_smp_wait(NULL); 
     40        /* NOTREACHED */ 
     41} 
     42 
     43static void crash_kexec_prepare_cpus(void) 
     44{ 
     45        unsigned int msecs; 
     46 
     47        unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */ 
     48 
     49        dump_send_ipi(crash_shutdown_secondary); 
     50        smp_wmb(); 
     51 
     52        /* 
     53         * The crash CPU sends an IPI and wait for other CPUs to 
     54         * respond. Delay of at least 10 seconds. 
     55         */ 
     56        printk(KERN_EMERG "Sending IPI to other cpus...\n"); 
     57        msecs = 10000; 
     58        while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) { 
     59                cpu_relax(); 
     60                mdelay(1); 
     61        } 
     62} 
     63 
     64#else 
     65static void crash_kexec_prepare_cpus(void) {} 
     66#endif 
     67 
     68void default_machine_crash_shutdown(struct pt_regs *regs) 
     69{ 
     70        local_irq_disable(); 
     71        crashing_cpu = smp_processor_id(); 
     72        crash_save_cpu(regs, crashing_cpu); 
     73        crash_kexec_prepare_cpus(); 
     74        cpu_set(crashing_cpu, cpus_in_crash); 
     75} 
  • new file arch/mips/kernel/crash_dump.c

    - +  
     1#include <linux/highmem.h> 
     2#include <linux/bootmem.h> 
     3#include <linux/crash_dump.h> 
     4#include <asm/uaccess.h> 
     5 
     6#ifdef CONFIG_PROC_VMCORE 
     7static int __init parse_elfcorehdr(char *p) 
     8{ 
     9        if (p) 
     10                elfcorehdr_addr = memparse(p, &p); 
     11        return 1; 
     12} 
     13__setup("elfcorehdr=", parse_elfcorehdr); 
     14#endif 
     15 
     16static int __init parse_savemaxmem(char *p) 
     17{ 
     18        if (p) 
     19                saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; 
     20 
     21        return 1; 
     22} 
     23__setup("savemaxmem=", parse_savemaxmem); 
     24 
     25 
     26static void *kdump_buf_page; 
     27 
     28/** 
     29 * copy_oldmem_page - copy one page from "oldmem" 
     30 * @pfn: page frame number to be copied 
     31 * @buf: target memory address for the copy; this can be in kernel address 
     32 *      space or user address space (see @userbuf) 
     33 * @csize: number of bytes to copy 
     34 * @offset: offset in bytes into the page (based on pfn) to begin the copy 
     35 * @userbuf: if set, @buf is in user address space, use copy_to_user(), 
     36 *      otherwise @buf is in kernel address space, use memcpy(). 
     37 * 
     38 * Copy a page from "oldmem". For this page, there is no pte mapped 
     39 * in the current kernel. 
     40 * 
     41 * Calling copy_to_user() in atomic context is not desirable. Hence first 
     42 * copying the data to a pre-allocated kernel page and then copying to user 
     43 * space in non-atomic context. 
     44 */ 
     45ssize_t copy_oldmem_page(unsigned long pfn, char *buf, 
     46                size_t csize, unsigned long offset, int userbuf) 
     47{ 
     48        void  *vaddr; 
     49 
     50        if (!csize) 
     51                return 0; 
     52 
     53        vaddr = kmap_atomic_pfn(pfn, KM_PTE0); 
     54 
     55        if (!userbuf) { 
     56                memcpy(buf, (vaddr + offset), csize); 
     57                kunmap_atomic(vaddr, KM_PTE0); 
     58        } else { 
     59                if (!kdump_buf_page) { 
     60                        printk(KERN_WARNING "Kdump: Kdump buffer page not" 
     61                                " allocated\n"); 
     62                        return -EFAULT; 
     63                } 
     64                copy_page(kdump_buf_page, vaddr); 
     65                kunmap_atomic(vaddr, KM_PTE0); 
     66                if (copy_to_user(buf, (kdump_buf_page + offset), csize)) 
     67                        return -EFAULT; 
     68        } 
     69 
     70        return csize; 
     71} 
     72 
     73static int __init kdump_buf_page_init(void) 
     74{ 
     75        int ret = 0; 
     76 
     77        kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL); 
     78        if (!kdump_buf_page) { 
     79                printk(KERN_WARNING "Kdump: Failed to allocate kdump buffer" 
     80                         " page\n"); 
     81                ret = -ENOMEM; 
     82        } 
     83 
     84        return ret; 
     85} 
     86arch_initcall(kdump_buf_page_init); 
  • arch/mips/kernel/machine_kexec.c

    a b extern const size_t relocate_new_kernel_ 
    1919extern unsigned long kexec_start_address; 
    2020extern unsigned long kexec_indirection_page; 
    2121 
     22int (*_machine_kexec_prepare)(struct kimage *) = NULL; 
     23void (*_machine_kexec_shutdown)(void) = NULL; 
     24void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL; 
     25#ifdef CONFIG_SMP 
     26void (*relocated_kexec_smp_wait) (void *); 
     27atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0); 
     28#endif 
     29 
    2230int 
    2331machine_kexec_prepare(struct kimage *kimage) 
    2432{ 
     33        if (_machine_kexec_prepare) 
     34                return _machine_kexec_prepare(kimage); 
    2535        return 0; 
    2636} 
    2737 
    machine_kexec_cleanup(struct kimage *kim 
    3343void 
    3444machine_shutdown(void) 
    3545{ 
     46        if (_machine_kexec_shutdown) 
     47                _machine_kexec_shutdown(); 
    3648} 
    3749 
    3850void 
    3951machine_crash_shutdown(struct pt_regs *regs) 
    4052{ 
     53        if (_machine_crash_shutdown) 
     54                _machine_crash_shutdown(regs); 
     55        else 
     56                default_machine_crash_shutdown(regs); 
    4157} 
    4258 
    4359typedef void (*noretfun_t)(void) __attribute__((noreturn)); 
    machine_kexec(struct kimage *image) 
    5268        reboot_code_buffer = 
    5369          (unsigned long)page_address(image->control_code_page); 
    5470 
    55         kexec_start_address = (unsigned long) phys_to_virt(image->start); 
     71        kexec_start_address = 
     72          (unsigned long) phys_to_virt(image->start); 
     73 
    5674        kexec_indirection_page = 
    5775                (unsigned long) phys_to_virt(image->head & PAGE_MASK); 
    5876 
    machine_kexec(struct kimage *image) 
    6381         * The generic kexec code builds a page list with physical 
    6482         * addresses. they are directly accessible through KSEG0 (or 
    6583         * CKSEG0 or XPHYS if on 64bit system), hence the 
    66          * pys_to_virt() call. 
     84         * phys_to_virt() call. 
    6785         */ 
    6886        for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE); 
    6987             ptr = (entry & IND_INDIRECTION) ? 
    machine_kexec(struct kimage *image) 
    8199        printk("Will call new kernel at %08lx\n", image->start); 
    82100        printk("Bye ...\n"); 
    83101        __flush_cache_all(); 
     102#ifdef CONFIG_SMP 
     103        /* All secondary cpus now may jump to kexec_wait cycle */ 
     104        relocated_kexec_smp_wait = reboot_code_buffer + 
     105                (void *)(kexec_smp_wait - relocate_new_kernel); 
     106        smp_wmb(); 
     107        atomic_set(&kexec_ready_to_reboot, 1); 
     108#endif 
    84109        ((noretfun_t) reboot_code_buffer)(); 
    85110} 
     111 
  • arch/mips/kernel/relocate_kernel.S

    a b  
    1515#include <asm/addrspace.h> 
    1616 
    1717LEAF(relocate_new_kernel) 
     18        PTR_L a0,       arg0 
     19        PTR_L a1,       arg1 
     20        PTR_L a2,       arg2 
     21        PTR_L a3,       arg3 
     22 
    1823        PTR_L           s0, kexec_indirection_page 
    1924        PTR_L           s1, kexec_start_address 
    2025 
    process_entry: 
    2631        and             s3, s2, 0x1 
    2732        beq             s3, zero, 1f 
    2833        and             s4, s2, ~0x1    /* store destination addr in s4 */ 
    29         move            a0, s4 
    3034        b               process_entry 
    3135 
    32361: 
    copy_word: 
    6064        b               process_entry 
    6165 
    6266done: 
     67#ifdef CONFIG_SMP 
     68        /* kexec_flag reset is signal to other CPUs what kernel 
     69           was moved to it's location. Note - we need relocated address 
     70           of kexec_flag.  */ 
     71 
     72        bal             1f 
     73 1:     move            t1,ra; 
     74        PTR_LA          t2,1b 
     75        PTR_LA          t0,kexec_flag 
     76        PTR_SUB         t0,t0,t2; 
     77        PTR_ADD         t0,t1,t0; 
     78        LONG_S          zero,(t0) 
     79#endif 
     80 
     81        sync 
    6382        /* jump to kexec_start_address */ 
    6483        j               s1 
    6584        END(relocate_new_kernel) 
    6685 
    67 kexec_start_address: 
    68         EXPORT(kexec_start_address) 
     86#ifdef CONFIG_SMP 
     87/* 
     88 * Other CPUs should wait until code is relocated and 
     89 * then start at entry (?) point. 
     90 */ 
     91LEAF(kexec_smp_wait) 
     92        PTR_L           a0, s_arg0 
     93        PTR_L           a1, s_arg1 
     94        PTR_L           a2, s_arg2 
     95        PTR_L           a3, s_arg3 
     96        PTR_L           s1, kexec_start_address 
     97 
     98        /* Non-relocated address works for args and kexec_start_address ( old 
     99         * kernel is not overwritten). But we need relocated address of 
     100         * kexec_flag. 
     101         */ 
     102 
     103        bal             1f 
     1041:      move            t1,ra; 
     105        PTR_LA          t2,1b 
     106        PTR_LA          t0,kexec_flag 
     107        PTR_SUB         t0,t0,t2; 
     108        PTR_ADD         t0,t1,t0; 
     109 
     1101:      LONG_L          s0, (t0) 
     111        bne             s0, zero,1b 
     112 
     113        sync 
     114        j               s1 
     115        END(kexec_smp_wait) 
     116#endif 
     117 
     118#ifdef __mips64 
     119       /* all PTR's must be aligned to 8 byte in 64-bit mode */ 
     120       .align  3 
     121#endif 
     122 
     123/* All parameters to new kernel are passed in registers a0-a3. 
     124 * kexec_args[0..3] are uses to prepare register values. 
     125 */ 
     126 
     127EXPORT(kexec_args) 
     128arg0:   PTR             0x0 
     129arg1:   PTR             0x0 
     130arg2:   PTR             0x0 
     131arg3:   PTR             0x0 
     132        .size   kexec_args,PTRSIZE*4 
     133 
     134#ifdef CONFIG_SMP 
     135/* 
     136 * Secondary CPUs may have different kernel parameters in 
     137 * their registers a0-a3. secondary_kexec_args[0..3] are used 
     138 * to prepare register values. 
     139 */ 
     140EXPORT(secondary_kexec_args) 
     141s_arg0: PTR             0x0 
     142s_arg1: PTR             0x0 
     143s_arg2: PTR             0x0 
     144s_arg3: PTR             0x0 
     145        .size   secondary_kexec_args,PTRSIZE*4 
     146kexec_flag: 
     147        LONG            0x1 
     148 
     149#endif 
     150 
     151EXPORT(kexec_start_address) 
    69152        PTR             0x0 
    70153        .size           kexec_start_address, PTRSIZE 
    71154 
    72 kexec_indirection_page: 
    73         EXPORT(kexec_indirection_page) 
     155EXPORT(kexec_indirection_page) 
    74156        PTR             0 
    75157        .size           kexec_indirection_page, PTRSIZE 
    76158 
    77159relocate_new_kernel_end: 
    78160 
    79 relocate_new_kernel_size: 
    80         EXPORT(relocate_new_kernel_size) 
     161EXPORT(relocate_new_kernel_size) 
    81162        PTR             relocate_new_kernel_end - relocate_new_kernel 
    82163        .size           relocate_new_kernel_size, PTRSIZE 
  • arch/mips/kernel/setup.c

    a b  
    2222#include <linux/console.h> 
    2323#include <linux/pfn.h> 
    2424#include <linux/debugfs.h> 
     25#include <linux/kexec.h> 
    2526 
    2627#include <asm/addrspace.h> 
    2728#include <asm/bootinfo.h> 
    static void __init arch_mem_init(char ** 
    523524        } 
    524525 
    525526        bootmem_init(); 
     527#ifdef CONFIG_KEXEC 
     528        if (crashk_res.start != crashk_res.end) 
     529                reserve_bootmem(crashk_res.start, 
     530                        crashk_res.end - crashk_res.start + 1, 
     531                        BOOTMEM_DEFAULT); 
     532#endif 
    526533        device_tree_init(); 
    527534        sparse_init(); 
    528535        plat_swiotlb_setup(); 
    529536        paging_init(); 
    530537} 
    531538 
     539#ifdef CONFIG_KEXEC 
     540static inline unsigned long long get_total_mem(void) 
     541{ 
     542        unsigned long long total; 
     543        total = max_pfn - min_low_pfn; 
     544        return total << PAGE_SHIFT; 
     545} 
     546 
     547static void __init mips_parse_crashkernel(void) 
     548{ 
     549        unsigned long long total_mem; 
     550        unsigned long long crash_size, crash_base; 
     551        int ret; 
     552 
     553        total_mem = get_total_mem(); 
     554        ret = parse_crashkernel(boot_command_line, total_mem, 
     555                        &crash_size, &crash_base); 
     556        if (ret != 0 || crash_size <= 0) 
     557                return; 
     558 
     559        crashk_res.start = crash_base; 
     560        crashk_res.end   = crash_base + crash_size - 1; 
     561} 
     562static void __init request_crashkernel(struct resource *res) 
     563{ 
     564        int ret; 
     565 
     566        ret = request_resource(res, &crashk_res); 
     567        if (!ret) 
     568                printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " 
     569                        "for crashkernel\n", 
     570                        (unsigned long)((crashk_res.end - 
     571                                crashk_res.start + 1) >> 20), 
     572                        (unsigned long)(crashk_res.start  >> 20)); 
     573} 
     574#else 
     575static void __init mips_parse_crashkernel(void) 
     576{ 
     577} 
     578static void __init request_crashkernel(struct resource *res) 
     579{ 
     580} 
     581#endif 
     582 
    532583static void __init resource_init(void) 
    533584{ 
    534585        int i; 
    static void __init resource_init(void) 
    544595        /* 
    545596         * Request address space for all standard RAM. 
    546597         */ 
     598        mips_parse_crashkernel(); 
     599 
    547600        for (i = 0; i < boot_mem_map.nr_map; i++) { 
    548601                struct resource *res; 
    549602                unsigned long start, end; 
    static void __init resource_init(void) 
    580633                 */ 
    581634                request_resource(res, &code_resource); 
    582635                request_resource(res, &data_resource); 
     636                request_crashkernel(res); 
    583637        } 
    584638} 
    585639 
  • arch/mips/kernel/smp.c

    a b void flush_tlb_one(unsigned long vaddr) 
    433433 
    434434EXPORT_SYMBOL(flush_tlb_page); 
    435435EXPORT_SYMBOL(flush_tlb_one); 
     436 
     437#if defined(CONFIG_KEXEC) 
     438void (*dump_ipi_function_ptr)(void *) = NULL; 
     439void dump_send_ipi(void (*dump_ipi_callback)(void *)) 
     440{ 
     441        int i; 
     442        int cpu = smp_processor_id(); 
     443 
     444        dump_ipi_function_ptr = dump_ipi_callback; 
     445        smp_mb(); 
     446        for_each_online_cpu(i) 
     447                if (i != cpu) 
     448                        core_send_ipi(i, SMP_DUMP); 
     449 
     450} 
     451EXPORT_SYMBOL(dump_send_ipi); 
     452#endif 
     453 
  • arch/mips/include/asm/kexec.h

    a b  
    99#ifndef _MIPS_KEXEC 
    1010# define _MIPS_KEXEC 
    1111 
     12#include <asm/stacktrace.h> 
     13 
     14extern unsigned long long elfcorehdr_addr; 
     15 
    1216/* Maximum physical address we can use pages from */ 
    1317#define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000) 
    1418/* Maximum address we can reach in physical address mode */ 
    1519#define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000) 
    1620 /* Maximum address we can use for the control code buffer */ 
    1721#define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000) 
    18  
    19 #define KEXEC_CONTROL_PAGE_SIZE 4096 
     22/* Reserve 3*4096 bytes for board-specific info */ 
     23#define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096) 
    2024 
    2125/* The native architecture */ 
    2226#define KEXEC_ARCH KEXEC_ARCH_MIPS 
     27#define MAX_NOTE_BYTES 1024 
    2328 
    2429static inline void crash_setup_regs(struct pt_regs *newregs, 
    25                                     struct pt_regs *oldregs) 
     30                                        struct pt_regs *oldregs) 
    2631{ 
    27         /* Dummy implementation for now */ 
     32        if (oldregs) 
     33                memcpy(newregs, oldregs, sizeof(*newregs)); 
     34        else 
     35                prepare_frametrace(newregs); 
    2836} 
    2937 
     38#ifdef CONFIG_KEXEC 
     39struct kimage; 
     40extern unsigned long kexec_args[4]; 
     41extern int (*_machine_kexec_prepare)(struct kimage *); 
     42extern void (*_machine_kexec_shutdown)(void); 
     43extern void (*_machine_crash_shutdown)(struct pt_regs *regs); 
     44extern void default_machine_crash_shutdown(struct pt_regs *regs); 
     45#ifdef CONFIG_SMP 
     46extern const unsigned char kexec_smp_wait[]; 
     47extern unsigned long secondary_kexec_args[4]; 
     48extern void (*relocated_kexec_smp_wait) (void *); 
     49extern atomic_t kexec_ready_to_reboot; 
     50#endif 
     51#endif 
     52 
    3053#endif /* !_MIPS_KEXEC */ 
  • arch/mips/include/asm/smp.h

    a b extern int __cpu_logical_map[NR_CPUS]; 
    4040#define SMP_CALL_FUNCTION       0x2 
    4141/* Octeon - Tell another core to flush its icache */ 
    4242#define SMP_ICACHE_FLUSH        0x4 
     43/* Used by kexec crashdump to save all cpu's state */ 
     44#define SMP_DUMP                0x8 
    4345 
    4446extern volatile cpumask_t cpu_callin_map; 
    4547 
    static inline void arch_send_call_functi 
    9193        mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION); 
    9294} 
    9395 
     96extern void core_send_ipi(int cpu, unsigned int action); 
     97#if defined(CONFIG_KEXEC) 
     98extern void (*dump_ipi_function_ptr)(void *); 
     99void dump_send_ipi(void (*dump_ipi_callback)(void *)); 
     100#endif 
    94101#endif /* __ASM_SMP_H */ 
Note: See TracBrowser for help on using the repository browser.