2 * machine_kexec.c - handle transition of Linux booting another kernel
3 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
5 * GAMECUBE/PPC32 port Copyright (C) 2004 Albert Herranz
7 * This source code is licensed under the GNU General Public License,
8 * Version 2. See the file COPYING for more details.
12 #include <linux/kexec.h>
13 #include <linux/delay.h>
14 #include <asm/pgtable.h>
15 #include <asm/pgalloc.h>
16 #include <asm/mmu_context.h>
18 #include <asm/hw_irq.h>
19 #include <asm/cacheflush.h>
21 typedef void (*relocate_new_kernel_t)(
22 unsigned long indirection_page, unsigned long reboot_code_buffer,
23 unsigned long start_address);
25 const extern unsigned char relocate_new_kernel[];
26 const extern unsigned int relocate_new_kernel_size;
27 extern void use_mm(struct mm_struct *mm);
29 static int identity_map_pages(struct page *pages, int order)
32 struct vm_area_struct *vma;
38 down_write(&mm->mmap_sem);
40 vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
45 memset(vma, 0, sizeof(*vma));
47 vma->vm_start = page_to_pfn(pages) << PAGE_SHIFT;
48 vma->vm_end = vma->vm_start + (1 << (order + PAGE_SHIFT));
50 vma->vm_flags = VM_SHARED \
51 | VM_READ | VM_WRITE | VM_EXEC \
52 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC \
53 | VM_DONTCOPY | VM_RESERVED;
54 vma->vm_page_prot = protection_map[vma->vm_flags & 0xf];
56 vma->vm_private_data = NULL;
57 insert_vm_struct(mm, vma);
59 error = remap_page_range(vma, vma->vm_start, vma->vm_start,
60 vma->vm_end - vma->vm_start, vma->vm_page_prot);
68 kmem_cache_free(vm_area_cachep, vma);
71 up_write(&mm->mmap_sem);
77 * Do what every setup is needed on image and the
78 * reboot code buffer to allow us to avoid allocations
81 int machine_kexec_prepare(struct kimage *image)
84 order = get_order(KEXEC_CONTROL_CODE_SIZE);
85 return identity_map_pages(image->control_code_page, order);
88 void machine_kexec_cleanup(struct kimage *image)
91 order = get_order(KEXEC_CONTROL_CODE_SIZE);
93 page_to_pfn(image->control_code_page) << PAGE_SHIFT,
94 1 << (order + PAGE_SHIFT));
97 void machine_shutdown(void)
102 * Do not allocate memory (or fail in any way) in machine_kexec().
103 * We are past the point of no return, committed to rebooting now.
105 void machine_kexec(struct kimage *image)
107 unsigned long indirection_page;
108 unsigned long reboot_code_buffer;
109 relocate_new_kernel_t rnk;
111 /* switch to an mm where the reboot_code_buffer is identity mapped */
114 /* Interrupts aren't acceptable while we reboot */
117 reboot_code_buffer = page_to_pfn(image->control_code_page) <<PAGE_SHIFT;
118 indirection_page = image->head & PAGE_MASK;
121 memcpy((void *)reboot_code_buffer,
122 relocate_new_kernel, relocate_new_kernel_size);
124 flush_icache_range(reboot_code_buffer,
125 reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
126 printk(KERN_INFO "Bye!\n");
129 rnk = (relocate_new_kernel_t) reboot_code_buffer;
130 (*rnk)(indirection_page, reboot_code_buffer, image->start);