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