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 / kernel / head.S
1 /*
2  *  linux/arch/x86_64/kernel/head.S -- start in 32bit and switch to 64bit
3  *
4  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
5  *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
6  *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
7  *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
8  *  Copyright (C) 2005 Eric Biederman <ebiederm@xmission.com>
9  */
10
11
12 #include <lwk/linkage.h>
13 #include <lwk/init.h>
14 #include <lwk/cpu.h>
15 #include <arch/desc.h>
16 #include <arch/segment.h>
17 #include <arch/pgtable.h>
18 #include <arch/page.h>
19 #include <arch/msr.h>
20 #include <arch/cache.h>
21
22 /* we are not able to switch in one step to the final KERNEL ADRESS SPACE
23  * because we need identity-mapped pages.
24  *
25  */
26
27         .text
28         .section .bootstrap.text
29
30 #ifdef CONFIG_CRAY_XT
31         .code32
32         .globl startup_32
33 startup_32:
34         cld
35         cli
36         movl    $(__KERNEL_DS), %eax
37         movl    %eax, %ds
38         lgdt    gdt32_descr - __START_KERNEL_map
39
40         /* Enable PAE mode and PGE */
41         xorl    %eax, %eax
42         btsl    $5,   %eax      /* enable PAE */
43         btsl    $7,   %eax      /* enable PGE */
44         movl    %eax, %cr4
45
46         /* Setup early boot page tables */
47         movl    $(init_level4_pgt - __START_KERNEL_map), %eax
48         movl    %eax, %cr3
49
50         /* Enable Long Mode */
51         movl    $MSR_EFER, %ecx
52         rdmsr
53         btsl    $_EFER_LME, %eax
54         wrmsr
55         xorl    %eax, %eax
56         btsl    $31,  %eax      /* enable paging */
57         btsl    $0,   %eax      /* enable protected mode */
58         movl    %eax, %cr0
59
60         /* coldstart uses a hard-coded address for real_mode_data */
61         movl    $0x90000, %esi
62
63         /*
64          * At this point we're in long mode but 32-bit compatibility mode.
65          * This jump transitions us into true 64-bit mode.
66          */
67         ljmp    $__KERNEL_CS, $(startup_64 - __START_KERNEL_map)
68 #endif /* CONFIG_CRAY_XT */
69
70         .code64
71         .globl startup_64
72 startup_64:
73
74         /*
75          * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 1,
76          * and someone has loaded an identity mapped page table
77          * for us.  These identity mapped page tables map all of the
78          * kernel pages and possibly all of memory.
79          *
80          * %esi holds a physical pointer to real_mode_data.
81          *
82          * We come here either directly from a 64bit bootloader, or from
83          * arch/x86_64/boot/compressed/head.S.
84          *
85          * We only come here initially at boot nothing else comes here.
86          *
87          * Since we may be loaded at an address different from what we were
88          * compiled to run at we first fixup the physical addresses in our page
89          * tables and then reload them.
90          */
91
92         /* Compute the delta between the address I am compiled to run at and the
93          * address I am actually running at.
94          */
95         leaq    _text(%rip), %rbp
96         subq    $_text - __START_KERNEL_map, %rbp
97
98         /* Is the address not 2M aligned? */
99         movq    %rbp, %rax
100         andl    $~LARGE_PAGE_MASK, %eax
101         testl   %eax, %eax
102         jnz     bad_address
103
104         /* Is the address too large? */
105         leaq    _text(%rip), %rdx
106         movq    $PGDIR_SIZE, %rax
107         cmpq    %rax, %rdx
108         jae     bad_address
109
110         /* Fixup the physical addresses in the page table
111          */
112         addq    %rbp, init_level4_pgt + 0(%rip)
113         addq    %rbp, init_level4_pgt + (258*8)(%rip)
114         addq    %rbp, init_level4_pgt + (511*8)(%rip)
115
116         addq    %rbp, level3_ident_pgt + 0(%rip)
117         addq    %rbp, level3_kernel_pgt + (510*8)(%rip)
118
119         /* Add an Identity mapping if I am above 1G */
120         leaq    _text(%rip), %rdi
121         andq    $LARGE_PAGE_MASK, %rdi
122
123         movq    %rdi, %rax
124         shrq    $PUD_SHIFT, %rax
125         andq    $(PTRS_PER_PUD - 1), %rax
126         jz      ident_complete
127
128         leaq    (level2_spare_pgt - __START_KERNEL_map + _KERNPG_TABLE)(%rbp), %rdx
129         leaq    level3_ident_pgt(%rip), %rbx
130         movq    %rdx, 0(%rbx, %rax, 8)
131
132         movq    %rdi, %rax
133         shrq    $PMD_SHIFT, %rax
134         andq    $(PTRS_PER_PMD - 1), %rax
135         leaq    __PAGE_KERNEL_LARGE_EXEC(%rdi), %rdx
136         leaq    level2_spare_pgt(%rip), %rbx
137         movq    %rdx, 0(%rbx, %rax, 8)
138 ident_complete:
139
140         /* Fixup the kernel text+data virtual addresses
141          */
142         leaq    level2_kernel_pgt(%rip), %rdi
143         leaq    4096(%rdi), %r8
144         /* See if it is a valid page table entry */
145 1:      testq   $1, 0(%rdi)
146         jz      2f
147         addq    %rbp, 0(%rdi)
148         /* Go to the next page */
149 2:      addq    $8, %rdi
150         cmp     %r8, %rdi
151         jne     1b
152
153         /* Fixup phys_base */
154         addq    %rbp, phys_base(%rip)
155
156         addq    %rbp, trampoline_level4_pgt + 0(%rip)
157         addq    %rbp, trampoline_level4_pgt + (511*8)(%rip)
158 #ifdef CONFIG_ACPI_SLEEP
159         addq    %rbp, wakeup_level4_pgt + 0(%rip)
160         addq    %rbp, wakeup_level4_pgt + (511*8)(%rip)
161 #endif
162
163         /* Due to ENTRY(), sometimes the empty space gets filled with
164          * zeros. Better take a jmp than relying on empty space being
165          * filled with 0x90 (nop)
166          */
167         jmp secondary_startup_64
168 ENTRY(secondary_startup_64)
169         /*
170          * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 1,
171          * and someone has loaded a mapped page table.
172          *
173          * %esi holds a physical pointer to real_mode_data.
174          *
175          * We come here either from startup_64 (using physical addresses)
176          * or from trampoline.S (using virtual addresses).
177          *
178          * Using virtual addresses from trampoline.S removes the need
179          * to have any identity mapped pages in the kernel page table
180          * after the boot processor executes this code.
181          */
182
183         /* Enable PAE mode and PGE */
184         xorq    %rax, %rax
185         btsq    $5, %rax
186         btsq    $7, %rax
187         movq    %rax, %cr4
188
189         /* Setup early boot stage 4 level pagetables. */
190         movq    $(init_level4_pgt - __START_KERNEL_map), %rax
191         addq    phys_base(%rip), %rax
192         movq    %rax, %cr3
193
194         /* Ensure I am executing from virtual addresses */
195         movq    $1f, %rax
196         jmp     *%rax
197 1:
198
199         /* Check if nx is implemented */
200         movl    $0x80000001, %eax
201         cpuid
202         movl    %edx,%edi
203
204         /* Setup EFER (Extended Feature Enable Register) */
205         movl    $MSR_EFER, %ecx
206         rdmsr
207         btsl    $_EFER_SCE, %eax        /* Enable System Call */
208         btl     $20,%edi                /* No Execute supported? */
209         jnc     1f
210         btsl    $_EFER_NX, %eax
211 1:      wrmsr                           /* Make changes effective */
212
213         /* Setup cr0 */
214 #define CR0_PM                          1               /* protected mode */
215 #define CR0_MP                          (1<<1)
216 #define CR0_ET                          (1<<4)
217 #define CR0_NE                          (1<<5)
218 #define CR0_WP                          (1<<16)
219 #define CR0_AM                          (1<<18)
220 #define CR0_PAGING                      (1<<31)
221         movl $CR0_PM|CR0_MP|CR0_ET|CR0_NE|CR0_WP|CR0_AM|CR0_PAGING,%eax
222         /* Make changes effective */
223         movq    %rax, %cr0
224
225         /* Setup a boot time stack */
226         movq init_rsp(%rip),%rsp
227
228         /* zero EFLAGS after setting rsp */
229         pushq $0
230         popfq
231
232         /*
233          * We must switch to a new descriptor in kernel space for the GDT
234          * because soon the kernel won't have access anymore to the userspace
235          * addresses where we're currently running on. We have to do that here
236          * because in 32bit we couldn't load a 64bit linear address.
237          */
238         lgdt    cpu_gdt_descr(%rip)
239
240         /* set up data segments. actually 0 would do too */
241         movl $__KERNEL_DS,%eax
242         movl %eax,%ds
243         movl %eax,%ss
244         movl %eax,%es
245
246         /*
247          * We don't really need to load %fs or %gs, but load them anyway
248          * to kill any stale realmode selectors.  This allows execution
249          * under VT hardware.
250          */
251         movl %eax,%fs
252         movl %eax,%gs
253
254         /* 
255          * Setup up a dummy PDA. this is just for some early bootup code
256          * that does in_interrupt() 
257          */ 
258         movl    $MSR_GS_BASE,%ecx
259         movq    $empty_zero_page,%rax
260         movq    %rax,%rdx
261         shrq    $32,%rdx
262         wrmsr   
263
264         /* esi is pointer to real mode structure with interesting info.
265            pass it to C */
266         movl    %esi, %edi
267         
268         /* Finally jump to run C code and to be on real kernel address
269          * Since we are running on identity-mapped space we have to jump
270          * to the full 64bit address, this is only possible as indirect
271          * jump.  In addition we need to ensure %cs is set so we make this
272          * a far return.
273          */
274         movq    initial_code(%rip),%rax
275         pushq   $0              # fake return address to stop unwinder
276         pushq   $__KERNEL_CS    # set correct cs
277         pushq   %rax            # target address in negative space
278         lretq
279
280         /* SMP bootup changes these two */
281         .align  8
282         .globl  initial_code
283 initial_code:
284         .quad   x86_64_start_kernel
285         .globl init_rsp
286 init_rsp:
287         .quad  bootstrap_task_union+TASK_SIZE-8
288
289 bad_address:
290         jmp bad_address
291
292 ENTRY(early_idt_handler)
293         cmpl $2,early_recursion_flag(%rip)
294         jz  1f
295         incl early_recursion_flag(%rip)
296         xorl %eax,%eax
297         movq 8(%rsp),%rsi       # get rip
298         movq (%rsp),%rdx
299         movq %cr2,%rcx
300         leaq early_idt_msg(%rip),%rdi
301         call printk
302         cmpl $2,early_recursion_flag(%rip)
303         jz  1f
304 //      call dump_stack
305 1:      hlt
306         jmp 1b
307 early_recursion_flag:
308         .long 0
309
310 early_idt_msg:
311         .asciz "PANIC: early exception rip %lx error %lx cr2 %lx\n"
312 early_idt_ripmsg:
313         .asciz "RIP %s\n"
314
315 .balign PAGE_SIZE
316
317 #define NEXT_PAGE(name) \
318         .balign PAGE_SIZE; \
319 ENTRY(name)
320
321 /* Automate the creation of 1 to 1 mapping pmd entries */
322 #define PMDS(START, PERM, COUNT)                \
323         i = 0 ;                                 \
324         .rept (COUNT) ;                         \
325         .quad   (START) + (i << 21) + (PERM) ;  \
326         i = i + 1 ;                             \
327         .endr
328
329         /*
330          * This default setting generates an ident mapping at address 0x100000
331          * and a mapping for the kernel that precisely maps virtual address
332          * 0xffffffff80000000 to physical address 0x000000. (always using
333          * 2Mbyte large pages provided by PAE mode)
334          */
335 NEXT_PAGE(init_level4_pgt)
336         .quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
337         .fill   257,8,0
338         .quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
339         .fill   252,8,0
340         /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
341         .quad   level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
342
343 NEXT_PAGE(level3_ident_pgt)
344         .quad   level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
345         .fill   511,8,0
346
347 NEXT_PAGE(level3_kernel_pgt)
348         .fill   510,8,0
349         /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
350         .quad   level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
351 #ifndef CONFIG_CRAY_XT
352         .fill   1,8,0
353 #else
354         .quad   level2_seastar_pgt - __START_KERNEL_map + _KERNPG_TABLE
355 #endif
356
357 NEXT_PAGE(level2_ident_pgt)
358         /* Since I easily can, map the first 1G.
359          * Don't set NX because code runs from these pages.
360          */
361         PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC, PTRS_PER_PMD)
362
363 NEXT_PAGE(level2_kernel_pgt)
364         /* 40MB kernel mapping. The kernel code cannot be bigger than that.
365            When you change this change KERNEL_TEXT_SIZE in page.h too. */
366         /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */
367         PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, KERNEL_TEXT_SIZE/PMD_SIZE)
368         /* Module mapping starts here */
369         .fill   (PTRS_PER_PMD - (KERNEL_TEXT_SIZE/PMD_SIZE)),8,0
370
371 #ifdef CONFIG_CRAY_XT
372 NEXT_PAGE(level2_seastar_pgt)
373         .fill 511,8,0
374         .quad   0x00000000ffe00193
375 #endif
376
377 NEXT_PAGE(level2_spare_pgt)
378         .fill   512,8,0
379
380 #undef PMDS
381 #undef NEXT_PAGE
382
383         .data
384         .align 16
385         .globl cpu_gdt_descr
386 cpu_gdt_descr:
387         .word   gdt_end-cpu_gdt_table-1
388 gdt:
389         .quad   cpu_gdt_table
390         .rept   NR_CPUS-1
391         .word   0
392         .quad   0
393         .endr
394
395 #ifdef CONFIG_CRAY_XT
396         .align 16
397         .globl gdt32_descr
398 gdt32_descr:
399         .word   gdt_end-cpu_gdt_table-1
400         .long   cpu_gdt_table-__START_KERNEL_map
401 #endif
402
403 ENTRY(phys_base)
404         /* This must match the first entry in level2_kernel_pgt */
405         .quad   0x0000000000000000
406
407 /* We need valid kernel segments for data and code in long mode too
408  * IRET will check the segment types  kkeil 2000/10/28
409  * Also sysret mandates a special GDT layout 
410  */
411                                 
412         .section .data.page_aligned, "aw"
413         .align PAGE_SIZE
414
415 /* The TLS descriptors are currently at a different place compared to i386.
416    Hopefully nobody expects them at a fixed place (Wine?) */
417         
418 ENTRY(cpu_gdt_table)
419         .quad   0x0000000000000000      /* NULL descriptor */
420         .quad   0x00cf9b000000ffff      /* __KERNEL32_CS */
421         .quad   0x00af9b000000ffff      /* __KERNEL_CS */
422         .quad   0x00cf93000000ffff      /* __KERNEL_DS */
423         .quad   0x00cffb000000ffff      /* __USER32_CS */
424         .quad   0x00cff3000000ffff      /* __USER_DS, __USER32_DS  */
425         .quad   0x00affb000000ffff      /* __USER_CS */
426         .quad   0x0                     /* unused */
427         .quad   0,0                     /* TSS */
428         .quad   0,0                     /* LDT */
429         .quad   0,0,0                   /* three TLS descriptors */ 
430         .quad   0x0000f40000000000      /* node/CPU stored in limit */
431 gdt_end:        
432         /* asm/segment.h:GDT_ENTRIES must match this */ 
433         /* This should be a multiple of the cache line size */
434         /* GDTs of other CPUs are now dynamically allocated */
435
436         /* zero the remaining page */
437         .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
438
439         .section .bss, "aw", @nobits
440         .align L1_CACHE_BYTES
441 ENTRY(idt_table)
442         .skip 256 * 16
443
444         .section .bss.page_aligned, "aw", @nobits
445         .align PAGE_SIZE
446 ENTRY(empty_zero_page)
447         .skip PAGE_SIZE