aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/relocate_kernel_64.S
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2007-10-11 05:17:24 -0400
committerThomas Gleixner <tglx@linutronix.de>2007-10-11 05:17:24 -0400
commit250c22777fe1ccd7ac588579a6c16db4c0161cc5 (patch)
tree55c317efb7d792ec6fdae1d1937c67a502c48dec /arch/x86/kernel/relocate_kernel_64.S
parent2db55d344e529492545cb3b755c7e9ba8e4fa94e (diff)
x86_64: move kernel
Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/relocate_kernel_64.S')
-rw-r--r--arch/x86/kernel/relocate_kernel_64.S276
1 files changed, 276 insertions, 0 deletions
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
new file mode 100644
index 000000000000..14e95872c6a3
--- /dev/null
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -0,0 +1,276 @@
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