linux/arch/mips/kernel/machine_kexec.c
<<
>>
Prefs
   1/*
   2 * machine_kexec.c for kexec
   3 * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006
   4 *
   5 * This source code is licensed under the GNU General Public License,
   6 * Version 2.  See the file COPYING for more details.
   7 */
   8#include <linux/compiler.h>
   9#include <linux/kexec.h>
  10#include <linux/mm.h>
  11#include <linux/delay.h>
  12
  13#include <asm/cacheflush.h>
  14#include <asm/page.h>
  15
  16extern const unsigned char relocate_new_kernel[];
  17extern const size_t relocate_new_kernel_size;
  18
  19extern unsigned long kexec_start_address;
  20extern unsigned long kexec_indirection_page;
  21
  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);
  28void (*_crash_smp_send_stop)(void) = NULL;
  29#endif
  30
  31int
  32machine_kexec_prepare(struct kimage *kimage)
  33{
  34        if (_machine_kexec_prepare)
  35                return _machine_kexec_prepare(kimage);
  36        return 0;
  37}
  38
  39void
  40machine_kexec_cleanup(struct kimage *kimage)
  41{
  42}
  43
  44void
  45machine_shutdown(void)
  46{
  47        if (_machine_kexec_shutdown)
  48                _machine_kexec_shutdown();
  49}
  50
  51void
  52machine_crash_shutdown(struct pt_regs *regs)
  53{
  54        if (_machine_crash_shutdown)
  55                _machine_crash_shutdown(regs);
  56        else
  57                default_machine_crash_shutdown(regs);
  58}
  59
  60typedef void (*noretfun_t)(void) __noreturn;
  61
  62void
  63machine_kexec(struct kimage *image)
  64{
  65        unsigned long reboot_code_buffer;
  66        unsigned long entry;
  67        unsigned long *ptr;
  68
  69        reboot_code_buffer =
  70          (unsigned long)page_address(image->control_code_page);
  71
  72        kexec_start_address =
  73                (unsigned long) phys_to_virt(image->start);
  74
  75        if (image->type == KEXEC_TYPE_DEFAULT) {
  76                kexec_indirection_page =
  77                        (unsigned long) phys_to_virt(image->head & PAGE_MASK);
  78        } else {
  79                kexec_indirection_page = (unsigned long)&image->head;
  80        }
  81
  82        memcpy((void*)reboot_code_buffer, relocate_new_kernel,
  83               relocate_new_kernel_size);
  84
  85        /*
  86         * The generic kexec code builds a page list with physical
  87         * addresses. they are directly accessible through KSEG0 (or
  88         * CKSEG0 or XPHYS if on 64bit system), hence the
  89         * phys_to_virt() call.
  90         */
  91        for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
  92             ptr = (entry & IND_INDIRECTION) ?
  93               phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
  94                if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
  95                    *ptr & IND_DESTINATION)
  96                        *ptr = (unsigned long) phys_to_virt(*ptr);
  97        }
  98
  99        /*
 100         * we do not want to be bothered.
 101         */
 102        local_irq_disable();
 103
 104        printk("Will call new kernel at %08lx\n", image->start);
 105        printk("Bye ...\n");
 106        __flush_cache_all();
 107#ifdef CONFIG_SMP
 108        /* All secondary cpus now may jump to kexec_wait cycle */
 109        relocated_kexec_smp_wait = reboot_code_buffer +
 110                (void *)(kexec_smp_wait - relocate_new_kernel);
 111        smp_wmb();
 112        atomic_set(&kexec_ready_to_reboot, 1);
 113#endif
 114        ((noretfun_t) reboot_code_buffer)();
 115}
 116