Blame view

arch/x86/kernel/relocate_kernel_64.S 5.22 KB
5234f5eb0   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-2005 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>
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
11
  #include <asm/kexec.h>
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
12
  #include <asm/processor-flags.h>
0341c14da   Jeremy Fitzhardinge   x86: use _types.h...
13
  #include <asm/pgtable_types.h>
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
14

4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
15
16
17
18
19
  /*
   * Must be relocatable PIC code callable as a C function
   */
  
  #define PTR(x) (x << 3)
366932deb   gorcunov@gmail.com   x86: relocate_ker...
20
  #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
21

fee7b0d84   Huang Ying   x86, kexec: x86_6...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  /*
   * control_page + KEXEC_CONTROL_CODE_MAX_SIZE
   * ~ control_page + PAGE_SIZE are used as data storage and stack for
   * jumping back
   */
  #define DATA(offset)		(KEXEC_CONTROL_CODE_MAX_SIZE+(offset))
  
  /* Minimal CPU state */
  #define RSP			DATA(0x0)
  #define CR0			DATA(0x8)
  #define CR3			DATA(0x10)
  #define CR4			DATA(0x18)
  
  /* other data */
  #define CP_PA_TABLE_PAGE	DATA(0x20)
  #define CP_PA_SWAP_PAGE		DATA(0x28)
  #define CP_PA_BACKUP_PAGES_MAP	DATA(0x30)
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
39
  	.text
288621e32   Cyrill Gorcunov   x86: relocate_ker...
40
  	.align PAGE_SIZE
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
41
  	.code64
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
42
43
  	.globl relocate_kernel
  relocate_kernel:
fef3a7a17   Huang Ying   x86, kexec: fix k...
44
45
  	/*
  	 * %rdi indirection_page
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
46
47
  	 * %rsi page_list
  	 * %rdx start address
fee7b0d84   Huang Ying   x86, kexec: x86_6...
48
  	 * %rcx preserve_context
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
49
  	 */
fee7b0d84   Huang Ying   x86, kexec: x86_6...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  	/* Save the CPU context, used for jumping back */
  	pushq %rbx
  	pushq %rbp
  	pushq %r12
  	pushq %r13
  	pushq %r14
  	pushq %r15
  	pushf
  
  	movq	PTR(VA_CONTROL_PAGE)(%rsi), %r11
  	movq	%rsp, RSP(%r11)
  	movq	%cr0, %rax
  	movq	%rax, CR0(%r11)
  	movq	%cr3, %rax
  	movq	%rax, CR3(%r11)
  	movq	%cr4, %rax
  	movq	%rax, CR4(%r11)
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
67
68
69
  	/* zero out flags, and disable interrupts */
  	pushq $0
  	popfq
fef3a7a17   Huang Ying   x86, kexec: fix k...
70
71
72
73
  	/*
  	 * get physical address of control page now
  	 * this is impossible after page table switch
  	 */
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
74
75
76
  	movq	PTR(PA_CONTROL_PAGE)(%rsi), %r8
  
  	/* get physical address of page table now too */
fee7b0d84   Huang Ying   x86, kexec: x86_6...
77
78
79
80
81
82
83
84
85
  	movq	PTR(PA_TABLE_PAGE)(%rsi), %r9
  
  	/* get physical address of swap page now */
  	movq	PTR(PA_SWAP_PAGE)(%rsi), %r10
  
  	/* save some information for jumping back */
  	movq	%r9, CP_PA_TABLE_PAGE(%r11)
  	movq	%r10, CP_PA_SWAP_PAGE(%r11)
  	movq	%rdi, CP_PA_BACKUP_PAGES_MAP(%r11)
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
86

f5deb7967   Huang Ying   x86: kexec: Use o...
87
  	/* Switch to the identity mapped page tables */
fee7b0d84   Huang Ying   x86, kexec: x86_6...
88
  	movq	%r9, %cr3
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
89
90
  
  	/* setup a new stack at the end of the physical control page */
a7bba17bf   gorcunov@gmail.com   x86: relocate_ker...
91
  	lea	PAGE_SIZE(%r8), %rsp
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
92
93
94
95
96
97
98
  
  	/* jump to identity mapped page */
  	addq	$(identity_mapped - relocate_kernel), %r8
  	pushq	%r8
  	ret
  
  identity_mapped:
050438ed5   Huang Ying   kexec, x86: Fix i...
99
100
  	/* set return address to 0 if not preserving context */
  	pushq	$0
4bfaaef01   Magnus Damm   [PATCH] Avoid ove...
101
102
  	/* store the start address on the stack */
  	pushq   %rdx
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
103

