2 * relocate_kernel.S - put the kernel image in place to boot
3 * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com>
5 * This source code is licensed under the GNU General Public License,
6 * Version 2. See the file COPYING for more details.
9 #include <linux/linkage.h>
11 #include <asm/kexec.h>
12 #include <asm/processor-flags.h>
15 * Must be relocatable PIC code callable as a C function
18 #define PTR(x) (x << 3)
19 #define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
24 .globl relocate_kernel
26 /* %rdi indirection_page
31 /* map the control page at its virtual address */
33 movq $0x0000ff8000000000, %r10 /* mask */
34 mov $(39 - 3), %cl /* bits to shift */
35 movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
41 movq PTR(VA_PGD)(%rsi), %r8
43 movq PTR(PA_PUD_0)(%rsi), %r8
54 movq PTR(VA_PUD_0)(%rsi), %r8
56 movq PTR(PA_PMD_0)(%rsi), %r8
67 movq PTR(VA_PMD_0)(%rsi), %r8
69 movq PTR(PA_PTE_0)(%rsi), %r8
80 movq PTR(VA_PTE_0)(%rsi), %r8
82 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
86 /* identity map the control page at its physical address */
88 movq $0x0000ff8000000000, %r10 /* mask */
89 mov $(39 - 3), %cl /* bits to shift */
90 movq PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
96 movq PTR(VA_PGD)(%rsi), %r8
98 movq PTR(PA_PUD_1)(%rsi), %r8
109 movq PTR(VA_PUD_1)(%rsi), %r8
111 movq PTR(PA_PMD_1)(%rsi), %r8
122 movq PTR(VA_PMD_1)(%rsi), %r8
124 movq PTR(PA_PTE_1)(%rsi), %r8
135 movq PTR(VA_PTE_1)(%rsi), %r8
137 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
142 /* %rdi indirection_page
147 /* zero out flags, and disable interrupts */
151 /* get physical address of control page now */
152 /* this is impossible after page table switch */
153 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
155 /* get physical address of page table now too */
156 movq PTR(PA_TABLE_PAGE)(%rsi), %rcx
158 /* switch to new set of page tables */
159 movq PTR(PA_PGD)(%rsi), %r9
162 /* setup a new stack at the end of the physical control page */
163 lea PAGE_SIZE(%r8), %rsp
165 /* jump to identity mapped page */
166 addq $(identity_mapped - relocate_kernel), %r8
171 /* store the start address on the stack */
174 /* Set cr0 to a known state:
176 * - Alignment check disabled
177 * - Write protect disabled
179 * - Don't do FP software emulation.
180 * - Proctected mode enabled
183 andq $~(X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %rax
184 orl $(X86_CR0_PG | X86_CR0_PE), %eax
187 /* Set cr4 to a known state:
188 * - physical address extension enabled
190 movq $X86_CR4_PAE, %rax
196 /* Switch to the identity mapped page tables,
202 movq %rdi, %rcx /* Put the page_list in %rcx */
207 0: /* top, read another word for the indirection page */
212 testq $0x1, %rcx /* is it a destination page? */
215 andq $0xfffffffffffff000, %rdi
218 testq $0x2, %rcx /* is it an indirection page? */
221 andq $0xfffffffffffff000, %rbx
224 testq $0x4, %rcx /* is it the done indicator? */
228 testq $0x8, %rcx /* is it the source indicator? */
229 jz 0b /* Ignore it otherwise */
230 movq %rcx, %rsi /* For ever source page do a copy */
231 andq $0xfffffffffffff000, %rsi
238 /* To be certain of avoiding problems with self-modifying code
239 * I need to execute a serializing instruction here.
240 * So I flush the TLB by reloading %cr3 here, it's handy,
241 * and not processor dependent.
246 /* set all of the registers to known values */
247 /* leave %rsp alone */