Blame view

arch/x86/kernel/relocate_kernel_32.S 5.56 KB
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
1
2
3
4
5
6
7
8
9
  /*
   * relocate_kernel.S - put the kernel image in place to boot
   * Copyright (C) 2002-2004 Eric Biederman  <ebiederm@xmission.com>
   *
   * This source code is licensed under the GNU General Public License,
   * Version 2.  See the file COPYING for more details.
   */
  
  #include <linux/linkage.h>
0341c14da   Jeremy Fitzhardinge   x86: use _types.h...
10
  #include <asm/page_types.h>
3566561bf   Magnus Damm   [PATCH] i386: Avo...
11
  #include <asm/kexec.h>
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
12
  #include <asm/processor-flags.h>
3566561bf   Magnus Damm   [PATCH] i386: Avo...
13
14
15
16
17
18
  
  /*
   * Must be relocatable PIC code callable as a C function
   */
  
  #define PTR(x) (x << 2)
3566561bf   Magnus Damm   [PATCH] i386: Avo...
19

fef3a7a17   Huang Ying   x86, kexec: fix k...
20
21
  /*
   * control_page + KEXEC_CONTROL_CODE_MAX_SIZE
fb45daa69   Huang Ying   kexec jump: check...
22
23
   * ~ control_page + PAGE_SIZE are used as data storage and stack for
   * jumping back
3ab835213   Huang Ying   kexec jump
24
   */
fb45daa69   Huang Ying   kexec jump: check...
25
  #define DATA(offset)		(KEXEC_CONTROL_CODE_MAX_SIZE+(offset))
3ab835213   Huang Ying   kexec jump
26
27
28
29
30
31
32
33
34
35
36
37
  
  /* Minimal CPU state */
  #define ESP			DATA(0x0)
  #define CR0			DATA(0x4)
  #define CR3			DATA(0x8)
  #define CR4			DATA(0xc)
  
  /* other data */
  #define CP_VA_CONTROL_PAGE	DATA(0x10)
  #define CP_PA_PGD		DATA(0x14)
  #define CP_PA_SWAP_PAGE		DATA(0x18)
  #define CP_PA_BACKUP_PAGES_MAP	DATA(0x1c)
3566561bf   Magnus Damm   [PATCH] i386: Avo...
38
  	.text
3566561bf   Magnus Damm   [PATCH] i386: Avo...
39
40
  	.globl relocate_kernel
  relocate_kernel:
3ab835213   Huang Ying   kexec jump
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  	/* Save the CPU context, used for jumping back */
  
  	pushl	%ebx
  	pushl	%esi
  	pushl	%edi
  	pushl	%ebp
  	pushf
  
  	movl	20+8(%esp), %ebp /* list of pages */
  	movl	PTR(VA_CONTROL_PAGE)(%ebp), %edi
  	movl	%esp, ESP(%edi)
  	movl	%cr0, %eax
  	movl	%eax, CR0(%edi)
  	movl	%cr3, %eax
  	movl	%eax, CR3(%edi)
  	movl	%cr4, %eax
  	movl	%eax, CR4(%edi)
3566561bf   Magnus Damm   [PATCH] i386: Avo...
58

5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
59
  	/* read the arguments and say goodbye to the stack */
3ab835213   Huang Ying   kexec jump
60
61
62
63
64
  	movl  20+4(%esp), %ebx /* page_list */
  	movl  20+8(%esp), %ebp /* list of pages */
  	movl  20+12(%esp), %edx /* start address */
  	movl  20+16(%esp), %ecx /* cpu_has_pae */
  	movl  20+20(%esp), %esi /* preserve_context */
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
65
66
67
68
  
  	/* zero out flags, and disable interrupts */
  	pushl $0
  	popfl
3ab835213   Huang Ying   kexec jump
69
70
71
72
73
74
75
76
  	/* save some information for jumping back */
  	movl	PTR(VA_CONTROL_PAGE)(%ebp), %edi
  	movl	%edi, CP_VA_CONTROL_PAGE(%edi)
  	movl	PTR(PA_PGD)(%ebp), %eax
  	movl	%eax, CP_PA_PGD(%edi)
  	movl	PTR(PA_SWAP_PAGE)(%ebp), %eax
  	movl	%eax, CP_PA_SWAP_PAGE(%edi)
  	movl	%ebx, CP_PA_BACKUP_PAGES_MAP(%edi)
