2 * linux/arch/x86_64/kernel/head.S -- start in 32bit and switch to 64bit
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>
13 #include <linux/linkage.h>
14 #include <linux/threads.h>
15 #include <linux/init.h>
16 #include <linux/elfnote.h>
18 #include <asm/segment.h>
21 #include <asm/cache.h>
22 #include <asm/dwarf2.h>
23 #include <xen/interface/elfnote.h>
25 .section .bootstrap.text, "ax", @progbits
27 #define VIRT_ENTRY_OFFSET 0x0
28 .org VIRT_ENTRY_OFFSET
32 movq $(init_thread_union+THREAD_SIZE-8),%rsp
34 /* rsi is pointer to startup info structure.
37 pushq $0 # fake return address
38 jmp x86_64_start_kernel
44 #define NEXT_PAGE(name) \
46 .org $page * 0x1000; \
47 phys_##name = $page * 0x1000 + __PHYSICAL_START; \
50 NEXT_PAGE(init_level4_pgt)
51 /* This gets initialized in x86_64_start_kernel */
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
61 NEXT_PAGE(init_level4_user_pgt)
64 NEXT_PAGE(level3_kernel_pgt)
68 * This is used for vsyscall area mapping as we have a different
69 * level4 page table for user.
71 NEXT_PAGE(level3_user_pgt)
74 NEXT_PAGE(level2_kernel_pgt)
77 NEXT_PAGE(hypercall_page)
80 .skip 1 /* push %rcx */
81 CFI_ADJUST_CFA_OFFSET 8
83 .skip 2 /* push %r11 */
84 CFI_ADJUST_CFA_OFFSET 8
86 .skip 5 /* mov $#,%eax */
88 .skip 2 /* pop %r11 */
89 CFI_ADJUST_CFA_OFFSET -8
91 .skip 1 /* pop %rcx */
92 CFI_ADJUST_CFA_OFFSET -8
94 .align 0x20,0 /* ret */
105 .word gdt_end-cpu_gdt_table-1
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
120 .section .data.page_aligned, "aw"
123 /* The TLS descriptors are currently at a different place compared to i386.
124 Hopefully nobody expects them at a fixed place (Wine?) */
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 */
137 .quad 0,0,0 /* three TLS descriptors */
138 .quad 0x0000f40000000000 /* node/CPU stored in limit */
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 */
144 /* zero the remaining page */
145 .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
147 .section .bss.page_aligned, "aw", @nobits
149 ENTRY(empty_zero_page)
152 #if CONFIG_XEN_COMPAT <= 0x030002
154 * __xen_guest information
157 .if (\value) < 0 || (\value) >= 0x10
158 utoh (((\value)>>4)&0x0fffffffffffffff)
160 .if ((\value) & 0xf) < 10
161 .byte '0' + ((\value) & 0xf)
163 .byte 'A' + ((\value) & 0xf) - 10
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"
184 #endif /* CONFIG_XEN_COMPAT <= 0x030002 */
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)
193 ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, .quad, 0)
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)