1 /* 2 * handle transition of Linux booting another kernel 3 * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com> 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 9 #include <linux/mm.h> 10 #include <linux/kexec.h> 11 #include <linux/delay.h> 12 #include <linux/init.h> 13 #include <asm/pgtable.h> 14 #include <asm/pgalloc.h> 15 #include <asm/tlbflush.h> 16 #include <asm/mmu_context.h> 17 #include <asm/io.h> 18 #include <asm/apic.h> 19 #include <asm/cpufeature.h> 20 #include <asm/desc.h> 21 #include <asm/system.h> 22 23 #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) 24 static u32 kexec_pgd[1024] PAGE_ALIGNED; 25 #ifdef CONFIG_X86_PAE 26 static u32 kexec_pmd0[1024] PAGE_ALIGNED; 27 static u32 kexec_pmd1[1024] PAGE_ALIGNED; 28 #endif 29 static u32 kexec_pte0[1024] PAGE_ALIGNED; 30 static u32 kexec_pte1[1024] PAGE_ALIGNED; 31 32 static void set_idt(void *newidt, __u16 limit) 33 { 34 struct Xgt_desc_struct curidt; 35 36 /* ia32 supports unaliged loads & stores */ 37 curidt.size = limit; 38 curidt.address = (unsigned long)newidt; 39 40 load_idt(&curidt); 41 }; 42 43 44 static void set_gdt(void *newgdt, __u16 limit) 45 { 46 struct Xgt_desc_struct curgdt; 47 48 /* ia32 supports unaligned loads & stores */ 49 curgdt.size = limit; 50 curgdt.address = (unsigned long)newgdt; 51 52 load_gdt(&curgdt); 53 }; 54 55 static void load_segments(void) 56 { 57 #define __STR(X) #X 58 #define STR(X) __STR(X) 59 60 __asm__ __volatile__ ( 61 "\tljmp $"STR(__KERNEL_CS)",$1f\n" 62 "\t1:\n" 63 "\tmovl $"STR(__KERNEL_DS)",%%eax\n" 64 "\tmovl %%eax,%%ds\n" 65 "\tmovl %%eax,%%es\n" 66 "\tmovl %%eax,%%fs\n" 67 "\tmovl %%eax,%%gs\n" 68 "\tmovl %%eax,%%ss\n" 69 ::: "eax", "memory"); 70 #undef STR 71 #undef __STR 72 } 73 74 /* 75 * A architecture hook called to validate the 76 * proposed image and prepare the control pages 77 * as needed. The pages for KEXEC_CONTROL_CODE_SIZE 78 * have been allocated, but the segments have yet 79 * been copied into the kernel. 80 * 81 * Do what every setup is needed on image and the 82 * reboot code buffer to allow us to avoid allocations 83 * later. 84 * 85 * Currently nothing. 86 */ 87 int machine_kexec_prepare(struct kimage *image) 88 { 89 return 0; 90 } 91 92 /* 93 * Undo anything leftover by machine_kexec_prepare 94 * when an image is freed. 95 */ 96 void machine_kexec_cleanup(struct kimage *image) 97 { 98 } 99 100 /* 101 * Do not allocate memory (or fail in any way) in machine_kexec(). 102 * We are past the point of no return, committed to rebooting now. 103 */ 104 NORET_TYPE void machine_kexec(struct kimage *image) 105 { 106 unsigned long page_list[PAGES_NR]; 107 void *control_page; 108 109 /* Interrupts aren't acceptable while we reboot */ 110 local_irq_disable(); 111 112 control_page = page_address(image->control_code_page); 113 memcpy(control_page, relocate_kernel, PAGE_SIZE); 114 115 page_list[PA_CONTROL_PAGE] = __pa(control_page); 116 page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; 117 page_list[PA_PGD] = __pa(kexec_pgd); 118 page_list[VA_PGD] = (unsigned long)kexec_pgd; 119 #ifdef CONFIG_X86_PAE 120 page_list[PA_PMD_0] = __pa(kexec_pmd0); 121 page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; 122 page_list[PA_PMD_1] = __pa(kexec_pmd1); 123 page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; 124 #endif 125 page_list[PA_PTE_0] = __pa(kexec_pte0); 126 page_list[VA_PTE_0] = (unsigned long)kexec_pte0; 127 page_list[PA_PTE_1] = __pa(kexec_pte1); 128 page_list[VA_PTE_1] = (unsigned long)kexec_pte1; 129 130 /* The segment registers are funny things, they have both a 131 * visible and an invisible part. Whenever the visible part is 132 * set to a specific selector, the invisible part is loaded 133 * with from a table in memory. At no other time is the 134 * descriptor table in memory accessed. 135 * 136 * I take advantage of this here by force loading the 137 * segments, before I zap the gdt with an invalid value. 138 */ 139 load_segments(); 140 /* The gdt & idt are now invalid. 141 * If you want to load them you must set up your own idt & gdt. 142 */ 143 set_gdt(phys_to_virt(0),0); 144 set_idt(phys_to_virt(0),0); 145 146 /* now call it */ 147 relocate_kernel((unsigned long)image->head, (unsigned long)page_list, 148 image->start, cpu_has_pae); 149 } 150 151 /* crashkernel=size@addr specifies the location to reserve for 152 * a crash kernel. By reserving this memory we guarantee 153 * that linux never sets it up as a DMA target. 154 * Useful for holding code to do something appropriate 155 * after a kernel panic. 156 */ 157 static int __init parse_crashkernel(char *arg) 158 { 159 unsigned long size, base; 160 size = memparse(arg, &arg); 161 if (*arg == '@') { 162 base = memparse(arg+1, &arg); 163 /* FIXME: Do I want a sanity check 164 * to validate the memory range? 165 */ 166 crashk_res.start = base; 167 crashk_res.end = base + size - 1; 168 } 169 return 0; 170 } 171 early_param("crashkernel", parse_crashkernel); 172