fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / x86_64 / kernel / head-xen.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  *
9  *  Jun Nakajima <jun.nakajima@intel.com>
10  *    Modified for Xen                                
11  */
12
13
14 #include <linux/linkage.h>
15 #include <linux/threads.h>
16 #include <linux/init.h>
17 #include <linux/elfnote.h>
18 #include <asm/desc.h>
19 #include <asm/segment.h>
20 #include <asm/page.h>
21 #include <asm/msr.h>
22 #include <asm/cache.h>
23
24 #include <xen/interface/elfnote.h>
25
26         .text
27         .section .bootstrap.text
28         .code64
29 #define VIRT_ENTRY_OFFSET 0x0
30 .org VIRT_ENTRY_OFFSET
31         .globl startup_64
32 startup_64:
33 ENTRY(_start)
34         movq $(init_thread_union+THREAD_SIZE-8),%rsp
35         /* zero EFLAGS after setting rsp */
36         pushq $0
37         popfq
38
39         /* rsi is pointer to startup info structure.
40            pass it to C */
41         movq %rsi,%rdi
42         jmp x86_64_start_kernel
43
44 ENTRY(stext)
45 ENTRY(_stext)
46
47         $page = 0
48 #define NEXT_PAGE(name) \
49         $page = $page + 1; \
50         .org $page * 0x1000; \
51         phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \
52 ENTRY(name)
53
54 NEXT_PAGE(init_level4_pgt)
55         /* This gets initialized in x86_64_start_kernel */
56         .fill   512,8,0
57
58         /*
59          * We update two pgd entries to make kernel and user pgd consistent
60          * at pgd_populate(). It can be used for kernel modules. So we place 
61          * this page here for those cases to avoid memory corruption.
62          * We also use this page to establish the initiali mapping for
63          * vsyscall area.
64          */
65 NEXT_PAGE(init_level4_user_pgt)
66         .fill   512,8,0
67
68 NEXT_PAGE(level3_kernel_pgt)
69         .fill   512,8,0
70
71         /*
72          * This is used for vsyscall area mapping as we have a different
73          * level4 page table for user.
74          */
75 NEXT_PAGE(level3_user_pgt)
76         .fill   512,8,0
77
78 NEXT_PAGE(level2_kernel_pgt)
79         .fill   512,8,0
80
81 NEXT_PAGE(hypercall_page)
82         .fill   512,8,0
83
84 #undef NEXT_PAGE
85
86         .data
87
88         .align 16
89         .globl cpu_gdt_descr
90 cpu_gdt_descr:
91         .word   gdt_end-cpu_gdt_table-1
92 gdt:
93         .quad   cpu_gdt_table
94 #ifdef CONFIG_SMP
95         .rept   NR_CPUS-1
96         .word   0
97         .quad   0
98         .endr
99 #endif
100
101 /* We need valid kernel segments for data and code in long mode too
102  * IRET will check the segment types  kkeil 2000/10/28
103  * Also sysret mandates a special GDT layout 
104  */
105                                 
106         .section .data.page_aligned, "aw"
107         .align PAGE_SIZE
108
109 /* The TLS descriptors are currently at a different place compared to i386.
110    Hopefully nobody expects them at a fixed place (Wine?) */
111         
112 ENTRY(cpu_gdt_table)
113         .quad   0x0000000000000000      /* NULL descriptor */
114         .quad   0x0                     /* unused */
115         .quad   0x00af9a000000ffff      /* __KERNEL_CS */
116         .quad   0x00cf92000000ffff      /* __KERNEL_DS */
117         .quad   0x00cffa000000ffff      /* __USER32_CS */
118         .quad   0x00cff2000000ffff      /* __USER_DS, __USER32_DS  */           
119         .quad   0x00affa000000ffff      /* __USER_CS */
120         .quad   0x00cf9a000000ffff      /* __KERNEL32_CS */
121         .quad   0,0                     /* TSS */
122         .quad   0,0                     /* LDT */
123         .quad   0,0,0                   /* three TLS descriptors */ 
124         .quad   0x0000f40000000000      /* node/CPU stored in limit */
125 gdt_end:        
126         /* asm/segment.h:GDT_ENTRIES must match this */ 
127         /* This should be a multiple of the cache line size */
128         /* GDTs of other CPUs are now dynamically allocated */
129
130         /* zero the remaining page */
131         .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
132
133         .section .bss, "aw", @nobits
134         .align L1_CACHE_BYTES
135 ENTRY(idt_table)
136         .skip 256 * 16
137
138         .section .bss.page_aligned, "aw", @nobits
139         .align PAGE_SIZE
140 ENTRY(empty_zero_page)
141         .skip PAGE_SIZE
142
143 #ifdef CONFIG_XEN_COMPAT_030002
144 /*
145  * __xen_guest information
146  */
147 .macro utoh value
148  .if (\value) < 0 || (\value) >= 0x10
149         utoh (((\value)>>4)&0x0fffffffffffffff)
150  .endif
151  .if ((\value) & 0xf) < 10
152   .byte '0' + ((\value) & 0xf)
153  .else
154   .byte 'A' + ((\value) & 0xf) - 10
155  .endif
156 .endm
157
158 .section __xen_guest
159         .ascii  "GUEST_OS=linux,GUEST_VER=2.6"
160         .ascii  ",XEN_VER=xen-3.0"
161         .ascii  ",VIRT_BASE=0x"
162                 utoh __START_KERNEL_map
163         .ascii  ",ELF_PADDR_OFFSET=0x"
164                 utoh __START_KERNEL_map
165         .ascii  ",VIRT_ENTRY=0x"
166                 utoh (__START_KERNEL_map + __PHYSICAL_START + VIRT_ENTRY_OFFSET)
167         .ascii  ",HYPERCALL_PAGE=0x"
168                 utoh (phys_hypercall_page >> PAGE_SHIFT)
169         .ascii  ",FEATURES=writable_page_tables"
170         .ascii           "|writable_descriptor_tables"
171         .ascii           "|auto_translated_physmap"
172         .ascii           "|supervisor_mode_kernel"
173         .ascii  ",LOADER=generic"
174         .byte   0
175 #endif /* CONFIG_XEN_COMPAT_030002 */
176         
177         ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")
178         ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
179         ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
180         ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .quad,  __START_KERNEL_map)
181 #ifdef CONFIG_XEN_COMPAT_030002
182         ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  __START_KERNEL_map)
183 #else
184         ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  0)
185 #endif /* !CONFIG_XEN_COMPAT_030002 */
186         ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad,  startup_64)
187         ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad,  hypercall_page)
188         ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel")
189         ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz, "generic")