fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / i386 / kernel / head-xen.S
1
2
3 .text
4 #include <linux/elfnote.h>
5 #include <linux/threads.h>
6 #include <linux/linkage.h>
7 #include <asm/segment.h>
8 #include <asm/page.h>
9 #include <asm/boot.h>
10 #include <asm/thread_info.h>
11 #include <asm/asm-offsets.h>
12 #include <xen/interface/xen.h>
13 #include <xen/interface/elfnote.h>
14
15 /*
16  * References to members of the new_cpu_data structure.
17  */
18
19 #define X86             new_cpu_data+CPUINFO_x86
20 #define X86_VENDOR      new_cpu_data+CPUINFO_x86_vendor
21 #define X86_MODEL       new_cpu_data+CPUINFO_x86_model
22 #define X86_MASK        new_cpu_data+CPUINFO_x86_mask
23 #define X86_HARD_MATH   new_cpu_data+CPUINFO_hard_math
24 #define X86_CPUID       new_cpu_data+CPUINFO_cpuid_level
25 #define X86_CAPABILITY  new_cpu_data+CPUINFO_x86_capability
26 #define X86_VENDOR_ID   new_cpu_data+CPUINFO_x86_vendor_id
27
28 #define VIRT_ENTRY_OFFSET 0x0
29 .org VIRT_ENTRY_OFFSET
30 ENTRY(startup_32)
31
32 #ifdef CONFIG_PARAVIRT
33         movl %cs, %eax
34         testl $0x3, %eax
35         jnz startup_paravirt
36 #endif
37
38         movl %esi,xen_start_info
39         cld
40
41         call setup_pda
42
43         /* Set up the stack pointer */
44         movl $(init_thread_union+THREAD_SIZE),%esp
45
46         /* get vendor info */
47         xorl %eax,%eax                  # call CPUID with 0 -> return vendor ID
48         XEN_CPUID
49         movl %eax,X86_CPUID             # save CPUID level
50         movl %ebx,X86_VENDOR_ID         # lo 4 chars
51         movl %edx,X86_VENDOR_ID+4       # next 4 chars
52         movl %ecx,X86_VENDOR_ID+8       # last 4 chars
53
54         movl $1,%eax            # Use the CPUID instruction to get CPU type
55         XEN_CPUID
56         movb %al,%cl            # save reg for future use
57         andb $0x0f,%ah          # mask processor family
58         movb %ah,X86
59         andb $0xf0,%al          # mask model
60         shrb $4,%al
61         movb %al,X86_MODEL
62         andb $0x0f,%cl          # mask mask revision
63         movb %cl,X86_MASK
64         movl %edx,X86_CAPABILITY
65
66         movb $1,X86_HARD_MATH
67
68         xorl %eax,%eax                  # Clear FS and LDT
69         movl %eax,%fs
70
71         movl $(__KERNEL_PDA),%eax
72         mov  %eax,%gs
73
74         cld                     # gcc2 wants the direction flag cleared at all times
75
76         call start_kernel
77 L6:
78         jmp L6                  # main should never return here, but
79                                 # just in case, we know what happens.
80
81 /*
82  * Point the GDT at this CPU's PDA.  This will be
83  * cpu_gdt_table and boot_pda.
84  */
85 setup_pda:
86         /* get the PDA pointer */
87         movl $boot_pda, %eax
88
89         /* slot the PDA address into the GDT */
90         mov $cpu_gdt_table, %ecx
91         mov %ax, (__KERNEL_PDA+0+2)(%ecx)               /* base & 0x0000ffff */
92         shr $16, %eax
93         mov %al, (__KERNEL_PDA+4+0)(%ecx)               /* base & 0x00ff0000 */
94         mov %ah, (__KERNEL_PDA+4+3)(%ecx)               /* base & 0xff000000 */
95
96         # %esi still points to start_info, and no registers
97         # need to be preserved.
98
99         movl XEN_START_mfn_list(%esi), %ebx
100         movl $(cpu_gdt_table - __PAGE_OFFSET), %eax
101         shrl $PAGE_SHIFT, %eax
102         movl (%ebx,%eax,4), %ecx
103         pushl %ecx                      # frame number for set_gdt below
104
105         xorl %esi, %esi
106         xorl %edx, %edx
107         shldl $PAGE_SHIFT, %ecx, %edx
108         shll $PAGE_SHIFT, %ecx
109         orl $0x61, %ecx
110         movl $cpu_gdt_table, %ebx
111         movl $__HYPERVISOR_update_va_mapping, %eax
112         int $0x82
113
114         movl $(PAGE_SIZE_asm / 8), %ecx
115         movl %esp, %ebx
116         movl $__HYPERVISOR_set_gdt, %eax
117         int $0x82
118
119         popl %ecx
120         ret
121
122 #define HYPERCALL_PAGE_OFFSET 0x1000
123 .org HYPERCALL_PAGE_OFFSET
124 ENTRY(hypercall_page)
125 .skip 0x1000
126
127 /*
128  * Real beginning of normal "text" segment
129  */
130 ENTRY(stext)
131 ENTRY(_stext)
132
133 /*
134  * BSS section
135  */
136 .section ".bss.page_aligned","w"
137 ENTRY(empty_zero_page)
138         .fill 4096,1,0
139
140 /*
141  * This starts the data section.
142  */
143 .data
144 ENTRY(start_pda)
145         .long boot_pda
146
147 #ifdef CONFIG_PARAVIRT
148 startup_paravirt:
149         cld
150         movl $(init_thread_union+THREAD_SIZE),%esp
151
152         /* We take pains to preserve all the regs. */
153         pushl   %edx
154         pushl   %ecx
155         pushl   %eax
156
157         /* paravirt.o is last in link, and that probe fn never returns */
158         pushl   $__start_paravirtprobe
159 1:
160         movl    0(%esp), %eax
161         pushl   (%eax)
162         movl    8(%esp), %eax
163         call    *(%esp)
164         popl    %eax
165
166         movl    4(%esp), %eax
167         movl    8(%esp), %ecx
168         movl    12(%esp), %edx
169
170         addl    $4, (%esp)
171         jmp     1b
172 #endif
173
174 /*
175  * The Global Descriptor Table contains 28 quadwords, per-CPU.
176  */
177         .section .data.page_aligned, "aw"
178         .align PAGE_SIZE_asm
179 ENTRY(cpu_gdt_table)
180         .quad 0x0000000000000000        /* NULL descriptor */
181         .quad 0x0000000000000000        /* 0x0b reserved */
182         .quad 0x0000000000000000        /* 0x13 reserved */
183         .quad 0x0000000000000000        /* 0x1b reserved */
184         .quad 0x0000000000000000        /* 0x20 unused */
185         .quad 0x0000000000000000        /* 0x28 unused */
186         .quad 0x0000000000000000        /* 0x33 TLS entry 1 */
187         .quad 0x0000000000000000        /* 0x3b TLS entry 2 */
188         .quad 0x0000000000000000        /* 0x43 TLS entry 3 */
189         .quad 0x0000000000000000        /* 0x4b reserved */
190         .quad 0x0000000000000000        /* 0x53 reserved */
191         .quad 0x0000000000000000        /* 0x5b reserved */
192
193         .quad 0x00cf9a000000ffff        /* 0x60 kernel 4GB code at 0x00000000 */
194         .quad 0x00cf92000000ffff        /* 0x68 kernel 4GB data at 0x00000000 */
195         .quad 0x00cffa000000ffff        /* 0x73 user 4GB code at 0x00000000 */
196         .quad 0x00cff2000000ffff        /* 0x7b user 4GB data at 0x00000000 */
197
198         .quad 0x0000000000000000        /* 0x80 TSS descriptor */
199         .quad 0x0000000000000000        /* 0x88 LDT descriptor */
200
201         /*
202          * Segments used for calling PnP BIOS have byte granularity.
203          * They code segments and data segments have fixed 64k limits,
204          * the transfer segment sizes are set at run time.
205          */
206         .quad 0x0000000000000000        /* 0x90 32-bit code */
207         .quad 0x0000000000000000        /* 0x98 16-bit code */
208         .quad 0x0000000000000000        /* 0xa0 16-bit data */
209         .quad 0x0000000000000000        /* 0xa8 16-bit data */
210         .quad 0x0000000000000000        /* 0xb0 16-bit data */
211
212         /*
213          * The APM segments have byte granularity and their bases
214          * are set at run time.  All have 64k limits.
215          */
216         .quad 0x0000000000000000        /* 0xb8 APM CS    code */
217         .quad 0x0000000000000000        /* 0xc0 APM CS 16 code (16 bit) */
218         .quad 0x0000000000000000        /* 0xc8 APM DS    data */
219
220         .quad 0x0000000000000000        /* 0xd0 - ESPFIX SS */
221         .quad 0x00cf92000000ffff        /* 0xd8 - PDA */
222         .quad 0x0000000000000000        /* 0xe0 - unused */
223         .quad 0x0000000000000000        /* 0xe8 - unused */
224         .quad 0x0000000000000000        /* 0xf0 - unused */
225         .quad 0x0000000000000000        /* 0xf8 - GDT entry 31: double-fault TSS */
226         .align PAGE_SIZE_asm
227
228 #ifdef CONFIG_XEN_COMPAT_030002
229 /*
230  * __xen_guest information
231  */
232 .macro utoa value
233  .if (\value) < 0 || (\value) >= 0x10
234         utoa (((\value)>>4)&0x0fffffff)
235  .endif
236  .if ((\value) & 0xf) < 10
237   .byte '0' + ((\value) & 0xf)
238  .else
239   .byte 'A' + ((\value) & 0xf) - 10
240  .endif
241 .endm
242
243 .section __xen_guest
244         .ascii  "GUEST_OS=linux,GUEST_VER=2.6"
245         .ascii  ",XEN_VER=xen-3.0"
246         .ascii  ",VIRT_BASE=0x"
247                 utoa __PAGE_OFFSET
248         .ascii  ",ELF_PADDR_OFFSET=0x"
249                 utoa __PAGE_OFFSET
250         .ascii  ",VIRT_ENTRY=0x"
251                 utoa (__PAGE_OFFSET + LOAD_PHYSICAL_ADDR + VIRT_ENTRY_OFFSET)
252         .ascii  ",HYPERCALL_PAGE=0x"
253                 utoa ((LOAD_PHYSICAL_ADDR+HYPERCALL_PAGE_OFFSET)>>PAGE_SHIFT)
254         .ascii  ",FEATURES=writable_page_tables"
255         .ascii           "|writable_descriptor_tables"
256         .ascii           "|auto_translated_physmap"
257         .ascii           "|pae_pgdir_above_4gb"
258         .ascii           "|supervisor_mode_kernel"
259 #ifdef CONFIG_X86_PAE
260         .ascii  ",PAE=yes[extended-cr3]"
261 #else
262         .ascii  ",PAE=no"
263 #endif
264         .ascii  ",LOADER=generic"
265         .byte   0
266 #endif /* CONFIG_XEN_COMPAT_030002 */
267
268
269         ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")       
270         ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
271         ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
272         ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long,  __PAGE_OFFSET)
273 #ifdef CONFIG_XEN_COMPAT_030002
274         ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  __PAGE_OFFSET)
275 #else
276         ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  0)
277 #endif /* !CONFIG_XEN_COMPAT_030002 */
278         ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .long,  startup_32)
279         ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long,  hypercall_page)
280         ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel")
281 #ifdef CONFIG_X86_PAE
282         ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz, "yes")
283 #else
284         ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz, "no")
285 #endif
286         ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz, "generic")