X86_32.s文件,32位下启动汇编程序的最后阶段,主要工作为装入堆栈指针, Xen会在栈顶分配一个cpu_info结构,这个结构包含很多重要的成员:1)客户系统的切换上下文2)当前运行的vcpu指针3)物理处理器编号1,IDT的处理,整个idt_table的向量入口都初始化ignore_int,这个中断处理函数打印"Unknown interrupt(cr2=XXXXXXXX)"信息后系统进入循环2,如果是BSP,跳转到__start_xen否则,跳转到start_secondary
.code32
/* Enable full CR4 features. */
mov mmu_cr4_features,%eax
mov %eax,%cr4
/* Initialise stack. */
/*在栈顶分配一个cpu_info结构(参见下图),这个结构包含很多重要的成员:
1)客户系统的切换上下文2)当前运行的vcpu指针3)物理处理器编号*/
mov stack_start,%esp
or $(STACK_SIZE-CPUINFO_sizeof),%esp
/* Reset EFLAGS (subsumes CLI and CLD). */
pushl $0
popf
lidt idt_descr/*加载中断描述符表*/
test %ebx,%ebx
jnz start_secondary
/* Initialise IDT with simple error defaults. */
lea ignore_int,%edx
mov $(__HYPERVISOR_CS << 16),%eax
mov %dx,%ax /* selector = 0x0010 = cs */
mov $0x8E00,%dx /* interrupt gate - dpl=0, present */
lea idt_table,%edi
mov $256,%ecx
1: mov %eax,(%edi)
mov %edx,4(%edi)
add $8,%edi
loop 1b
/* Pass off the Multiboot info structure to C land. */
pushl multiboot_ptr
call __start_xen/*调用该函数正式调入C代码初始化中*/
ud2 /* Force a panic (invalid opcode). */
/* This is the default interrupt handler. */
int_msg:
.asciz "Unknown interrupt (cr2=%08x)\n"
hex_msg:
.asciz " %08x"
ALIGN
ignore_int:
pusha
cld
mov $(__HYPERVISOR_DS),%eax
mov %eax,%ds
mov %eax,%es
mov %cr2,%eax
push %eax
pushl $int_msg
call printk
add $8,%esp
mov %esp,%ebp
0: pushl (%ebp)
add $4,%ebp
pushl $hex_msg
call printk
add $8,%esp
test $0xffc,%ebp
jnz 0b
1: jmp 1b
.data
ALIGN
ENTRY(stack_start)
.long cpu0_stack
/*** DESCRIPTOR TABLES ***/
ALIGN
multiboot_ptr:
.long 0
.word 0
idt_descr:
.word 256*8-1
.long idt_table
.word 0
gdt_descr:/*在第二阶段装载了*/
.word LAST_RESERVED_GDT_BYTE
.long boot_cpu_gdt_table - FIRST_RESERVED_GDT_BYTE
.align 32
ENTRY(idle_pg_table)
.long sym_phys(idle_pg_table_l2) + 0*PAGE_SIZE + 0x01, 0
.long sym_phys(idle_pg_table_l2) + 1*PAGE_SIZE + 0x01, 0
.long sym_phys(idle_pg_table_l2) + 2*PAGE_SIZE + 0x01, 0
.long sym_phys(idle_pg_table_l2) + 3*PAGE_SIZE + 0x01, 0
.section .data.page_aligned, "aw", @progbits
.align PAGE_SIZE, 0
/* NB. Rings != 0 get access up to MACH2PHYS_VIRT_END. This allows access to */
/* the machine->physical mapping table. Ring 0 can access all memory. */
#define GUEST_DESC(d) \
.long ((MACH2PHYS_VIRT_END - 1) >> 12) & 0xffff, \
((MACH2PHYS_VIRT_END - 1) >> 12) & (0xf << 16) | (d)
ENTRY(boot_cpu_gdt_table)
.quad 0x0000000000000000 /* double fault TSS */
.quad 0x00cf9a000000ffff /* 0xe008 ring 0 4.00GB code at 0x0 */
.quad 0x00cf92000000ffff /* 0xe010 ring 0 4.00GB data at 0x0 */
GUEST_DESC(0x00c0ba00) /* 0xe019 ring 1 3.xxGB code at 0x0 */
GUEST_DESC(0x00c0b200) /* 0xe021 ring 1 3.xxGB data at 0x0 */
GUEST_DESC(0x00c0fa00) /* 0xe02b ring 3 3.xxGB code at 0x0 */
GUEST_DESC(0x00c0f200) /* 0xe033 ring 3 3.xxGB data at 0x0 */
.fill (PER_CPU_GDT_ENTRY - FLAT_RING3_DS / 8 - 1), 8, 0
.quad 0x0000910000000000 /* per-CPU entry (limit == cpu) */
.align PAGE_SIZE,0