1/* 2 * relocate_kernel.S - put the kernel image in place to boot 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/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 << 3) 18#define PAGE_ALIGNED (1 << PAGE_SHIFT) 19#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */ 20 21 .text 22 .align PAGE_ALIGNED 23 .code64 24 .globl relocate_kernel 25relocate_kernel: 26 /* %rdi indirection_page 27 * %rsi page_list 28 * %rdx start address 29 */ 30 31 /* map the control page at its virtual address */ 32 33 movq $0x0000ff8000000000, %r10 /* mask */ 34 mov $(39 - 3), %cl /* bits to shift */ 35 movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ 36 37 movq %r11, %r9 38 andq %r10, %r9 39 shrq %cl, %r9 40 41 movq PTR(VA_PGD)(%rsi), %r8 42 addq %r8, %r9 43 movq PTR(PA_PUD_0)(%rsi), %r8 44 orq $PAGE_ATTR, %r8 45 movq %r8, (%r9) 46 47 shrq $9, %r10 48 sub $9, %cl 49 50 movq %r11, %r9 51 andq %r10, %r9 52 shrq %cl, %r9 53 54 movq PTR(VA_PUD_0)(%rsi), %r8 55 addq %r8, %r9 56 movq PTR(PA_PMD_0)(%rsi), %r8 57 orq $PAGE_ATTR, %r8 58 movq %r8, (%r9) 59 60 shrq $9, %r10 61 sub $9, %cl 62 63 movq %r11, %r9 64 andq %r10, %r9 65 shrq %cl, %r9 66 67 movq PTR(VA_PMD_0)(%rsi), %r8 68 addq %r8, %r9 69 movq PTR(PA_PTE_0)(%rsi), %r8 70 orq $PAGE_ATTR, %r8 71 movq %r8, (%r9) 72 73 shrq $9, %r10 74 sub $9, %cl 75 76 movq %r11, %r9 77 andq %r10, %r9 78 shrq %cl, %r9 79 80 movq PTR(VA_PTE_0)(%rsi), %r8 81 addq %r8, %r9 82 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 83 orq $PAGE_ATTR, %r8 84 movq %r8, (%r9) 85 86 /* identity map the control page at its physical address */ 87 88 movq $0x0000ff8000000000, %r10 /* mask */ 89 mov $(39 - 3), %cl /* bits to shift */ 90 movq PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ 91 92 movq %r11, %r9 93 andq %r10, %r9 94 shrq %cl, %r9 95 96 movq PTR(VA_PGD)(%rsi), %r8 97 addq %r8, %r9 98 movq PTR(PA_PUD_1)(%rsi), %r8 99 orq $PAGE_ATTR, %r8 100 movq %r8, (%r9) 101 102 shrq $9, %r10 103 sub $9, %cl 104 105 movq %r11, %r9 106 andq %r10, %r9 107 shrq %cl, %r9 108 109 movq PTR(VA_PUD_1)(%rsi), %r8 110 addq %r8, %r9 111 movq PTR(PA_PMD_1)(%rsi), %r8 112 orq $PAGE_ATTR, %r8 113 movq %r8, (%r9) 114 115 shrq $9, %r10 116 sub $9, %cl 117 118 movq %r11, %r9 119 andq %r10, %r9 120 shrq %cl, %r9 121 122 movq PTR(VA_PMD_1)(%rsi), %r8 123 addq %r8, %r9 124 movq PTR(PA_PTE_1)(%rsi), %r8 125 orq $PAGE_ATTR, %r8 126 movq %r8, (%r9) 127 128 shrq $9, %r10 129 sub $9, %cl 130 131 movq %r11, %r9 132 andq %r10, %r9 133 shrq %cl, %r9 134 135 movq PTR(VA_PTE_1)(%rsi), %r8 136 addq %r8, %r9 137 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 138 orq $PAGE_ATTR, %r8 139 movq %r8, (%r9) 140 141relocate_new_kernel: 142 /* %rdi indirection_page 143 * %rsi page_list 144 * %rdx start address 145 */ 146 147 /* zero out flags, and disable interrupts */ 148 pushq $0 149 popfq 150 151 /* get physical address of control page now */ 152 /* this is impossible after page table switch */ 153 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 154 155 /* get physical address of page table now too */ 156 movq PTR(PA_TABLE_PAGE)(%rsi), %rcx 157 158 /* switch to new set of page tables */ 159 movq PTR(PA_PGD)(%rsi), %r9 160 movq %r9, %cr3 161 162 /* setup a new stack at the end of the physical control page */ 163 lea 4096(%r8), %rsp 164 165 /* jump to identity mapped page */ 166 addq $(identity_mapped - relocate_kernel), %r8 167 pushq %r8 168 ret 169 170identity_mapped: 171 /* store the start address on the stack */ 172 pushq %rdx 173 174 /* Set cr0 to a known state: 175 * 31 1 == Paging enabled 176 * 18 0 == Alignment check disabled 177 * 16 0 == Write protect disabled 178 * 3 0 == No task switch 179 * 2 0 == Don't do FP software emulation. 180 * 0 1 == Proctected mode enabled 181 */ 182 movq %cr0, %rax 183 andq $~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax 184 orl $((1<<31)|(1<<0)), %eax 185 movq %rax, %cr0 186 187 /* Set cr4 to a known state: 188 * 10 0 == xmm exceptions disabled 189 * 9 0 == xmm registers instructions disabled 190 * 8 0 == performance monitoring counter disabled 191 * 7 0 == page global disabled 192 * 6 0 == machine check exceptions disabled 193 * 5 1 == physical address extension enabled 194 * 4 0 == page size extensions disabled 195 * 3 0 == Debug extensions disabled 196 * 2 0 == Time stamp disable (disabled) 197 * 1 0 == Protected mode virtual interrupts disabled 198 * 0 0 == VME disabled 199 */ 200 201 movq $((1<<5)), %rax 202 movq %rax, %cr4 203 204 jmp 1f 2051: 206 207 /* Switch to the identity mapped page tables, 208 * and flush the TLB. 209 */ 210 movq %rcx, %cr3 211 212 /* Do the copies */ 213 movq %rdi, %rcx /* Put the page_list in %rcx */ 214 xorq %rdi, %rdi 215 xorq %rsi, %rsi 216 jmp 1f 217 2180: /* top, read another word for the indirection page */ 219 220 movq (%rbx), %rcx 221 addq $8, %rbx 2221: 223 testq $0x1, %rcx /* is it a destination page? */ 224 jz 2f 225 movq %rcx, %rdi 226 andq $0xfffffffffffff000, %rdi 227 jmp 0b 2282: 229 testq $0x2, %rcx /* is it an indirection page? */ 230 jz 2f 231 movq %rcx, %rbx 232 andq $0xfffffffffffff000, %rbx 233 jmp 0b 2342: 235 testq $0x4, %rcx /* is it the done indicator? */ 236 jz 2f 237 jmp 3f 2382: 239 testq $0x8, %rcx /* is it the source indicator? */ 240 jz 0b /* Ignore it otherwise */ 241 movq %rcx, %rsi /* For ever source page do a copy */ 242 andq $0xfffffffffffff000, %rsi 243 244 movq $512, %rcx 245 rep ; movsq 246 jmp 0b 2473: 248 249 /* To be certain of avoiding problems with self-modifying code 250 * I need to execute a serializing instruction here. 251 * So I flush the TLB by reloading %cr3 here, it's handy, 252 * and not processor dependent. 253 */ 254 movq %cr3, %rax 255 movq %rax, %cr3 256 257 /* set all of the registers to known values */ 258 /* leave %rsp alone */ 259 260 xorq %rax, %rax 261 xorq %rbx, %rbx 262 xorq %rcx, %rcx 263 xorq %rdx, %rdx 264 xorq %rsi, %rsi 265 xorq %rdi, %rdi 266 xorq %rbp, %rbp 267 xorq %r8, %r8 268 xorq %r9, %r9 269 xorq %r10, %r9 270 xorq %r11, %r11 271 xorq %r12, %r12 272 xorq %r13, %r13 273 xorq %r14, %r14 274 xorq %r15, %r15 275 276 ret 277