fef3a7a17   Huang Ying   x86, kexec: fix k...
77
78
79
80
  	/*
  	 * get physical address of control page now
  	 * this is impossible after page table switch
  	 */
3566561bf   Magnus Damm   [PATCH] i386: Avo...
81
  	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edi
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
82

3566561bf   Magnus Damm   [PATCH] i386: Avo...
83
84
85
86
87
  	/* switch to new set of page tables */
  	movl	PTR(PA_PGD)(%ebp), %eax
  	movl	%eax, %cr3
  
  	/* setup a new stack at the end of the physical control page */
a7bba17bf   gorcunov@gmail.com   x86: relocate_ker...
88
  	lea	PAGE_SIZE(%edi), %esp
3566561bf   Magnus Damm   [PATCH] i386: Avo...
89
90
91
92
93
94
95
96
  
  	/* jump to identity mapped page */
  	movl    %edi, %eax
  	addl    $(identity_mapped - relocate_kernel), %eax
  	pushl   %eax
  	ret
  
  identity_mapped:
050438ed5   Huang Ying   kexec, x86: Fix i...
97
98
  	/* set return address to 0 if not preserving context */
  	pushl	$0
3566561bf   Magnus Damm   [PATCH] i386: Avo...
99
100
  	/* store the start address on the stack */
  	pushl   %edx
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
101

fef3a7a17   Huang Ying   x86, kexec: fix k...
102
103
  	/*
  	 * Set cr0 to a known state:
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
104
105
106
107
108
109
  	 *  - Paging disabled
  	 *  - Alignment check disabled
  	 *  - Write protect disabled
  	 *  - No task switch
  	 *  - Don't do FP software emulation.
  	 *  - Proctected mode enabled
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
110
111
  	 */
  	movl	%cr0, %eax
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
112
113
  	andl	$~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %eax
  	orl	$(X86_CR0_PE), %eax
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
114
115
116
117
118
  	movl	%eax, %cr0
  
  	/* clear cr4 if applicable */
  	testl	%ecx, %ecx
  	jz	1f
fef3a7a17   Huang Ying   x86, kexec: fix k...
119
120
  	/*
  	 * Set cr4 to a known state:
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
121
122
  	 * Setting everything to zero seems safe.
  	 */
4039ae538   gorcunov@gmail.com   x86: relocate_ker...
123
  	xorl	%eax, %eax
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
124
125
126
127
128
129
130
131
  	movl	%eax, %cr4
  
  	jmp 1f
  1:
  
  	/* Flush the TLB (needed?) */
  	xorl	%eax, %eax
  	movl	%eax, %cr3
3ab835213   Huang Ying   kexec jump
132
133
134
135
136
  	movl	CP_PA_SWAP_PAGE(%edi), %eax
  	pushl	%eax
  	pushl	%ebx
  	call	swap_pages
  	addl	$8, %esp
fef3a7a17   Huang Ying   x86, kexec: fix k...
137
138
  	/*
  	 * To be certain of avoiding problems with self-modifying code
3ab835213   Huang Ying   kexec jump
139
140
141
142
143
  	 * I need to execute a serializing instruction here.
  	 * So I flush the TLB, it's handy, and not processor dependent.
  	 */
  	xorl	%eax, %eax
  	movl	%eax, %cr3
fef3a7a17   Huang Ying   x86, kexec: fix k...
144
145
146
147
  	/*
  	 * set all of the registers to known values
  	 * leave %esp alone
  	 */
