xref: /linux/arch/x86/kernel/relocate_kernel_32.S (revision f7511d5f66f01fc451747b24e79f3ada7a3af9af)
1/*
2 * relocate_kernel.S - put the kernel image in place to boot
3 * Copyright (C) 2002-2004 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#include <asm/processor-flags.h>
13#include <asm/pgtable.h>
14
15/*
16 * Must be relocatable PIC code callable as a C function
17 */
18
19#define PTR(x) (x << 2)
20#define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
21#define PAE_PGD_ATTR (_PAGE_PRESENT)
22
23	.text
24	.align PAGE_SIZE
25	.globl relocate_kernel
26relocate_kernel:
27	movl	8(%esp), %ebp /* list of pages */
28
29#ifdef CONFIG_X86_PAE
30	/* map the control page at its virtual address */
31
32	movl	PTR(VA_PGD)(%ebp), %edi
33	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
34	andl	$0xc0000000, %eax
35	shrl	$27, %eax
36	addl	%edi, %eax
37
38	movl	PTR(PA_PMD_0)(%ebp), %edx
39	orl	$PAE_PGD_ATTR, %edx
40	movl	%edx, (%eax)
41
42	movl	PTR(VA_PMD_0)(%ebp), %edi
43	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
44	andl	$0x3fe00000, %eax
45	shrl	$18, %eax
46	addl	%edi, %eax
47
48	movl	PTR(PA_PTE_0)(%ebp), %edx
49	orl	$PAGE_ATTR, %edx
50	movl	%edx, (%eax)
51
52	movl	PTR(VA_PTE_0)(%ebp), %edi
53	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
54	andl	$0x001ff000, %eax
55	shrl	$9, %eax
56	addl	%edi, %eax
57
58	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
59	orl	$PAGE_ATTR, %edx
60	movl	%edx, (%eax)
61
62	/* identity map the control page at its physical address */
63
64	movl	PTR(VA_PGD)(%ebp), %edi
65	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
66	andl	$0xc0000000, %eax
67	shrl	$27, %eax
68	addl	%edi, %eax
69
70	movl	PTR(PA_PMD_1)(%ebp), %edx
71	orl	$PAE_PGD_ATTR, %edx
72	movl	%edx, (%eax)
73
74	movl	PTR(VA_PMD_1)(%ebp), %edi
75	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
76	andl	$0x3fe00000, %eax
77	shrl	$18, %eax
78	addl	%edi, %eax
79
80	movl	PTR(PA_PTE_1)(%ebp), %edx
81	orl	$PAGE_ATTR, %edx
82	movl	%edx, (%eax)
83
84	movl	PTR(VA_PTE_1)(%ebp), %edi
85	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
86	andl	$0x001ff000, %eax
87	shrl	$9, %eax
88	addl	%edi, %eax
89
90	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
91	orl	$PAGE_ATTR, %edx
92	movl	%edx, (%eax)
93#else
94	/* map the control page at its virtual address */
95
96	movl	PTR(VA_PGD)(%ebp), %edi
97	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
98	andl	$0xffc00000, %eax
99	shrl	$20, %eax
100	addl	%edi, %eax
101
102	movl	PTR(PA_PTE_0)(%ebp), %edx
103	orl	$PAGE_ATTR, %edx
104	movl	%edx, (%eax)
105
106	movl	PTR(VA_PTE_0)(%ebp), %edi
107	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
108	andl	$0x003ff000, %eax
109	shrl	$10, %eax
110	addl	%edi, %eax
111
112	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
113	orl	$PAGE_ATTR, %edx
114	movl	%edx, (%eax)
115
116	/* identity map the control page at its physical address */
117
118	movl	PTR(VA_PGD)(%ebp), %edi
119	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
120	andl	$0xffc00000, %eax
121	shrl	$20, %eax
122	addl	%edi, %eax
123
124	movl	PTR(PA_PTE_1)(%ebp), %edx
125	orl	$PAGE_ATTR, %edx
126	movl	%edx, (%eax)
127
128	movl	PTR(VA_PTE_1)(%ebp), %edi
129	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
130	andl	$0x003ff000, %eax
131	shrl	$10, %eax
132	addl	%edi, %eax
133
134	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
135	orl	$PAGE_ATTR, %edx
136	movl	%edx, (%eax)
137#endif
138
139relocate_new_kernel:
140	/* read the arguments and say goodbye to the stack */
141	movl  4(%esp), %ebx /* page_list */
142	movl  8(%esp), %ebp /* list of pages */
143	movl  12(%esp), %edx /* start address */
144	movl  16(%esp), %ecx /* cpu_has_pae */
145
146	/* zero out flags, and disable interrupts */
147	pushl $0
148	popfl
149
150	/* get physical address of control page now */
151	/* this is impossible after page table switch */
152	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edi
153
154	/* switch to new set of page tables */
155	movl	PTR(PA_PGD)(%ebp), %eax
156	movl	%eax, %cr3
157
158	/* setup a new stack at the end of the physical control page */
159	lea	PAGE_SIZE(%edi), %esp
160
161	/* jump to identity mapped page */
162	movl    %edi, %eax
163	addl    $(identity_mapped - relocate_kernel), %eax
164	pushl   %eax
165	ret
166
167identity_mapped:
168	/* store the start address on the stack */
169	pushl   %edx
170
171	/* Set cr0 to a known state:
172	 *  - Paging disabled
173	 *  - Alignment check disabled
174	 *  - Write protect disabled
175	 *  - No task switch
176	 *  - Don't do FP software emulation.
177	 *  - Proctected mode enabled
178	 */
179	movl	%cr0, %eax
180	andl	$~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %eax
181	orl	$(X86_CR0_PE), %eax
182	movl	%eax, %cr0
183
184	/* clear cr4 if applicable */
185	testl	%ecx, %ecx
186	jz	1f
187	/* Set cr4 to a known state:
188	 * Setting everything to zero seems safe.
189	 */
190	xorl	%eax, %eax
191	movl	%eax, %cr4
192
193	jmp 1f
1941:
195
196	/* Flush the TLB (needed?) */
197	xorl	%eax, %eax
198	movl	%eax, %cr3
199
200	/* Do the copies */
201	movl	%ebx, %ecx
202	jmp	1f
203
2040:	/* top, read another word from the indirection page */
205	movl	(%ebx), %ecx
206	addl	$4, %ebx
2071:
208	testl	$0x1,   %ecx  /* is it a destination page */
209	jz	2f
210	movl	%ecx,	%edi
211	andl	$0xfffff000, %edi
212	jmp     0b
2132:
214	testl	$0x2,	%ecx  /* is it an indirection page */
215	jz	2f
216	movl	%ecx,	%ebx
217	andl	$0xfffff000, %ebx
218	jmp     0b
2192:
220	testl   $0x4,   %ecx /* is it the done indicator */
221	jz      2f
222	jmp     3f
2232:
224	testl   $0x8,   %ecx /* is it the source indicator */
225	jz      0b	     /* Ignore it otherwise */
226	movl    %ecx,   %esi /* For every source page do a copy */
227	andl    $0xfffff000, %esi
228
229	movl    $1024, %ecx
230	rep ; movsl
231	jmp     0b
232
2333:
234
235	/* To be certain of avoiding problems with self-modifying code
236	 * I need to execute a serializing instruction here.
237	 * So I flush the TLB, it's handy, and not processor dependent.
238	 */
239	xorl	%eax, %eax
240	movl	%eax, %cr3
241
242	/* set all of the registers to known values */
243	/* leave %esp alone */
244
245	xorl	%eax, %eax
246	xorl	%ebx, %ebx
247	xorl    %ecx, %ecx
248	xorl    %edx, %edx
249	xorl    %esi, %esi
250	xorl    %edi, %edi
251	xorl    %ebp, %ebp
252	ret
253