ia64/xen-unstable

view xen/arch/x86/boot/trampoline.S @ 17065:55ae3b66b1b6

x86/64: Make BIOS call to declare our intention to enter long mode.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 14 11:24:49 2008 +0000 (2008-02-14)
parents 207ad1afe9bb
children ffcc213f8711
line source
1 .code16
3 /* NB. bootsym() is only usable in real mode, or via BOOT_PSEUDORM_DS. */
4 #undef bootsym
5 #define bootsym(s) ((s)-trampoline_start)
7 .globl trampoline_realmode_entry
8 trampoline_realmode_entry:
9 mov %cs,%ax
10 mov %ax,%ds
11 movb $0xA5,bootsym(trampoline_cpu_started)
12 cld
13 cli
14 lidt bootsym(idt_48)
15 lgdt bootsym(gdt_48)
16 mov $1,%bl # EBX != 0 indicates we are an AP
17 xor %ax, %ax
18 inc %ax
19 lmsw %ax # CR0.PE = 1 (enter protected mode)
20 ljmpl $BOOT_CS32,$bootsym_phys(trampoline_protmode_entry)
22 idt_48: .word 0, 0, 0 # base = limit = 0
23 gdt_48: .word 6*8-1
24 .long bootsym_phys(trampoline_gdt)
25 trampoline_gdt:
26 /* 0x0000: unused */
27 .quad 0x0000000000000000
28 /* 0x0008: ring 0 code, 32-bit mode */
29 .quad 0x00cf9a000000ffff
30 /* 0x0010: ring 0 code, 64-bit mode */
31 .quad 0x00af9a000000ffff
32 /* 0x0018: ring 0 data */
33 .quad 0x00cf92000000ffff
34 /* 0x0020: real-mode code @ BOOT_TRAMPOLINE */
35 .long 0x0000ffff | ((BOOT_TRAMPOLINE & 0x00ffff) << 16)
36 .long 0x00009a00 | ((BOOT_TRAMPOLINE & 0xff0000) >> 16)
37 /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
38 .long 0x0000ffff | ((BOOT_TRAMPOLINE & 0x00ffff) << 16)
39 .long 0x00009200 | ((BOOT_TRAMPOLINE & 0xff0000) >> 16)
41 cpuid_ext_features:
42 .long 0
44 .globl trampoline_xen_phys_start
45 trampoline_xen_phys_start:
46 .long 0
48 .globl trampoline_cpu_started
49 trampoline_cpu_started:
50 .byte 0
52 .code32
53 trampoline_protmode_entry:
54 /* Set up a few descriptors: on entry only CS is guaranteed good. */
55 mov $BOOT_DS,%eax
56 mov %eax,%ds
57 mov %eax,%es
59 /* Set up FPU. */
60 fninit
62 /* Initialise CR4. */
63 #if CONFIG_PAGING_LEVELS == 2
64 mov $X86_CR4_PSE,%ecx
65 #else
66 mov $X86_CR4_PAE,%ecx
67 #endif
68 mov %ecx,%cr4
70 /* Load pagetable base register. */
71 mov $sym_phys(idle_pg_table),%eax
72 add bootsym_phys(trampoline_xen_phys_start),%eax
73 mov %eax,%cr3
75 #if CONFIG_PAGING_LEVELS != 2
76 /* Set up EFER (Extended Feature Enable Register). */
77 mov bootsym_phys(cpuid_ext_features),%edi
78 test $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */
79 jz .Lskip_efer
80 movl $MSR_EFER,%ecx
81 rdmsr
82 #if CONFIG_PAGING_LEVELS == 4
83 btsl $_EFER_LME,%eax /* Long Mode */
84 btsl $_EFER_SCE,%eax /* SYSCALL/SYSRET */
85 #endif
86 btl $20,%edi /* No Execute? */
87 jnc 1f
88 btsl $_EFER_NX,%eax /* No Execute */
89 1: wrmsr
90 .Lskip_efer:
91 #endif
93 mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
94 mov %eax,%cr0
95 jmp 1f
96 1:
98 #if defined(__x86_64__)
100 /* Now in compatibility mode. Long-jump into 64-bit mode. */
101 ljmp $BOOT_CS64,$bootsym_phys(start64)
103 .code64
104 start64:
105 /* Jump to high mappings. */
106 mov high_start(%rip),%rax
107 jmpq *%rax
109 high_start:
110 .quad __high_start
112 #else /* !defined(__x86_64__) */
114 /* Install relocated selectors. */
115 lgdt gdt_descr
116 mov $(__HYPERVISOR_DS),%eax
117 mov %eax,%ds
118 mov %eax,%es
119 mov %eax,%fs
120 mov %eax,%gs
121 mov %eax,%ss
122 ljmp $(__HYPERVISOR_CS),$__high_start
124 #endif
126 .code32
127 trampoline_boot_cpu_entry:
128 cmpb $0,bootsym_phys(skip_realmode)
129 jnz .Lskip_realmode
131 /* Load pseudo-real-mode segments. */
132 mov $BOOT_PSEUDORM_DS,%eax
133 mov %eax,%ds
134 mov %eax,%es
135 mov %eax,%fs
136 mov %eax,%gs
137 mov %eax,%ss
139 /* Switch to pseudo-rm CS, enter real mode, and flush insn queue. */
140 mov %cr0,%eax
141 dec %eax
142 ljmp $BOOT_PSEUDORM_CS,$bootsym(1f)
143 .code16
144 1: mov %eax,%cr0 # CR0.PE = 0 (leave protected mode)
146 /* Load proper real-mode values into %cs, %ds, %es and %ss. */
147 ljmp $(BOOT_TRAMPOLINE>>4),$bootsym(1f)
148 1: mov $(BOOT_TRAMPOLINE>>4),%ax
149 mov %ax,%ds
150 mov %ax,%es
151 mov %ax,%ss
153 /* Initialise stack pointer and IDT, and enable irqs. */
154 mov $bootsym(early_stack),%sp
155 lidt bootsym(rm_idt)
156 sti
158 #if defined(__x86_64__)
159 /* Declare that our target operating mode is long mode. */
160 movw $0xec00,%ax # declare target operating mode
161 movw $0x0002,%bx # long mode
162 int $0x15
163 #endif
165 /*
166 * Do real-mode work:
167 * 1. Get memory map.
168 * 2. Get Enhanced Disk Drive (EDD) information.
169 * 3. Set video mode.
170 */
171 call get_memory_map
172 call get_edd
173 call video
175 /* Disable irqs before returning to protected mode. */
176 cli
178 /* Reset GDT and IDT. Some BIOSes clobber GDTR. */
179 lidt bootsym(idt_48)
180 lgdt bootsym(gdt_48)
182 /* Enter protected mode, and flush insn queue. */
183 xor %ax,%ax
184 inc %ax
185 lmsw %ax # CR0.PE = 1 (enter protected mode)
187 /* Load proper protected-mode values into all segment registers. */
188 ljmpl $BOOT_CS32,$bootsym_phys(1f)
189 .code32
190 1: mov $BOOT_DS,%eax
191 mov %eax,%ds
192 mov %eax,%es
193 mov %eax,%fs
194 mov %eax,%gs
195 mov %eax,%ss
197 .Lskip_realmode:
198 /* EBX == 0 indicates we are the BP (Boot Processor). */
199 xor %ebx,%ebx
201 /* Jump to the common bootstrap entry point. */
202 jmp trampoline_protmode_entry
204 skip_realmode:
205 .byte 0
207 rm_idt: .word 256*4-1, 0, 0
209 #include "mem.S"
210 #include "edd.S"
211 #include "video.S"
212 #include "wakeup.S"
214 .align 16
215 .fill PAGE_SIZE,1,0
216 early_stack: