1
2
3
4
5
6
7 #include <linux/linkage.h>
8 #include <asm/page_types.h>
9 #include <asm/kexec.h>
10 #include <asm/processor-flags.h>
11 #include <asm/pgtable_types.h>
12
13
14
15
16
17 #define PTR(x) (x << 3)
18 #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
19
20
21
22
23
24
25 #define DATA(offset) (KEXEC_CONTROL_CODE_MAX_SIZE+(offset))
26
27
28 #define RSP DATA(0x0)
29 #define CR0 DATA(0x8)
30 #define CR3 DATA(0x10)
31 #define CR4 DATA(0x18)
32
33
34 #define CP_PA_TABLE_PAGE DATA(0x20)
35 #define CP_PA_SWAP_PAGE DATA(0x28)
36 #define CP_PA_BACKUP_PAGES_MAP DATA(0x30)
37
38 .text
39 .align PAGE_SIZE
40 .code64
41 .globl relocate_kernel
42 relocate_kernel:
43
44
45
46
47
48
49
50
51
52 pushq %rbx
53 pushq %rbp
54 pushq %r12
55 pushq %r13
56 pushq %r14
57 pushq %r15
58 pushf
59
60 movq PTR(VA_CONTROL_PAGE)(%rsi), %r11
61 movq %rsp, RSP(%r11)
62 movq %cr0, %rax
63 movq %rax, CR0(%r11)
64 movq %cr3, %rax
65 movq %rax, CR3(%r11)
66 movq %cr4, %rax
67 movq %rax, CR4(%r11)
68
69
70 movq %rax, %r13
71
72
73 pushq $0
74 popfq
75
76
77 movq %r8, %r12
78
79
80
81
82
83 movq PTR(PA_CONTROL_PAGE)(%rsi), %r8
84
85
86 movq PTR(PA_TABLE_PAGE)(%rsi), %r9
87
88
89 movq PTR(PA_SWAP_PAGE)(%rsi), %r10
90
91
92 movq %r9, CP_PA_TABLE_PAGE(%r11)
93 movq %r10, CP_PA_SWAP_PAGE(%r11)
94 movq %rdi, CP_PA_BACKUP_PAGES_MAP(%r11)
95
96
97 movq %r9, %cr3
98
99
100 lea PAGE_SIZE(%r8), %rsp
101
102
103 addq $(identity_mapped - relocate_kernel), %r8
104 pushq %r8
105 ret
106
107 identity_mapped:
108
109 pushq $0
110
111 pushq %rdx
112
113
114
115
116
117
118
119
120
121
122 movq %cr0, %rax
123 andq $~(X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %rax
124 orl $(X86_CR0_PG | X86_CR0_PE), %eax
125 movq %rax, %cr0
126
127
128
129
130
131
132 movl $X86_CR4_PAE, %eax
133 testq $X86_CR4_LA57, %r13
134 jz 1f
135 orl $X86_CR4_LA57, %eax
136 1:
137 movq %rax, %cr4
138
139 jmp 1f
140 1:
141
142
143 movq %r9, %cr3
144
145
146
147
148
149
150 testq %r12, %r12
151 jz 1f
152 wbinvd
153 1:
154
155 movq %rcx, %r11
156 call swap_pages
157
158
159
160
161
162
163
164 movq %cr3, %rax
165 movq %rax, %cr3
166
167
168
169
170
171
172 testq %r11, %r11
173 jnz 1f
174 xorl %eax, %eax
175 xorl %ebx, %ebx
176 xorl %ecx, %ecx
177 xorl %edx, %edx
178 xorl %esi, %esi
179 xorl %edi, %edi
180 xorl %ebp, %ebp
181 xorl %r8d, %r8d
182 xorl %r9d, %r9d
183 xorl %r10d, %r10d
184 xorl %r11d, %r11d
185 xorl %r12d, %r12d
186 xorl %r13d, %r13d
187 xorl %r14d, %r14d
188 xorl %r15d, %r15d
189
190 ret
191
192 1:
193 popq %rdx
194 leaq PAGE_SIZE(%r10), %rsp
195 call *%rdx
196
197
198 movq 0(%rsp), %rbp
199 call 1f
200 1:
201 popq %r8
202 subq $(1b - relocate_kernel), %r8
203 movq CP_PA_SWAP_PAGE(%r8), %r10
204 movq CP_PA_BACKUP_PAGES_MAP(%r8), %rdi
205 movq CP_PA_TABLE_PAGE(%r8), %rax
206 movq %rax, %cr3
207 lea PAGE_SIZE(%r8), %rsp
208 call swap_pages
209 movq $virtual_mapped, %rax
210 pushq %rax
211 ret
212
213 virtual_mapped:
214 movq RSP(%r8), %rsp
215 movq CR4(%r8), %rax
216 movq %rax, %cr4
217 movq CR3(%r8), %rax
218 movq CR0(%r8), %r8
219 movq %rax, %cr3
220 movq %r8, %cr0
221 movq %rbp, %rax
222
223 popf
224 popq %r15
225 popq %r14
226 popq %r13
227 popq %r12
228 popq %rbp
229 popq %rbx
230 ret
231
232
233 swap_pages:
234 movq %rdi, %rcx
235 xorl %edi, %edi
236 xorl %esi, %esi
237 jmp 1f
238
239 0:
240
241 movq (%rbx), %rcx
242 addq $8, %rbx
243 1:
244 testb $0x1, %cl
245 jz 2f
246 movq %rcx, %rdi
247 andq $0xfffffffffffff000, %rdi
248 jmp 0b
249 2:
250 testb $0x2, %cl
251 jz 2f
252 movq %rcx, %rbx
253 andq $0xfffffffffffff000, %rbx
254 jmp 0b
255 2:
256 testb $0x4, %cl
257 jz 2f
258 jmp 3f
259 2:
260 testb $0x8, %cl
261 jz 0b
262 movq %rcx, %rsi
263 andq $0xfffffffffffff000, %rsi
264
265 movq %rdi, %rdx
266 movq %rsi, %rax
267
268 movq %r10, %rdi
269 movl $512, %ecx
270 rep ; movsq
271
272 movq %rax, %rdi
273 movq %rdx, %rsi
274 movl $512, %ecx
275 rep ; movsq
276
277 movq %rdx, %rdi
278 movq %r10, %rsi
279 movl $512, %ecx
280 rep ; movsq
281
282 lea PAGE_SIZE(%rax), %rsi
283 jmp 0b
284 3:
285 ret
286
287 .globl kexec_control_code_size
288 .set kexec_control_code_size, . - relocate_kernel