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