|
汇编文件trampoline.s,为启动汇编程序第二阶段,主要工作为进入实模式,读取内存,磁盘,视频信息然后再次进入保护模式装入新的GDT(gdt_table),英文注释了很大部分,很容易理解。下面的代码注释中,从标号0开始运行,然后是标号1。
1 .code16
2 /* NB. bootsym() is only usable in real mode, or via BOOT_PSEUDORM_DS. */
3 #undef bootsym
4 /*bootsym(s)定义的是s的相对位置*/
5 #define bootsym(s) ((s)-trampoline_start)
6
7 #define bootsym_rel(sym, off, opnd...) \
8 bootsym(sym),##opnd; \
9 111:; \
10 .pushsection .trampoline_rel, "a"; \
11 .long 111b - (off) - .; \
12 .popsection
13
14 #define bootsym_segrel(sym, off) \
15 $0,$bootsym(sym); \
16 111:; \
17 .pushsection .trampoline_seg, "a"; \
18 .long 111b - (off) - .; \
19 .popsection
20
21 .globl trampoline_realmode_entry
22 trampoline_realmode_entry:
23 mov %cs,%ax
24 mov %ax,%ds
25 movb $0xA5,bootsym(trampoline_cpu_started)
26 cld
27 cli
28 lidt bootsym(idt_48)
29 lgdt bootsym(gdt_48)
30 mov $1,%bl # EBX != 0 indicates we are an AP
31 xor %ax, %ax
32 inc %ax
33 lmsw %ax # CR0.PE = 1 (enter protected mode)
34 ljmpl $BOOT_CS32,$bootsym_rel(trampoline_protmode_entry,6)
35
36 idt_48: .word 0, 0, 0 # base = limit = 0
37 gdt_48: .word 6*8-1
38 .long bootsym_rel(trampoline_gdt,4)
39 trampoline_gdt:
40 /* 0x0000: unused */
41 .quad 0x0000000000000000
42 /* 0x0008: ring 0 code, 32-bit mode */
43 .quad 0x00cf9a000000ffff
44 /* 0x0010: ring 0 code, 64-bit mode */
45 .quad 0x00af9a000000ffff
46 /* 0x0018: ring 0 data */
47 .quad 0x00cf92000000ffff
48 /* 0x0020: real-mode code @ BOOT_TRAMPOLINE */
49 .long 0x0000ffff
50 .long 0x00009a00
51 /* 0x0028: real-mode data @ BOOT_TRAMPOLINE */
52 .long 0x0000ffff
53 .long 0x00009200
54
55 .pushsection .trampoline_rel, "a"
56 .long trampoline_gdt + BOOT_PSEUDORM_CS + 2 - .
57 .long trampoline_gdt + BOOT_PSEUDORM_DS + 2 - .
58 .popsection
59
60 .globl cpuid_ext_features
61 cpuid_ext_features:
62 .long 0
63
64 .globl trampoline_xen_phys_start
65 trampoline_xen_phys_start:
66 .long 0
67
68 .globl trampoline_cpu_started
69 trampoline_cpu_started:
70 .byte 0
71
72 .code32
73 /*1: 从实模式跳转到这里运行,也就是正式进入保护模式*/
74 trampoline_protmode_entry:
75 /* Set up a few descriptors: on entry only CS is guaranteed good. */
76 mov $BOOT_DS,%eax
77 mov %eax,%ds
78 mov %eax,%es
79
80 /* Set up FPU. */
81 fninit
82
83 /* Initialise CR4. */
84 mov $X86_CR4_PAE,%ecx
85 mov %ecx,%cr4
86
87 /* Load pagetable base register. */
88 mov $sym_phys(idle_pg_table),%eax
89 add bootsym_rel(trampoline_xen_phys_start,4,%eax)
90 mov %eax,%cr3
91
92 /* Set up EFER (Extended Feature Enable Register). */
93 mov bootsym_rel(cpuid_ext_features,4,%edi)
94 test $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */
95 jz .Lskip_efer
96 movl $MSR_EFER,%ecx
97 rdmsr
98 #if CONFIG_PAGING_LEVELS == 4
99 btsl $_EFER_LME,%eax /* Long Mode */
100 btsl $_EFER_SCE,%eax /* SYSCALL/SYSRET */
101 #endif
102 btl $20,%edi /* No Execute? */
103 jnc 1f
104 btsl $_EFER_NX,%eax /* No Execute */
105 1: wrmsr
106 .Lskip_efer:
107
108 mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
109 mov %eax,%cr0
110 jmp 1f
111 1:
112
113 #if defined(__x86_64__)
114
115 /* Now in compatibility mode. Long-jump into 64-bit mode. */
116 ljmp $BOOT_CS64,$bootsym_rel(start64,6)
117
118 .code64
119 start64:
120 /* Jump to high mappings. */
121 mov high_start(%rip),%rax
122 jmpq *%rax
123
124 high_start:
125 .quad __high_start
126
127 #else /* !defined(__x86_64__) */
128
129 /* Install relocated selectors. */
130 lgdt gdt_descr/*正式装载初始化后的GDT,这里装入的GDT为汇编期间最终的GDT,在x86_32.s中定义*/
131 mov $(__HYPERVISOR_DS),%eax
132 mov %eax,%ds
133 mov %eax,%es
134 mov %eax,%fs
135 mov %eax,%gs
136 mov %eax,%ss
137 /*长跳转到x86_32.s的入口__high_start,该变量在head.s中定义,为x86_32.s的入口,x86_32.s
138 在head.s中以包含的方式调用*/
139 ljmp $(__HYPERVISOR_CS),$__high_start
140
141 #endif
142
143 .code32
144 /*0: 从head.s的ret指令跳转后首先到达这里开始执行,32位代码,此时还处在保护模式下*/
145 trampoline_boot_cpu_entry:
146 cmpb $0,bootsym_rel(skip_realmode,5)
147 jnz .Lskip_realmode
148
149 /* Load pseudo-real-mode segments. */
150 mov $BOOT_PSEUDORM_DS,%eax
151 mov %eax,%ds
152 mov %eax,%es
153 mov %eax,%fs
154 mov %eax,%gs
155 mov %eax,%ss
156
157 /* Switch to pseudo-rm CS, enter real mode, and flush insn queue. */
158 mov %cr0,%eax
159 dec %eax
160 /*通过下面两个长跳转切换到实模式*/
161 ljmp $BOOT_PSEUDORM_CS,$bootsym(1f)
162 .code16
163 1: mov %eax,%cr0 # CR0.PE = 0 (leave protected mode)
164
165 /* Load proper real-mode values into %cs, %ds, %es and %ss. */
166 ljmp bootsym_segrel(1f,2)
167 1: mov %cs,%ax
168 mov %ax,%ds
169 mov %ax,%es
170 mov %ax,%ss
171
172 /* Initialise stack pointer and IDT, and enable irqs. */
173 xor %sp,%sp
174 lidt bootsym(rm_idt)/*加载IDT*/
175 sti
176
177 #if defined(__x86_64__)
178 /*
179 * Declare that our target operating mode is long mode.
180 * Initialise 32-bit registers since some buggy BIOSes depend on it.
181 */
182 movl $0xec00,%eax # declare target operating mode
183 movl $0x0002,%ebx # long mode
184 int $0x15
185 #endif
186
187 /*
188 * Do real-mode work:
189 * 1. Get memory map.
190 * 2. Get Enhanced Disk Drive (EDD) information.
191 * 3. Set video mode.
192 */
193 /*获得内存信息,该函数于mem.s中调用,内存信息存放于e820map变量中,
194 类似Linux内核的处理方式,调用0x15号中断*/
195 call get_memory_map
196 /*调用于edd.s中*/
197 call get_edd
198 /*调用于video.s中*/
199 call video
200
201 /* Disable irqs before returning to protected mode. */
202 cli
203
204 /* Reset GDT and IDT. Some BIOSes clobber GDTR. */
205 lidt bootsym(idt_48)
206 lgdt bootsym(gdt_48)
207
208 /* Enter protected mode, and flush insn queue. */
209 xor %ax,%ax
210 inc %ax
211 lmsw %ax # CR0.PE = 1 (enter protected mode)
212
213 /* Load proper protected-mode values into all segment registers. */
214 /*跳转到32位代码,为进入保护模式做准备*/
215 ljmpl $BOOT_CS32,$bootsym_rel(1f,6)
216 .code32
217 1: mov $BOOT_DS,%eax
218 mov %eax,%ds
219 mov %eax,%es
220 mov %eax,%fs
221 mov %eax,%gs
222 mov %eax,%ss
223
224 .Lskip_realmode:
225 /* EBX == 0 indicates we are the BP (Boot Processor). */
226 xor %ebx,%ebx
227
228 /* Jump to the common bootstrap entry point. */
229 jmp trampoline_protmode_entry/*跳转到保护模式入口*/
230
231 skip_realmode:
232 .byte 0
233
234 rm_idt: .word 256*4-1, 0, 0
235 /*这三部分的内容不再这里详细写了*/
236 #include "mem.S"
237 #include "edd.S"
238 #include "video.S"
239 #include "wakeup.S"
|
|