direct-io.hg

view xen/arch/x86/boot/x86_32.S @ 12764:1c15f97a220d

[XEN] Make multiboot-related code more readable.
Tested on i386 and x86_64 with GRUB and PXELINUX bootmanagers.

From: Christoph Egger <Christoph.Egger@amd.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Dec 07 11:22:26 2006 +0000 (2006-12-07)
parents 02899109a3ac
children 60f91c9f1a24
line source
1 #include <xen/config.h>
2 #include <xen/multiboot.h>
3 #include <public/xen.h>
4 #include <asm/asm_defns.h>
5 #include <asm/desc.h>
6 #include <asm/page.h>
7 #include <asm/msr.h>
9 #define SECONDARY_CPU_FLAG 0xA5A5A5A5
11 .text
13 ENTRY(start)
14 ENTRY(stext)
15 ENTRY(_stext)
16 jmp __start
18 .align 4
20 /*** MULTIBOOT HEADER ****/
21 #define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_MODS_ALIGNED | \
22 MULTIBOOT_HEADER_WANT_MEMORY)
23 /* Magic number indicating a Multiboot header. */
24 .long MULTIBOOT_HEADER_MAGIC
25 /* Flags to bootloader (see Multiboot spec). */
26 .long MULTIBOOT_HEADER_FLAGS
27 /* Checksum: must be the negated sum of the first two fields. */
28 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
30 not_multiboot_msg:
31 .asciz "ERR: Not a Multiboot bootloader!"
32 not_multiboot:
33 mov $not_multiboot_msg-__PAGE_OFFSET,%esi
34 mov $0xB8000,%edi # VGA framebuffer
35 1: mov (%esi),%bl
36 test %bl,%bl # Terminate on '\0' sentinel
37 2: je 2b
38 mov $0x3f8+5,%dx # UART Line Status Register
39 3: in %dx,%al
40 test $0x20,%al # Test THR Empty flag
41 je 3b
42 mov $0x3f8+0,%dx # UART Transmit Holding Register
43 mov %bl,%al
44 out %al,%dx # Send a character over the serial line
45 movsb # Write a character to the VGA framebuffer
46 mov $7,%al
47 stosb # Write an attribute to the VGA framebuffer
48 jmp 1b
50 __start:
51 /* Set up a few descriptors: on entry only CS is guaranteed good. */
52 lgdt %cs:nopaging_gdt_descr-__PAGE_OFFSET
53 mov $(__HYPERVISOR_DS),%ecx
54 mov %ecx,%ds
55 mov %ecx,%es
56 mov %ecx,%fs
57 mov %ecx,%gs
58 ljmp $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET
59 1: lss stack_start-__PAGE_OFFSET,%esp
60 add $(STACK_SIZE-CPUINFO_sizeof-__PAGE_OFFSET),%esp
62 /* Reset EFLAGS (subsumes CLI and CLD). */
63 pushl $0
64 popf
66 /* Set up FPU. */
67 fninit
69 /* Set up CR4, except global flag which Intel requires should be */
70 /* left until after paging is enabled (IA32 Manual Vol. 3, Sec. 2.5) */
71 mov mmu_cr4_features-__PAGE_OFFSET,%ecx
72 and $0x7f,%cl # CR4.PGE (global enable)
73 mov %ecx,%cr4
75 cmp $(SECONDARY_CPU_FLAG),%ebx
76 je start_paging
78 /* Check for Multiboot bootloader */
79 cmp $0x2BADB002,%eax
80 jne not_multiboot
82 /* Initialize BSS (no nasty surprises!) */
83 mov $__bss_start-__PAGE_OFFSET,%edi
84 mov $_end-__PAGE_OFFSET,%ecx
85 sub %edi,%ecx
86 xor %eax,%eax
87 rep stosb
89 /* Save the Multiboot info structure for later use. */
90 add $__PAGE_OFFSET,%ebx
91 push %ebx
93 #ifdef CONFIG_X86_PAE
94 /* Initialize low and high mappings of all memory with 2MB pages */
95 mov $idle_pg_table_l2-__PAGE_OFFSET,%edi
96 mov $0xe3,%eax /* PRESENT+RW+A+D+2MB */
97 1: mov %eax,__PAGE_OFFSET>>18(%edi) /* high mapping */
98 stosl /* low mapping */
99 add $4,%edi
100 add $(1<<L2_PAGETABLE_SHIFT),%eax
101 cmp $DIRECTMAP_PHYS_END+0xe3,%eax
102 jne 1b
103 1: stosl /* low mappings cover as much physmem as possible */
104 add $4,%edi
105 add $(1<<L2_PAGETABLE_SHIFT),%eax
106 cmp $HYPERVISOR_VIRT_START+0xe3,%eax
107 jne 1b
108 #else
109 /* Initialize low and high mappings of all memory with 4MB pages */
110 mov $idle_pg_table-__PAGE_OFFSET,%edi
111 mov $0xe3,%eax /* PRESENT+RW+A+D+4MB */
112 1: mov %eax,__PAGE_OFFSET>>20(%edi) /* high mapping */
113 stosl /* low mapping */
114 add $(1<<L2_PAGETABLE_SHIFT),%eax
115 cmp $DIRECTMAP_PHYS_END+0xe3,%eax
116 jne 1b
117 1: stosl /* low mappings cover as much physmem as possible */
118 add $(1<<L2_PAGETABLE_SHIFT),%eax
119 cmp $HYPERVISOR_VIRT_START+0xe3,%eax
120 jne 1b
121 #endif
123 /* Initialise IDT with simple error defaults. */
124 lea ignore_int,%edx
125 mov $(__HYPERVISOR_CS << 16),%eax
126 mov %dx,%ax /* selector = 0x0010 = cs */
127 mov $0x8E00,%dx /* interrupt gate - dpl=0, present */
128 lea idt_table-__PAGE_OFFSET,%edi
129 mov $256,%ecx
130 1: mov %eax,(%edi)
131 mov %edx,4(%edi)
132 add $8,%edi
133 loop 1b
135 start_paging:
136 #ifdef CONFIG_X86_PAE
137 /* Enable Execute-Disable (NX/XD) support if it is available. */
138 push %ebx
139 mov $0x80000000,%eax
140 cpuid
141 cmp $0x80000000,%eax /* Any function > 0x80000000? */
142 jbe no_execute_disable
143 mov $0x80000001,%eax
144 cpuid
145 bt $20,%edx /* Execute Disable? */
146 jnc no_execute_disable
147 movl $MSR_EFER,%ecx
148 rdmsr
149 bts $_EFER_NX,%eax
150 wrmsr
151 no_execute_disable:
152 pop %ebx
153 #endif
154 mov $idle_pg_table-__PAGE_OFFSET,%eax
155 mov %eax,%cr3
156 mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
157 mov %eax,%cr0
158 jmp 1f
159 1: /* Install relocated selectors (FS/GS unused). */
160 lgdt gdt_descr
161 mov $(__HYPERVISOR_DS),%ecx
162 mov %ecx,%ds
163 mov %ecx,%es
164 mov %ecx,%ss
165 ljmp $(__HYPERVISOR_CS),$1f
166 1: /* Paging enabled, so we can now enable GLOBAL mappings in CR4. */
167 mov mmu_cr4_features,%ecx
168 mov %ecx,%cr4
169 /* Relocate ESP */
170 add $__PAGE_OFFSET,%esp
172 lidt idt_descr
174 cmp $(SECONDARY_CPU_FLAG),%ebx
175 je start_secondary
177 /* Call into main C routine. This should never return.*/
178 call __start_xen
179 ud2 /* Force a panic (invalid opcode). */
181 /* This is the default interrupt handler. */
182 int_msg:
183 .asciz "Unknown interrupt\n"
184 ALIGN
185 ignore_int:
186 cld
187 mov $(__HYPERVISOR_DS),%eax
188 mov %eax,%ds
189 mov %eax,%es
190 pushl $int_msg
191 call printk
192 1: jmp 1b
194 /*** STACK LOCATION ***/
196 ENTRY(stack_start)
197 .long cpu0_stack
198 .long __HYPERVISOR_DS
200 /*** DESCRIPTOR TABLES ***/
202 ALIGN
204 .word 0
205 idt_descr:
206 .word 256*8-1
207 .long idt_table
209 .word 0
210 gdt_descr:
211 .word LAST_RESERVED_GDT_BYTE
212 .long gdt_table - FIRST_RESERVED_GDT_BYTE
214 .word 0
215 nopaging_gdt_descr:
216 .word LAST_RESERVED_GDT_BYTE
217 .long gdt_table - FIRST_RESERVED_GDT_BYTE - __PAGE_OFFSET
219 .align PAGE_SIZE, 0
220 /* NB. Rings != 0 get access up to MACH2PHYS_VIRT_END. This allows access to */
221 /* the machine->physical mapping table. Ring 0 can access all memory. */
222 #define GUEST_DESC(d) \
223 .long ((MACH2PHYS_VIRT_END - 1) >> 12) & 0xffff, \
224 ((MACH2PHYS_VIRT_END - 1) >> 12) & (0xf << 16) | (d)
225 ENTRY(gdt_table)
226 .quad 0x0000000000000000 /* unused */
227 .quad 0x00cf9a000000ffff /* 0xe008 ring 0 4.00GB code at 0x0 */
228 .quad 0x00cf92000000ffff /* 0xe010 ring 0 4.00GB data at 0x0 */
229 GUEST_DESC(0x00c0ba00) /* 0xe019 ring 1 3.xxGB code at 0x0 */
230 GUEST_DESC(0x00c0b200) /* 0xe021 ring 1 3.xxGB data at 0x0 */
231 GUEST_DESC(0x00c0fa00) /* 0xe02b ring 3 3.xxGB code at 0x0 */
232 GUEST_DESC(0x00c0f200) /* 0xe033 ring 3 3.xxGB data at 0x0 */
233 .quad 0x0000000000000000 /* unused */
234 .fill 2*NR_CPUS,8,0 /* space for TSS and LDT per CPU */
236 .align PAGE_SIZE, 0
238 #ifdef CONFIG_X86_PAE
239 ENTRY(idle_pg_table)
240 ENTRY(idle_pg_table_l3)
241 .long idle_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
242 .long idle_pg_table_l2 + 1*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
243 .long idle_pg_table_l2 + 2*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
244 .long idle_pg_table_l2 + 3*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
245 .section ".bss.page_aligned","w"
246 ENTRY(idle_pg_table_l2)
247 .fill 4*PAGE_SIZE,1,0
248 #else
249 .section ".bss.page_aligned","w"
250 ENTRY(idle_pg_table)
251 ENTRY(idle_pg_table_l2)
252 .fill 1*PAGE_SIZE,1,0
253 #endif
255 .section ".bss.stack_aligned","w"
256 ENTRY(cpu0_stack)
257 .fill STACK_SIZE,1,0