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
12
13
14
15
16 #define PTR(x) (x << 2)
17
18
19
20
21
22
23 #define DATA(offset) (KEXEC_CONTROL_CODE_MAX_SIZE+(offset))
24
25
26 #define ESP DATA(0x0)
27 #define CR0 DATA(0x4)
28 #define CR3 DATA(0x8)
29 #define CR4 DATA(0xc)
30
31
32 #define CP_VA_CONTROL_PAGE DATA(0x10)
33 #define CP_PA_PGD DATA(0x14)
34 #define CP_PA_SWAP_PAGE DATA(0x18)
35 #define CP_PA_BACKUP_PAGES_MAP DATA(0x1c)
36
37 .text
38 .globl relocate_kernel
39 relocate_kernel:
40
41
42 pushl %ebx
43 pushl %esi
44 pushl %edi
45 pushl %ebp
46 pushf
47
48 movl 20+8(%esp), %ebp
49 movl PTR(VA_CONTROL_PAGE)(%ebp), %edi
50 movl %esp, ESP(%edi)
51 movl %cr0, %eax
52 movl %eax, CR0(%edi)
53 movl %cr3, %eax
54 movl %eax, CR3(%edi)
55 movl %cr4, %eax
56 movl %eax, CR4(%edi)
57
58
59 movl 20+4(%esp), %ebx
60 movl 20+8(%esp), %ebp
61 movl 20+12(%esp), %edx
62 movl 20+16(%esp), %ecx
63 movl 20+20(%esp), %esi
64
65
66 pushl $0
67 popfl
68
69
70 movl PTR(VA_CONTROL_PAGE)(%ebp), %edi
71 movl %edi, CP_VA_CONTROL_PAGE(%edi)
72 movl PTR(PA_PGD)(%ebp), %eax
73 movl %eax, CP_PA_PGD(%edi)
74 movl PTR(PA_SWAP_PAGE)(%ebp), %eax
75 movl %eax, CP_PA_SWAP_PAGE(%edi)
76 movl %ebx, CP_PA_BACKUP_PAGES_MAP(%edi)
77
78
79
80
81
82 movl PTR(PA_CONTROL_PAGE)(%ebp), %edi
83
84
85 movl PTR(PA_PGD)(%ebp), %eax
86 movl %eax, %cr3
87
88
89 lea PAGE_SIZE(%edi), %esp
90
91
92 movl %edi, %eax
93 addl $(identity_mapped - relocate_kernel), %eax
94 pushl %eax
95 ret
96
97 identity_mapped:
98
99 pushl $0
100
101 pushl %edx
102
103
104
105
106
107
108
109
110
111
112 movl %cr0, %eax
113 andl $~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %eax
114 orl $(X86_CR0_PE), %eax
115 movl %eax, %cr0
116
117
118 testl %ecx, %ecx
119 jz 1f
120
121
122
123
124 xorl %eax, %eax
125 movl %eax, %cr4
126
127 jmp 1f
128 1:
129
130
131 xorl %eax, %eax
132 movl %eax, %cr3
133
134 movl CP_PA_SWAP_PAGE(%edi), %eax
135 pushl %eax
136 pushl %ebx
137 call swap_pages
138 addl $8, %esp
139
140
141
142
143
144
145 xorl %eax, %eax
146 movl %eax, %cr3
147
148
149
150
151
152
153 testl %esi, %esi
154 jnz 1f
155 xorl %edi, %edi
156 xorl %eax, %eax
157 xorl %ebx, %ebx
158 xorl %ecx, %ecx
159 xorl %edx, %edx
160 xorl %esi, %esi
161 xorl %ebp, %ebp
162 ret
163 1:
164 popl %edx
165 movl CP_PA_SWAP_PAGE(%edi), %esp
166 addl $PAGE_SIZE, %esp
167 2:
168 call *%edx
169
170
171 movl 0(%esp), %ebp
172 call 1f
173 1:
174 popl %ebx
175 subl $(1b - relocate_kernel), %ebx
176 movl CP_VA_CONTROL_PAGE(%ebx), %edi
177 lea PAGE_SIZE(%ebx), %esp
178 movl CP_PA_SWAP_PAGE(%ebx), %eax
179 movl CP_PA_BACKUP_PAGES_MAP(%ebx), %edx
180 pushl %eax
181 pushl %edx
182 call swap_pages
183 addl $8, %esp
184 movl CP_PA_PGD(%ebx), %eax
185 movl %eax, %cr3
186 movl %cr0, %eax
187 orl $X86_CR0_PG, %eax
188 movl %eax, %cr0
189 lea PAGE_SIZE(%edi), %esp
190 movl %edi, %eax
191 addl $(virtual_mapped - relocate_kernel), %eax
192 pushl %eax
193 ret
194
195 virtual_mapped:
196 movl CR4(%edi), %eax
197 movl %eax, %cr4
198 movl CR3(%edi), %eax
199 movl %eax, %cr3
200 movl CR0(%edi), %eax
201 movl %eax, %cr0
202 movl ESP(%edi), %esp
203 movl %ebp, %eax
204
205 popf
206 popl %ebp
207 popl %edi
208 popl %esi
209 popl %ebx
210 ret
211
212
213 swap_pages:
214 movl 8(%esp), %edx
215 movl 4(%esp), %ecx
216 pushl %ebp
217 pushl %ebx
218 pushl %edi
219 pushl %esi
220 movl %ecx, %ebx
221 jmp 1f
222
223 0:
224 movl (%ebx), %ecx
225 addl $4, %ebx
226 1:
227 testb $0x1, %cl
228 jz 2f
229 movl %ecx, %edi
230 andl $0xfffff000, %edi
231 jmp 0b
232 2:
233 testb $0x2, %cl
234 jz 2f
235 movl %ecx, %ebx
236 andl $0xfffff000, %ebx
237 jmp 0b
238 2:
239 testb $0x4, %cl
240 jz 2f
241 jmp 3f
242 2:
243 testb $0x8, %cl
244 jz 0b
245 movl %ecx, %esi
246 andl $0xfffff000, %esi
247
248 movl %edi, %eax
249 movl %esi, %ebp
250
251 movl %edx, %edi
252 movl $1024, %ecx
253 rep ; movsl
254
255 movl %ebp, %edi
256 movl %eax, %esi
257 movl $1024, %ecx
258 rep ; movsl
259
260 movl %eax, %edi
261 movl %edx, %esi
262 movl $1024, %ecx
263 rep ; movsl
264
265 lea PAGE_SIZE(%ebp), %esi
266 jmp 0b
267 3:
268 popl %esi
269 popl %edi
270 popl %ebx
271 popl %ebp
272 ret
273
274 .globl kexec_control_code_size
275 .set kexec_control_code_size, . - relocate_kernel