Xen源代码分析(三)——x86_32.s
X86_32.s文件,启动汇编程序的最后阶段,主要工作为装入堆栈指针, Xen会在栈顶分配一个cpu_info结构,这个结构包含很多重要的成员:1)客户系统的切换上下文2)当前运行的vcpu指针3)物理处理器编号.
1,IDT的处理,整个idt_table的向量入口都初始化ignore_int,这个中断处理函数打印"Unknown interrupt(cr2=XXXXXXXX)"信息后系统进入循环
2,如果是BSP,跳转到__start_xen否则,跳转到start_secondary
1 .code32 2 3 /* Enable full CR4 features. */ 4 mov mmu_cr4_features,%eax 5 mov %eax,%cr4 6 7 /* Initialise stack. */ 8 /*在栈顶分配一个cpu_info结构(参见下图),这个结构包含很多重要的成员: 9 1)客户系统的切换上下文2)当前运行的vcpu指针3)物理处理器编号*/ 10 mov stack_start,%esp 11 or $(STACK_SIZE-CPUINFO_sizeof),%esp 12 13 /* Reset EFLAGS (subsumes CLI and CLD). */ 14 pushl $0 15 popf 16 17 lidt idt_descr/*加载中断描述符表*/ 18 19 test %ebx,%ebx 20 jnz start_secondary 21 22 /* Initialise IDT with simple error defaults. */ 23 lea ignore_int,%edx 24 mov $(__HYPERVISOR_CS << 16),%eax 25 mov %dx,%ax /* selector = 0x0010 = cs */ 26 mov $0x8E00,%dx /* interrupt gate - dpl=0, present */ 27 lea idt_table,%edi 28 mov $256,%ecx 29 1: mov %eax,(%edi) 30 mov %edx,4(%edi) 31 add $8,%edi 32 loop 1b 33 34 /* Pass off the Multiboot info structure to C land. */ 35 pushl multiboot_ptr 36 call __start_xen/*调用该函数正式调入C代码初始化中*/ 37 ud2 /* Force a panic (invalid opcode). */ 38 39 /* This is the default interrupt handler. */ 40 int_msg: 41 .asciz "Unknown interrupt (cr2=%08x)\n" 42 hex_msg: 43 .asciz " %08x" 44 ALIGN 45 ignore_int: 46 pusha 47 cld 48 mov $(__HYPERVISOR_DS),%eax 49 mov %eax,%ds 50 mov %eax,%es 51 mov %cr2,%eax 52 push %eax 53 pushl $int_msg 54 call printk 55 add $8,%esp 56 mov %esp,%ebp 57 0: pushl (%ebp) 58 add $4,%ebp 59 pushl $hex_msg 60 call printk 61 add $8,%esp 62 test $0xffc,%ebp 63 jnz 0b 64 1: jmp 1b 65 66 .data 67 ALIGN 68 ENTRY(stack_start) 69 .long cpu0_stack 70 71 /*** DESCRIPTOR TABLES ***/ 72 73 ALIGN 74 multiboot_ptr: 75 .long 0 76 77 .word 0 78 idt_descr: 79 .word 256*8-1 80 .long idt_table 81 82 .word 0 83 gdt_descr:/*在第二阶段装载了*/ 84 .word LAST_RESERVED_GDT_BYTE 85 .long boot_cpu_gdt_table - FIRST_RESERVED_GDT_BYTE 86 87 88 .align 32 89 ENTRY(idle_pg_table) 90 .long sym_phys(idle_pg_table_l2) + 0*PAGE_SIZE + 0x01, 0 91 .long sym_phys(idle_pg_table_l2) + 1*PAGE_SIZE + 0x01, 0 92 .long sym_phys(idle_pg_table_l2) + 2*PAGE_SIZE + 0x01, 0 93 .long sym_phys(idle_pg_table_l2) + 3*PAGE_SIZE + 0x01, 0 94 95 .section .data.page_aligned, "aw", @progbits 96 .align PAGE_SIZE, 0 97 /* NB. Rings != 0 get access up to MACH2PHYS_VIRT_END. This allows access to */ 98 /* the machine->physical mapping table. Ring 0 can access all memory. */ 99 #define GUEST_DESC(d) \ 100 .long ((MACH2PHYS_VIRT_END - 1) >> 12) & 0xffff, \ 101 ((MACH2PHYS_VIRT_END - 1) >> 12) & (0xf << 16) | (d) 102 ENTRY(boot_cpu_gdt_table) 103 .quad 0x0000000000000000 /* double fault TSS */ 104 .quad 0x00cf9a000000ffff /* 0xe008 ring 0 4.00GB code at 0x0 */ 105 .quad 0x00cf92000000ffff /* 0xe010 ring 0 4.00GB data at 0x0 */ 106 GUEST_DESC(0x00c0ba00) /* 0xe019 ring 1 3.xxGB code at 0x0 */ 107 GUEST_DESC(0x00c0b200) /* 0xe021 ring 1 3.xxGB data at 0x0 */ 108 GUEST_DESC(0x00c0fa00) /* 0xe02b ring 3 3.xxGB code at 0x0 */ 109 GUEST_DESC(0x00c0f200) /* 0xe033 ring 3 3.xxGB data at 0x0 */ 110 .fill (PER_CPU_GDT_ENTRY - FLAT_RING3_DS / 8 - 1), 8, 0 111 .quad 0x0000910000000000 /* per-CPU entry (limit == cpu) */ 112 .align PAGE_SIZE,0