Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / boot / compressed / head.S
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 <lwk/linkage.h>
28 #include <arch/segment.h>
29 #include <arch/pgtable.h>
30 #include <arch/page.h>
31 #include <arch/msr.h>
32
33 .section ".text.head"
34         .code32
35         .globl startup_32
36
37 startup_32:
38         cld
39         cli
40         movl    $(__KERNEL_DS), %eax
41         movl    %eax, %ds
42         movl    %eax, %es
43         movl    %eax, %ss
44
45 /* Calculate the delta between where we were compiled to run
46  * at and where we were actually loaded at.  This can only be done
47  * with a short local call on x86.  Nothing  else will tell us what
48  * address we are running at.  The reserved chunk of the real-mode
49  * data at 0x34-0x3f are used as the stack for this calculation.
50  * Only 4 bytes are needed.
51  */
52         leal    0x40(%esi), %esp
53         call    1f
54 1:      popl    %ebp
55         subl    $1b, %ebp
56
57 /* setup a stack and make sure cpu supports long mode. */
58         movl    $user_stack_end, %eax
59         addl    %ebp, %eax
60         movl    %eax, %esp
61
62         call    verify_cpu
63         testl   %eax, %eax
64         jnz     no_longmode
65
66 /* Compute the delta between where we were compiled to run at
67  * and where the code will actually run at.
68  */
69 /* %ebp contains the address we are loaded at by the boot loader and %ebx
70  * contains the address where we should move the kernel image temporarily
71  * for safe in-place decompression.
72  */
73
74 #ifdef CONFIG_RELOCATABLE
75         movl    %ebp, %ebx
76         addl    $(LARGE_PAGE_SIZE -1), %ebx
77         andl    $LARGE_PAGE_MASK, %ebx
78 #else
79         movl    $CONFIG_PHYSICAL_START, %ebx
80 #endif
81
82         /* Replace the compressed data size with the uncompressed size */
83         subl    input_len(%ebp), %ebx
84         movl    output_len(%ebp), %eax
85         addl    %eax, %ebx
86         /* Add 8 bytes for every 32K input block */
87         shrl    $12, %eax
88         addl    %eax, %ebx
89         /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */
90         addl    $(32768 + 18 + 4095), %ebx
91         andl    $~4095, %ebx
92
93 /*
94  * Prepare for entering 64 bit mode
95  */
96
97         /* Load new GDT with the 64bit segments using 32bit descriptor */
98         leal    gdt(%ebp), %eax
99         movl    %eax, gdt+2(%ebp)
100         lgdt    gdt(%ebp)
101
102         /* Enable PAE mode */
103         xorl    %eax, %eax
104         orl     $(1 << 5), %eax
105         movl    %eax, %cr4
106
107  /*
108   * Build early 4G boot pagetable
109   */
110         /* Initialize Page tables to 0*/
111         leal    pgtable(%ebx), %edi
112         xorl    %eax, %eax
113         movl    $((4096*6)/4), %ecx
114         rep     stosl
115
116         /* Build Level 4 */
117         leal    pgtable + 0(%ebx), %edi
118         leal    0x1007 (%edi), %eax
119         movl    %eax, 0(%edi)
120
121         /* Build Level 3 */
122         leal    pgtable + 0x1000(%ebx), %edi
123         leal    0x1007(%edi), %eax
124         movl    $4, %ecx
125 1:      movl    %eax, 0x00(%edi)
126         addl    $0x00001000, %eax
127         addl    $8, %edi
128         decl    %ecx
129         jnz     1b
130
131         /* Build Level 2 */
132         leal    pgtable + 0x2000(%ebx), %edi
133         movl    $0x00000183, %eax
134         movl    $2048, %ecx
135 1:      movl    %eax, 0(%edi)
136         addl    $0x00200000, %eax
137         addl    $8, %edi
138         decl    %ecx
139         jnz     1b
140
141         /* Enable the boot page tables */
142         leal    pgtable(%ebx), %eax
143         movl    %eax, %cr3
144
145         /* Enable Long mode in EFER (Extended Feature Enable Register) */
146         movl    $MSR_EFER, %ecx
147         rdmsr
148         btsl    $_EFER_LME, %eax
149         wrmsr
150
151         /* Setup for the jump to 64bit mode
152          *
153          * When the jump is performend we will be in long mode but
154          * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1
155          * (and in turn EFER.LMA = 1).  To jump into 64bit mode we use
156          * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
157          * We place all of the values on our mini stack so lret can
158          * used to perform that far jump.
159          */
160         pushl   $__KERNEL_CS
161         leal    startup_64(%ebp), %eax
162         pushl   %eax
163
164         /* Enter paged protected Mode, activating Long Mode */
165         movl    $0x80000001, %eax /* Enable Paging and Protected mode */
166         movl    %eax, %cr0
167
168         /* Jump from 32bit compatibility mode into 64bit mode. */
169         lret
170
171 no_longmode:
172         /* This isn't an x86-64 CPU so hang */
173 1:
174         hlt
175         jmp     1b
176
177 #include "../../kernel/verify_cpu.S"
178
179         /* Be careful here startup_64 needs to be at a predictable
180          * address so I can export it in an ELF header.  Bootloaders
181          * should look at the ELF header to find this address, as
182          * it may change in the future.
183          */
184         .code64
185         .org 0x200
186 ENTRY(startup_64)
187         /* We come here either from startup_32 or directly from a
188          * 64bit bootloader.  If we come here from a bootloader we depend on
189          * an identity mapped page table being provied that maps our
190          * entire text+data+bss and hopefully all of memory.
191          */
192
193         /* Setup data segments. */
194         xorl    %eax, %eax
195         movl    %eax, %ds
196         movl    %eax, %es
197         movl    %eax, %ss
198
199         /* Compute the decompressed kernel start address.  It is where
200          * we were loaded at aligned to a 2M boundary. %rbp contains the
201          * decompressed kernel start address.
202          *
203          * If it is a relocatable kernel then decompress and run the kernel
204          * from load address aligned to 2MB addr, otherwise decompress and
205          * run the kernel from CONFIG_PHYSICAL_START
206          */
207
208         /* Start with the delta to where the kernel will run at. */
209 #ifdef CONFIG_RELOCATABLE
210         leaq    startup_32(%rip) /* - $startup_32 */, %rbp
211         addq    $(LARGE_PAGE_SIZE - 1), %rbp
212         andq    $LARGE_PAGE_MASK, %rbp
213         movq    %rbp, %rbx
214 #else
215         movq    $CONFIG_PHYSICAL_START, %rbp
216         movq    %rbp, %rbx
217 #endif
218
219         /* Replace the compressed data size with the uncompressed size */
220         movl    input_len(%rip), %eax
221         subq    %rax, %rbx
222         movl    output_len(%rip), %eax
223         addq    %rax, %rbx
224         /* Add 8 bytes for every 32K input block */
225         shrq    $12, %rax
226         addq    %rax, %rbx
227         /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */
228         addq    $(32768 + 18 + 4095), %rbx
229         andq    $~4095, %rbx
230
231 /* Copy the compressed kernel to the end of our buffer
232  * where decompression in place becomes safe.
233  */
234         leaq    _end(%rip), %r8
235         leaq    _end(%rbx), %r9
236         movq    $_end /* - $startup_32 */, %rcx
237 1:      subq    $8, %r8
238         subq    $8, %r9
239         movq    0(%r8), %rax
240         movq    %rax, 0(%r9)
241         subq    $8, %rcx
242         jnz     1b
243
244 /*
245  * Jump to the relocated address.
246  */
247         leaq    relocated(%rbx), %rax
248         jmp     *%rax
249
250 .section ".text"
251 relocated:
252
253 /*
254  * Clear BSS
255  */
256         xorq    %rax, %rax
257         leaq    _edata(%rbx), %rdi
258         leaq    _end(%rbx), %rcx
259         subq    %rdi, %rcx
260         cld
261         rep
262         stosb
263
264         /* Setup the stack */
265         leaq    user_stack_end(%rip), %rsp
266
267         /* zero EFLAGS after setting rsp */
268         pushq   $0
269         popfq
270
271 /*
272  * Do the decompression, and jump to the new kernel..
273  */
274         pushq   %rsi                    # Save the real mode argument
275         movq    %rsi, %rdi              # real mode address
276         leaq    _heap(%rip), %rsi       # _heap
277         leaq    input_data(%rip), %rdx  # input_data
278         movl    input_len(%rip), %eax
279         movq    %rax, %rcx              # input_len
280         movq    %rbp, %r8               # output
281         call    decompress_kernel
282         popq    %rsi
283
284
285 /*
286  * Jump to the decompressed kernel.
287  */
288         jmp     *%rbp
289
290         .data
291 gdt:
292         .word   gdt_end - gdt
293         .long   gdt
294         .word   0
295         .quad   0x0000000000000000      /* NULL descriptor */
296         .quad   0x00af9a000000ffff      /* __KERNEL_CS */
297         .quad   0x00cf92000000ffff      /* __KERNEL_DS */
298 gdt_end:
299         .bss
300 /* Stack for uncompression */
301         .balign 4
302 user_stack:
303         .fill 4096,4,0
304 user_stack_end: