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