汇编文件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"