source:
trunk/packages/xen-common/xen-common/patches/linux-2.6.18/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch
@
34
Last change on this file since 34 was 34, checked in by hartmans, 17 years ago | |
---|---|
|
|
File size: 10.8 KB |
-
arch/i386/kernel/machine_kexec.c
diff -pruN ../orig-linux-2.6.18/arch/i386/kernel/machine_kexec.c ./arch/i386/kernel/machine_kexec.c
old new 20 20 #include <asm/system.h> 21 21 22 22 #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) 23 24 #define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) 25 #define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) 26 #define L2_ATTR (_PAGE_PRESENT) 27 28 #define LEVEL0_SIZE (1UL << 12UL) 29 30 #ifndef CONFIG_X86_PAE 31 #define LEVEL1_SIZE (1UL << 22UL) 32 static u32 pgtable_level1[1024] PAGE_ALIGNED; 33 34 static void identity_map_page(unsigned long address) 35 { 36 unsigned long level1_index, level2_index; 37 u32 *pgtable_level2; 38 39 /* Find the current page table */ 40 pgtable_level2 = __va(read_cr3()); 41 42 /* Find the indexes of the physical address to identity map */ 43 level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE; 44 level2_index = address / LEVEL1_SIZE; 45 46 /* Identity map the page table entry */ 47 pgtable_level1[level1_index] = address | L0_ATTR; 48 pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR; 49 50 /* Flush the tlb so the new mapping takes effect. 51 * Global tlb entries are not flushed but that is not an issue. 52 */ 53 load_cr3(pgtable_level2); 54 } 55 56 #else 57 #define LEVEL1_SIZE (1UL << 21UL) 58 #define LEVEL2_SIZE (1UL << 30UL) 59 static u64 pgtable_level1[512] PAGE_ALIGNED; 60 static u64 pgtable_level2[512] PAGE_ALIGNED; 61 62 static void identity_map_page(unsigned long address) 63 { 64 unsigned long level1_index, level2_index, level3_index; 65 u64 *pgtable_level3; 66 67 /* Find the current page table */ 68 pgtable_level3 = __va(read_cr3()); 69 70 /* Find the indexes of the physical address to identity map */ 71 level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE; 72 level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE; 73 level3_index = address / LEVEL2_SIZE; 74 75 /* Identity map the page table entry */ 76 pgtable_level1[level1_index] = address | L0_ATTR; 77 pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR; 78 set_64bit(&pgtable_level3[level3_index], 79 __pa(pgtable_level2) | L2_ATTR); 80 81 /* Flush the tlb so the new mapping takes effect. 82 * Global tlb entries are not flushed but that is not an issue. 83 */ 84 load_cr3(pgtable_level3); 85 } 23 static u32 kexec_pgd[1024] PAGE_ALIGNED; 24 #ifdef CONFIG_X86_PAE 25 static u32 kexec_pmd0[1024] PAGE_ALIGNED; 26 static u32 kexec_pmd1[1024] PAGE_ALIGNED; 86 27 #endif 28 static u32 kexec_pte0[1024] PAGE_ALIGNED; 29 static u32 kexec_pte1[1024] PAGE_ALIGNED; 87 30 88 31 static void set_idt(void *newidt, __u16 limit) 89 32 { … … static void load_segments(void) 127 70 #undef __STR 128 71 } 129 72 130 typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(131 unsigned long indirection_page,132 unsigned long reboot_code_buffer,133 unsigned long start_address,134 unsigned int has_pae) ATTRIB_NORET;135 136 extern const unsigned char relocate_new_kernel[];137 extern void relocate_new_kernel_end(void);138 extern const unsigned int relocate_new_kernel_size;139 140 73 /* 141 74 * A architecture hook called to validate the 142 75 * proposed image and prepare the control pages … … void machine_kexec_cleanup(struct kimage 169 102 */ 170 103 NORET_TYPE void machine_kexec(struct kimage *image) 171 104 { 172 unsigned long page_list; 173 unsigned long reboot_code_buffer; 174 175 relocate_new_kernel_t rnk; 105 unsigned long page_list[PAGES_NR]; 106 void *control_page; 176 107 177 108 /* Interrupts aren't acceptable while we reboot */ 178 109 local_irq_disable(); 179 110 180 /* Compute some offsets */ 181 reboot_code_buffer = page_to_pfn(image->control_code_page) 182 << PAGE_SHIFT; 183 page_list = image->head; 184 185 /* Set up an identity mapping for the reboot_code_buffer */ 186 identity_map_page(reboot_code_buffer); 187 188 /* copy it out */ 189 memcpy((void *)reboot_code_buffer, relocate_new_kernel, 190 relocate_new_kernel_size); 111 control_page = page_address(image->control_code_page); 112 memcpy(control_page, relocate_kernel, PAGE_SIZE); 113 114 page_list[PA_CONTROL_PAGE] = __pa(control_page); 115 page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; 116 page_list[PA_PGD] = __pa(kexec_pgd); 117 page_list[VA_PGD] = (unsigned long)kexec_pgd; 118 #ifdef CONFIG_X86_PAE 119 page_list[PA_PMD_0] = __pa(kexec_pmd0); 120 page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; 121 page_list[PA_PMD_1] = __pa(kexec_pmd1); 122 page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; 123 #endif 124 page_list[PA_PTE_0] = __pa(kexec_pte0); 125 page_list[VA_PTE_0] = (unsigned long)kexec_pte0; 126 page_list[PA_PTE_1] = __pa(kexec_pte1); 127 page_list[VA_PTE_1] = (unsigned long)kexec_pte1; 191 128 192 129 /* The segment registers are funny things, they have both a 193 130 * visible and an invisible part. Whenever the visible part is … … NORET_TYPE void machine_kexec(struct kim 206 143 set_idt(phys_to_virt(0),0); 207 144 208 145 /* now call it */ 209 r nk = (relocate_new_kernel_t) reboot_code_buffer;210 (*rnk)(page_list, reboot_code_buffer,image->start, cpu_has_pae);146 relocate_kernel((unsigned long)image->head, (unsigned long)page_list, 147 image->start, cpu_has_pae); 211 148 } -
arch/i386/kernel/relocate_kernel.S
diff -pruN ../orig-linux-2.6.18/arch/i386/kernel/relocate_kernel.S ./arch/i386/kernel/relocate_kernel.S
old new 7 7 */ 8 8 9 9 #include <linux/linkage.h> 10 #include <asm/page.h> 11 #include <asm/kexec.h> 12 13 /* 14 * Must be relocatable PIC code callable as a C function 15 */ 16 17 #define PTR(x) (x << 2) 18 #define PAGE_ALIGNED (1 << PAGE_SHIFT) 19 #define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */ 20 #define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */ 21 22 .text 23 .align PAGE_ALIGNED 24 .globl relocate_kernel 25 relocate_kernel: 26 movl 8(%esp), %ebp /* list of pages */ 27 28 #ifdef CONFIG_X86_PAE 29 /* map the control page at its virtual address */ 30 31 movl PTR(VA_PGD)(%ebp), %edi 32 movl PTR(VA_CONTROL_PAGE)(%ebp), %eax 33 andl $0xc0000000, %eax 34 shrl $27, %eax 35 addl %edi, %eax 36 37 movl PTR(PA_PMD_0)(%ebp), %edx 38 orl $PAE_PGD_ATTR, %edx 39 movl %edx, (%eax) 40 41 movl PTR(VA_PMD_0)(%ebp), %edi 42 movl PTR(VA_CONTROL_PAGE)(%ebp), %eax 43 andl $0x3fe00000, %eax 44 shrl $18, %eax 45 addl %edi, %eax 46 47 movl PTR(PA_PTE_0)(%ebp), %edx 48 orl $PAGE_ATTR, %edx 49 movl %edx, (%eax) 50 51 movl PTR(VA_PTE_0)(%ebp), %edi 52 movl PTR(VA_CONTROL_PAGE)(%ebp), %eax 53 andl $0x001ff000, %eax 54 shrl $9, %eax 55 addl %edi, %eax 56 57 movl PTR(PA_CONTROL_PAGE)(%ebp), %edx 58 orl $PAGE_ATTR, %edx 59 movl %edx, (%eax) 60 61 /* identity map the control page at its physical address */ 62 63 movl PTR(VA_PGD)(%ebp), %edi 64 movl PTR(PA_CONTROL_PAGE)(%ebp), %eax 65 andl $0xc0000000, %eax 66 shrl $27, %eax 67 addl %edi, %eax 68 69 movl PTR(PA_PMD_1)(%ebp), %edx 70 orl $PAE_PGD_ATTR, %edx 71 movl %edx, (%eax) 72 73 movl PTR(VA_PMD_1)(%ebp), %edi 74 movl PTR(PA_CONTROL_PAGE)(%ebp), %eax 75 andl $0x3fe00000, %eax 76 shrl $18, %eax 77 addl %edi, %eax 78 79 movl PTR(PA_PTE_1)(%ebp), %edx 80 orl $PAGE_ATTR, %edx 81 movl %edx, (%eax) 82 83 movl PTR(VA_PTE_1)(%ebp), %edi 84 movl PTR(PA_CONTROL_PAGE)(%ebp), %eax 85 andl $0x001ff000, %eax 86 shrl $9, %eax 87 addl %edi, %eax 88 89 movl PTR(PA_CONTROL_PAGE)(%ebp), %edx 90 orl $PAGE_ATTR, %edx 91 movl %edx, (%eax) 92 #else 93 /* map the control page at its virtual address */ 94 95 movl PTR(VA_PGD)(%ebp), %edi 96 movl PTR(VA_CONTROL_PAGE)(%ebp), %eax 97 andl $0xffc00000, %eax 98 shrl $20, %eax 99 addl %edi, %eax 100 101 movl PTR(PA_PTE_0)(%ebp), %edx 102 orl $PAGE_ATTR, %edx 103 movl %edx, (%eax) 104 105 movl PTR(VA_PTE_0)(%ebp), %edi 106 movl PTR(VA_CONTROL_PAGE)(%ebp), %eax 107 andl $0x003ff000, %eax 108 shrl $10, %eax 109 addl %edi, %eax 110 111 movl PTR(PA_CONTROL_PAGE)(%ebp), %edx 112 orl $PAGE_ATTR, %edx 113 movl %edx, (%eax) 114 115 /* identity map the control page at its physical address */ 116 117 movl PTR(VA_PGD)(%ebp), %edi 118 movl PTR(PA_CONTROL_PAGE)(%ebp), %eax 119 andl $0xffc00000, %eax 120 shrl $20, %eax 121 addl %edi, %eax 122 123 movl PTR(PA_PTE_1)(%ebp), %edx 124 orl $PAGE_ATTR, %edx 125 movl %edx, (%eax) 126 127 movl PTR(VA_PTE_1)(%ebp), %edi 128 movl PTR(PA_CONTROL_PAGE)(%ebp), %eax 129 andl $0x003ff000, %eax 130 shrl $10, %eax 131 addl %edi, %eax 132 133 movl PTR(PA_CONTROL_PAGE)(%ebp), %edx 134 orl $PAGE_ATTR, %edx 135 movl %edx, (%eax) 136 #endif 10 137 11 /*12 * Must be relocatable PIC code callable as a C function, that once13 * it starts can not use the previous processes stack.14 */15 .globl relocate_new_kernel16 138 relocate_new_kernel: 17 139 /* read the arguments and say goodbye to the stack */ 18 140 movl 4(%esp), %ebx /* page_list */ 19 movl 8(%esp), %ebp /* reboot_code_buffer*/141 movl 8(%esp), %ebp /* list of pages */ 20 142 movl 12(%esp), %edx /* start address */ 21 143 movl 16(%esp), %ecx /* cpu_has_pae */ 22 144 … … relocate_new_kernel: 24 146 pushl $0 25 147 popfl 26 148 27 /* set a new stack at the bottom of our page... */ 28 lea 4096(%ebp), %esp 149 /* get physical address of control page now */ 150 /* this is impossible after page table switch */ 151 movl PTR(PA_CONTROL_PAGE)(%ebp), %edi 152 153 /* switch to new set of page tables */ 154 movl PTR(PA_PGD)(%ebp), %eax 155 movl %eax, %cr3 156 157 /* setup a new stack at the end of the physical control page */ 158 lea 4096(%edi), %esp 29 159 30 /* store the parameters back on the stack */ 31 pushl %edx /* store the start address */ 160 /* jump to identity mapped page */ 161 movl %edi, %eax 162 addl $(identity_mapped - relocate_kernel), %eax 163 pushl %eax 164 ret 165 166 identity_mapped: 167 /* store the start address on the stack */ 168 pushl %edx 32 169 33 170 /* Set cr0 to a known state: 34 171 * 31 0 == Paging disabled … … relocate_new_kernel: 113 250 xorl %edi, %edi 114 251 xorl %ebp, %ebp 115 252 ret 116 relocate_new_kernel_end:117 118 .globl relocate_new_kernel_size119 relocate_new_kernel_size:120 .long relocate_new_kernel_end - relocate_new_kernel -
include/asm-i386/kexec.h
diff -pruN ../orig-linux-2.6.18/include/asm-i386/kexec.h ./include/asm-i386/kexec.h
old new 1 1 #ifndef _I386_KEXEC_H 2 2 #define _I386_KEXEC_H 3 3 4 #define PA_CONTROL_PAGE 0 5 #define VA_CONTROL_PAGE 1 6 #define PA_PGD 2 7 #define VA_PGD 3 8 #define PA_PTE_0 4 9 #define VA_PTE_0 5 10 #define PA_PTE_1 6 11 #define VA_PTE_1 7 12 #ifdef CONFIG_X86_PAE 13 #define PA_PMD_0 8 14 #define VA_PMD_0 9 15 #define PA_PMD_1 10 16 #define VA_PMD_1 11 17 #define PAGES_NR 12 18 #else 19 #define PAGES_NR 8 20 #endif 21 22 #ifndef __ASSEMBLY__ 23 4 24 #include <asm/fixmap.h> 5 25 #include <asm/ptrace.h> 6 26 #include <asm/string.h> … … static inline void crash_setup_regs(stru 72 92 newregs->eip = (unsigned long)current_text_addr(); 73 93 } 74 94 } 95 asmlinkage NORET_TYPE void 96 relocate_kernel(unsigned long indirection_page, 97 unsigned long control_page, 98 unsigned long start_address, 99 unsigned int has_pae) ATTRIB_NORET; 100 101 #endif /* __ASSEMBLY__ */ 75 102 76 103 #endif /* _I386_KEXEC_H */
Note: See TracBrowser
for help on using the repository browser.