ia64/xen-unstable

view xen/arch/x86/boot/trampoline.S @ 16223:0f86492f1a8c

x86: GDTR must be reset after using real-mode BIOS services. Some
BIOSes clobber GDTR. While we're here reset IDTR too, although it's
not really necessary.
Signed-off-by: John Byrne <john.l.byrne@hp.com>
Sigend-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Thu Oct 25 09:43:42 2007 +0100 (2007-10-25)
parents 118a21c66fd5
children 207ad1afe9bb
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 /* Stack grows down from +0x3000. Initialise IDT and enable irqs. */
154 mov $0x3000,%sp
155 lidt bootsym(rm_idt)
156 sti
158 /*
159 * Do real-mode work:
160 * 1. Get memory map.
161 * 2. Get Enhanced Disk Drive (EDD) information.
162 * 3. Set video mode.
163 */
164 call get_memory_map
165 call get_edd
166 call video
168 /* Disable irqs before returning to protected mode. */
169 cli
171 /* Reset GDT and IDT. Some BIOSes clobber GDTR. */
172 lidt bootsym(idt_48)
173 lgdt bootsym(gdt_48)
175 /* Enter protected mode, and flush insn queue. */
176 xor %ax,%ax
177 inc %ax
178 lmsw %ax # CR0.PE = 1 (enter protected mode)
180 /* Load proper protected-mode values into all segment registers. */
181 ljmpl $BOOT_CS32,$bootsym_phys(1f)
182 .code32
183 1: mov $BOOT_DS,%eax
184 mov %eax,%ds
185 mov %eax,%es
186 mov %eax,%fs
187 mov %eax,%gs
188 mov %eax,%ss
190 .Lskip_realmode:
191 /* EBX == 0 indicates we are the BP (Boot Processor). */
192 xor %ebx,%ebx
194 /* Jump to the common bootstrap entry point. */
195 jmp trampoline_protmode_entry
197 skip_realmode:
198 .byte 0
200 rm_idt: .word 256*4-1, 0, 0
202 #include "mem.S"
203 #include "edd.S"
204 #include "video.S"