fef3a7a17   Huang Ying   x86, kexec: fix k...
104
105
  	/*
  	 * Set cr0 to a known state:
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
106
107
108
109
110
111
  	 *  - Paging enabled
  	 *  - Alignment check disabled
  	 *  - Write protect disabled
  	 *  - No task switch
  	 *  - Don't do FP software emulation.
  	 *  - Proctected mode enabled
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
112
113
  	 */
  	movq	%cr0, %rax
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
114
115
  	andq	$~(X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %rax
  	orl	$(X86_CR0_PG | X86_CR0_PE), %eax
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
116
  	movq	%rax, %cr0
fef3a7a17   Huang Ying   x86, kexec: fix k...
117
118
  	/*
  	 * Set cr4 to a known state:
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
119
  	 *  - physical address extension enabled
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
120
  	 */
fd3af5312   gorcunov@gmail.com   x86: relocate_ker...
121
  	movq	$X86_CR4_PAE, %rax
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
122
123
124
125
  	movq	%rax, %cr4
  
  	jmp 1f
  1:
f5deb7967   Huang Ying   x86: kexec: Use o...
126
  	/* Flush the TLB (needed?) */
fee7b0d84   Huang Ying   x86, kexec: x86_6...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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
  	movq	%r9, %cr3
  
  	movq	%rcx, %r11
  	call	swap_pages
  
  	/*
  	 * To be certain of avoiding problems with self-modifying code
  	 * I need to execute a serializing instruction here.
  	 * So I flush the TLB by reloading %cr3 here, it's handy,
  	 * and not processor dependent.
  	 */
  	movq	%cr3, %rax
  	movq	%rax, %cr3
  
  	/*
  	 * set all of the registers to known values
  	 * leave %rsp alone
  	 */
  
  	testq	%r11, %r11
  	jnz 1f
  	xorq	%rax, %rax
  	xorq	%rbx, %rbx
  	xorq    %rcx, %rcx
  	xorq    %rdx, %rdx
  	xorq    %rsi, %rsi
  	xorq    %rdi, %rdi
  	xorq    %rbp, %rbp
  	xorq	%r8,  %r8
  	xorq	%r9,  %r9
  	xorq	%r10, %r9
  	xorq	%r11, %r11
  	xorq	%r12, %r12
  	xorq	%r13, %r13
  	xorq	%r14, %r14
  	xorq	%r15, %r15
  
  	ret
  
  1:
  	popq	%rdx
  	leaq	PAGE_SIZE(%r10), %rsp
  	call	*%rdx
  
  	/* get the re-entry point of the peer system */
  	movq	0(%rsp), %rbp
  	call	1f
  1:
  	popq	%r8
  	subq	$(1b - relocate_kernel), %r8
  	movq	CP_PA_SWAP_PAGE(%r8), %r10
  	movq	CP_PA_BACKUP_PAGES_MAP(%r8), %rdi
  	movq	CP_PA_TABLE_PAGE(%r8), %rax
  	movq	%rax, %cr3
  	lea	PAGE_SIZE(%r8), %rsp
  	call	swap_pages
  	movq	$virtual_mapped, %rax
  	pushq	%rax
  	ret
  
  virtual_mapped:
  	movq	RSP(%r8), %rsp
  	movq	CR4(%r8), %rax
  	movq	%rax, %cr4
  	movq	CR3(%r8), %rax
  	movq	CR0(%r8), %r8
  	movq	%rax, %cr3
  	movq	%r8, %cr0
  	movq	%rbp, %rax
  
  	popf
  	popq	%r15
  	popq	%r14
  	popq	%r13
  	popq	%r12
  	popq	%rbp
  	popq	%rbx
  	ret
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
205
206
  
  	/* Do the copies */
fee7b0d84   Huang Ying   x86, kexec: x86_6...
207
  swap_pages:
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  	movq	%rdi, %rcx 	/* Put the page_list in %rcx */
  	xorq	%rdi, %rdi
  	xorq	%rsi, %rsi
  	jmp	1f
  
  0:	/* top, read another word for the indirection page */
  
  	movq	(%rbx), %rcx
  	addq	$8,	%rbx
  1:
  	testq	$0x1,	%rcx  /* is it a destination page? */
  	jz	2f
  	movq	%rcx,	%rdi
  	andq	$0xfffffffffffff000, %rdi
  	jmp	0b
  2:
  	testq	$0x2,	%rcx  /* is it an indirection page? */
  	jz	2f
  	movq	%rcx,   %rbx
  	andq	$0xfffffffffffff000, %rbx
  	jmp	0b
  2:
  	testq	$0x4,	%rcx  /* is it the done indicator? */
  	jz	2f
  	jmp	3f
  2:
  	testq	$0x8,	%rcx  /* is it the source indicator? */
  	jz	0b	      /* Ignore it otherwise */
  	movq	%rcx,   %rsi  /* For ever source page do a copy */
  	andq	$0xfffffffffffff000, %rsi
fee7b0d84   Huang Ying   x86, kexec: x86_6...
238
239
240
241
  	movq	%rdi, %rdx
  	movq	%rsi, %rax
  
  	movq	%r10, %rdi
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
242
243
  	movq	$512,   %rcx
  	rep ; movsq
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
244

fee7b0d84   Huang Ying   x86, kexec: x86_6...
245
246
247
248
  	movq	%rax, %rdi
  	movq	%rdx, %rsi
  	movq	$512,   %rcx
  	rep ; movsq
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
249

fee7b0d84   Huang Ying   x86, kexec: x86_6...
250
251
252
253
  	movq	%rdx, %rdi
  	movq	%r10, %rsi
  	movq	$512,   %rcx
  	rep ; movsq
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
254

fee7b0d84   Huang Ying   x86, kexec: x86_6...
255
256
257
  	lea	PAGE_SIZE(%rax), %rsi
  	jmp	0b
  3:
5234f5eb0   Eric W. Biederman   [PATCH] kexec: x8...
258
  	ret
fee7b0d84   Huang Ying   x86, kexec: x86_6...
259
260
261
  
  	.globl kexec_control_code_size
  .set kexec_control_code_size, . - relocate_kernel