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>
14 * Must be relocatable PIC code callable as a C function
17 #define PTR(x) (x << 3)
18 #define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
23 .globl relocate_kernel
25 /* %rdi indirection_page
30 /* map the control page at its virtual address */
32 movq $0x0000ff8000000000, %r10 /* mask */
33 mov $(39 - 3), %cl /* bits to shift */
34 movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
40 movq PTR(VA_PGD)(%rsi), %r8
42 movq PTR(PA_PUD_0)(%rsi), %r8
53 movq PTR(VA_PUD_0)(%rsi), %r8
55 movq PTR(PA_PMD_0)(%rsi), %r8
66 movq PTR(VA_PMD_0)(%rsi), %r8
68 movq PTR(PA_PTE_0)(%rsi), %r8
79 movq PTR(VA_PTE_0)(%rsi), %r8
81 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
85 /* identity map the control page at its physical address */
87 movq $0x0000ff8000000000, %r10 /* mask */
88 mov $(39 - 3), %cl /* bits to shift */
89 movq PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
95 movq PTR(VA_PGD)(%rsi), %r8
97 movq PTR(PA_PUD_1)(%rsi), %r8
108 movq PTR(VA_PUD_1)(%rsi), %r8
110 movq PTR(PA_PMD_1)(%rsi), %r8
121 movq PTR(VA_PMD_1)(%rsi), %r8
123 movq PTR(PA_PTE_1)(%rsi), %r8
134 movq PTR(VA_PTE_1)(%rsi), %r8
136 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
141 /* %rdi indirection_page
146 /* zero out flags, and disable interrupts */
150 /* get physical address of control page now */
151 /* this is impossible after page table switch */
152 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
154 /* get physical address of page table now too */
155 movq PTR(PA_TABLE_PAGE)(%rsi), %rcx
157 /* switch to new set of page tables */
158 movq PTR(PA_PGD)(%rsi), %r9
161 /* setup a new stack at the end of the physical control page */
164 /* jump to identity mapped page */
165 addq $(identity_mapped - relocate_kernel), %r8
170 /* store the start address on the stack */
173 /* Set cr0 to a known state:
174 * 31 1 == Paging enabled
175 * 18 0 == Alignment check disabled
176 * 16 0 == Write protect disabled
177 * 3 0 == No task switch
178 * 2 0 == Don't do FP software emulation.
179 * 0 1 == Proctected mode enabled
182 andq $~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax
183 orl $((1<<31)|(1<<0)), %eax
186 /* Set cr4 to a known state:
187 * 10 0 == xmm exceptions disabled
188 * 9 0 == xmm registers instructions disabled
189 * 8 0 == performance monitoring counter disabled
190 * 7 0 == page global disabled
191 * 6 0 == machine check exceptions disabled
192 * 5 1 == physical address extension enabled
193 * 4 0 == page size extensions disabled
194 * 3 0 == Debug extensions disabled
195 * 2 0 == Time stamp disable (disabled)
196 * 1 0 == Protected mode virtual interrupts disabled
197 * 0 0 == VME disabled
206 /* Switch to the identity mapped page tables,
212 movq %rdi, %rcx /* Put the page_list in %rcx */
217 0: /* top, read another word for the indirection page */
222 testq $0x1, %rcx /* is it a destination page? */
225 andq $0xfffffffffffff000, %rdi
228 testq $0x2, %rcx /* is it an indirection page? */
231 andq $0xfffffffffffff000, %rbx
234 testq $0x4, %rcx /* is it the done indicator? */
238 testq $0x8, %rcx /* is it the source indicator? */
239 jz 0b /* Ignore it otherwise */
240 movq %rcx, %rsi /* For ever source page do a copy */
241 andq $0xfffffffffffff000, %rsi
248 /* To be certain of avoiding problems with self-modifying code
249 * I need to execute a serializing instruction here.
250 * So I flush the TLB by reloading %cr3 here, it's handy,
251 * and not processor dependent.
256 /* set all of the registers to known values */
257 /* leave %rsp alone */