3ab835213   Huang Ying   kexec jump
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  
  	testl	%esi, %esi
  	jnz 1f
  	xorl	%edi, %edi
  	xorl	%eax, %eax
  	xorl	%ebx, %ebx
  	xorl    %ecx, %ecx
  	xorl    %edx, %edx
  	xorl    %esi, %esi
  	xorl    %ebp, %ebp
  	ret
  1:
  	popl	%edx
  	movl	CP_PA_SWAP_PAGE(%edi), %esp
  	addl	$PAGE_SIZE, %esp
  2:
  	call	*%edx
  
  	/* get the re-entry point of the peer system */
  	movl	0(%esp), %ebp
  	call	1f
  1:
  	popl	%ebx
  	subl	$(1b - relocate_kernel), %ebx
  	movl	CP_VA_CONTROL_PAGE(%ebx), %edi
  	lea	PAGE_SIZE(%ebx), %esp
  	movl	CP_PA_SWAP_PAGE(%ebx), %eax
  	movl	CP_PA_BACKUP_PAGES_MAP(%ebx), %edx
  	pushl	%eax
  	pushl	%edx
  	call	swap_pages
  	addl	$8, %esp
  	movl	CP_PA_PGD(%ebx), %eax
  	movl	%eax, %cr3
  	movl	%cr0, %eax
  	orl	$(1<<31), %eax
  	movl	%eax, %cr0
  	lea	PAGE_SIZE(%edi), %esp
  	movl	%edi, %eax
  	addl	$(virtual_mapped - relocate_kernel), %eax
  	pushl	%eax
  	ret
  
  virtual_mapped:
  	movl	CR4(%edi), %eax
  	movl	%eax, %cr4
  	movl	CR3(%edi), %eax
  	movl	%eax, %cr3
  	movl	CR0(%edi), %eax
  	movl	%eax, %cr0
  	movl	ESP(%edi), %esp
  	movl	%ebp, %eax
  
  	popf
  	popl	%ebp
  	popl	%edi
  	popl	%esi
  	popl	%ebx
  	ret
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
207
  	/* Do the copies */
3ab835213   Huang Ying   kexec jump
208
209
210
211
212
213
214
215
  swap_pages:
  	movl	8(%esp), %edx
  	movl	4(%esp), %ecx
  	pushl	%ebp
  	pushl	%ebx
  	pushl	%edi
  	pushl	%esi
  	movl	%ecx, %ebx
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  	jmp	1f
  
  0:	/* top, read another word from the indirection page */
  	movl	(%ebx), %ecx
  	addl	$4, %ebx
  1:
  	testl	$0x1,   %ecx  /* is it a destination page */
  	jz	2f
  	movl	%ecx,	%edi
  	andl	$0xfffff000, %edi
  	jmp     0b
  2:
  	testl	$0x2,	%ecx  /* is it an indirection page */
  	jz	2f
  	movl	%ecx,	%ebx
  	andl	$0xfffff000, %ebx
  	jmp     0b
  2:
  	testl   $0x4,   %ecx /* is it the done indicator */
  	jz      2f
  	jmp     3f
  2:
  	testl   $0x8,   %ecx /* is it the source indicator */
  	jz      0b	     /* Ignore it otherwise */
  	movl    %ecx,   %esi /* For every source page do a copy */
  	andl    $0xfffff000, %esi
3ab835213   Huang Ying   kexec jump
242
243
244
245
  	movl	%edi, %eax
  	movl	%esi, %ebp
  
  	movl	%edx, %edi
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
246
247
  	movl    $1024, %ecx
  	rep ; movsl
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
248

3ab835213   Huang Ying   kexec jump
249
250
251
252
  	movl	%ebp, %edi
  	movl	%eax, %esi
  	movl	$1024, %ecx
  	rep ; movsl
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
253

3ab835213   Huang Ying   kexec jump
254
255
256
257
  	movl	%eax, %edi
  	movl	%edx, %esi
  	movl	$1024, %ecx
  	rep ; movsl
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
258

3ab835213   Huang Ying   kexec jump
259
260
261
262
263
264
265
  	lea	PAGE_SIZE(%ebp), %esi
  	jmp     0b
  3:
  	popl	%esi
  	popl	%edi
  	popl	%ebx
  	popl	%ebp
5033cba08   Eric W. Biederman   [PATCH] kexec: x8...
266
  	ret
fb45daa69   Huang Ying   kexec jump: check...
267
268
269
  
  	.globl kexec_control_code_size
  .set kexec_control_code_size, . - relocate_kernel