Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/boot/compressed/head_64.S
10820 views
1
/*
2
* linux/boot/head.S
3
*
4
* Copyright (C) 1991, 1992, 1993 Linus Torvalds
5
*/
6
7
/*
8
* head.S contains the 32-bit startup code.
9
*
10
* NOTE!!! Startup happens at absolute address 0x00001000, which is also where
11
* the page directory will exist. The startup code will be overwritten by
12
* the page directory. [According to comments etc elsewhere on a compressed
13
* kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
14
*
15
* Page 0 is deliberately kept safe, since System Management Mode code in
16
* laptops may need to access the BIOS data stored there. This is also
17
* useful for future device drivers that either access the BIOS via VM86
18
* mode.
19
*/
20
21
/*
22
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
23
*/
24
.code32
25
.text
26
27
#include <linux/init.h>
28
#include <linux/linkage.h>
29
#include <asm/segment.h>
30
#include <asm/pgtable_types.h>
31
#include <asm/page_types.h>
32
#include <asm/boot.h>
33
#include <asm/msr.h>
34
#include <asm/processor-flags.h>
35
#include <asm/asm-offsets.h>
36
37
__HEAD
38
.code32
39
ENTRY(startup_32)
40
cld
41
/*
42
* Test KEEP_SEGMENTS flag to see if the bootloader is asking
43
* us to not reload segments
44
*/
45
testb $(1<<6), BP_loadflags(%esi)
46
jnz 1f
47
48
cli
49
movl $(__KERNEL_DS), %eax
50
movl %eax, %ds
51
movl %eax, %es
52
movl %eax, %ss
53
1:
54
55
/*
56
* Calculate the delta between where we were compiled to run
57
* at and where we were actually loaded at. This can only be done
58
* with a short local call on x86. Nothing else will tell us what
59
* address we are running at. The reserved chunk of the real-mode
60
* data at 0x1e4 (defined as a scratch field) are used as the stack
61
* for this calculation. Only 4 bytes are needed.
62
*/
63
leal (BP_scratch+4)(%esi), %esp
64
call 1f
65
1: popl %ebp
66
subl $1b, %ebp
67
68
/* setup a stack and make sure cpu supports long mode. */
69
movl $boot_stack_end, %eax
70
addl %ebp, %eax
71
movl %eax, %esp
72
73
call verify_cpu
74
testl %eax, %eax
75
jnz no_longmode
76
77
/*
78
* Compute the delta between where we were compiled to run at
79
* and where the code will actually run at.
80
*
81
* %ebp contains the address we are loaded at by the boot loader and %ebx
82
* contains the address where we should move the kernel image temporarily
83
* for safe in-place decompression.
84
*/
85
86
#ifdef CONFIG_RELOCATABLE
87
movl %ebp, %ebx
88
movl BP_kernel_alignment(%esi), %eax
89
decl %eax
90
addl %eax, %ebx
91
notl %eax
92
andl %eax, %ebx
93
#else
94
movl $LOAD_PHYSICAL_ADDR, %ebx
95
#endif
96
97
/* Target address to relocate to for decompression */
98
addl $z_extract_offset, %ebx
99
100
/*
101
* Prepare for entering 64 bit mode
102
*/
103
104
/* Load new GDT with the 64bit segments using 32bit descriptor */
105
leal gdt(%ebp), %eax
106
movl %eax, gdt+2(%ebp)
107
lgdt gdt(%ebp)
108
109
/* Enable PAE mode */
110
movl $(X86_CR4_PAE), %eax
111
movl %eax, %cr4
112
113
/*
114
* Build early 4G boot pagetable
115
*/
116
/* Initialize Page tables to 0 */
117
leal pgtable(%ebx), %edi
118
xorl %eax, %eax
119
movl $((4096*6)/4), %ecx
120
rep stosl
121
122
/* Build Level 4 */
123
leal pgtable + 0(%ebx), %edi
124
leal 0x1007 (%edi), %eax
125
movl %eax, 0(%edi)
126
127
/* Build Level 3 */
128
leal pgtable + 0x1000(%ebx), %edi
129
leal 0x1007(%edi), %eax
130
movl $4, %ecx
131
1: movl %eax, 0x00(%edi)
132
addl $0x00001000, %eax
133
addl $8, %edi
134
decl %ecx
135
jnz 1b
136
137
/* Build Level 2 */
138
leal pgtable + 0x2000(%ebx), %edi
139
movl $0x00000183, %eax
140
movl $2048, %ecx
141
1: movl %eax, 0(%edi)
142
addl $0x00200000, %eax
143
addl $8, %edi
144
decl %ecx
145
jnz 1b
146
147
/* Enable the boot page tables */
148
leal pgtable(%ebx), %eax
149
movl %eax, %cr3
150
151
/* Enable Long mode in EFER (Extended Feature Enable Register) */
152
movl $MSR_EFER, %ecx
153
rdmsr
154
btsl $_EFER_LME, %eax
155
wrmsr
156
157
/*
158
* Setup for the jump to 64bit mode
159
*
160
* When the jump is performend we will be in long mode but
161
* in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
162
* (and in turn EFER.LMA = 1). To jump into 64bit mode we use
163
* the new gdt/idt that has __KERNEL_CS with CS.L = 1.
164
* We place all of the values on our mini stack so lret can
165
* used to perform that far jump.
166
*/
167
pushl $__KERNEL_CS
168
leal startup_64(%ebp), %eax
169
pushl %eax
170
171
/* Enter paged protected Mode, activating Long Mode */
172
movl $(X86_CR0_PG | X86_CR0_PE), %eax /* Enable Paging and Protected mode */
173
movl %eax, %cr0
174
175
/* Jump from 32bit compatibility mode into 64bit mode. */
176
lret
177
ENDPROC(startup_32)
178
179
no_longmode:
180
/* This isn't an x86-64 CPU so hang */
181
1:
182
hlt
183
jmp 1b
184
185
#include "../../kernel/verify_cpu.S"
186
187
/*
188
* Be careful here startup_64 needs to be at a predictable
189
* address so I can export it in an ELF header. Bootloaders
190
* should look at the ELF header to find this address, as
191
* it may change in the future.
192
*/
193
.code64
194
.org 0x200
195
ENTRY(startup_64)
196
/*
197
* We come here either from startup_32 or directly from a
198
* 64bit bootloader. If we come here from a bootloader we depend on
199
* an identity mapped page table being provied that maps our
200
* entire text+data+bss and hopefully all of memory.
201
*/
202
203
/* Setup data segments. */
204
xorl %eax, %eax
205
movl %eax, %ds
206
movl %eax, %es
207
movl %eax, %ss
208
movl %eax, %fs
209
movl %eax, %gs
210
lldt %ax
211
movl $0x20, %eax
212
ltr %ax
213
214
/*
215
* Compute the decompressed kernel start address. It is where
216
* we were loaded at aligned to a 2M boundary. %rbp contains the
217
* decompressed kernel start address.
218
*
219
* If it is a relocatable kernel then decompress and run the kernel
220
* from load address aligned to 2MB addr, otherwise decompress and
221
* run the kernel from LOAD_PHYSICAL_ADDR
222
*
223
* We cannot rely on the calculation done in 32-bit mode, since we
224
* may have been invoked via the 64-bit entry point.
225
*/
226
227
/* Start with the delta to where the kernel will run at. */
228
#ifdef CONFIG_RELOCATABLE
229
leaq startup_32(%rip) /* - $startup_32 */, %rbp
230
movl BP_kernel_alignment(%rsi), %eax
231
decl %eax
232
addq %rax, %rbp
233
notq %rax
234
andq %rax, %rbp
235
#else
236
movq $LOAD_PHYSICAL_ADDR, %rbp
237
#endif
238
239
/* Target address to relocate to for decompression */
240
leaq z_extract_offset(%rbp), %rbx
241
242
/* Set up the stack */
243
leaq boot_stack_end(%rbx), %rsp
244
245
/* Zero EFLAGS */
246
pushq $0
247
popfq
248
249
/*
250
* Copy the compressed kernel to the end of our buffer
251
* where decompression in place becomes safe.
252
*/
253
pushq %rsi
254
leaq (_bss-8)(%rip), %rsi
255
leaq (_bss-8)(%rbx), %rdi
256
movq $_bss /* - $startup_32 */, %rcx
257
shrq $3, %rcx
258
std
259
rep movsq
260
cld
261
popq %rsi
262
263
/*
264
* Jump to the relocated address.
265
*/
266
leaq relocated(%rbx), %rax
267
jmp *%rax
268
269
.text
270
relocated:
271
272
/*
273
* Clear BSS (stack is currently empty)
274
*/
275
xorl %eax, %eax
276
leaq _bss(%rip), %rdi
277
leaq _ebss(%rip), %rcx
278
subq %rdi, %rcx
279
shrq $3, %rcx
280
rep stosq
281
282
/*
283
* Adjust our own GOT
284
*/
285
leaq _got(%rip), %rdx
286
leaq _egot(%rip), %rcx
287
1:
288
cmpq %rcx, %rdx
289
jae 2f
290
addq %rbx, (%rdx)
291
addq $8, %rdx
292
jmp 1b
293
2:
294
295
/*
296
* Do the decompression, and jump to the new kernel..
297
*/
298
pushq %rsi /* Save the real mode argument */
299
movq %rsi, %rdi /* real mode address */
300
leaq boot_heap(%rip), %rsi /* malloc area for uncompression */
301
leaq input_data(%rip), %rdx /* input_data */
302
movl $z_input_len, %ecx /* input_len */
303
movq %rbp, %r8 /* output target address */
304
call decompress_kernel
305
popq %rsi
306
307
/*
308
* Jump to the decompressed kernel.
309
*/
310
jmp *%rbp
311
312
.data
313
gdt:
314
.word gdt_end - gdt
315
.long gdt
316
.word 0
317
.quad 0x0000000000000000 /* NULL descriptor */
318
.quad 0x00af9a000000ffff /* __KERNEL_CS */
319
.quad 0x00cf92000000ffff /* __KERNEL_DS */
320
.quad 0x0080890000000000 /* TS descriptor */
321
.quad 0x0000000000000000 /* TS continued */
322
gdt_end:
323
324
/*
325
* Stack and heap for uncompression
326
*/
327
.bss
328
.balign 4
329
boot_heap:
330
.fill BOOT_HEAP_SIZE, 1, 0
331
boot_stack:
332
.fill BOOT_STACK_SIZE, 1, 0
333
boot_stack_end:
334
335
/*
336
* Space for page tables (not in .bss so not zeroed)
337
*/
338
.section ".pgtable","a",@nobits
339
.balign 4096
340
pgtable:
341
.fill 6*4096, 1, 0
342
343