Xen启动过程概述
2017-04-11 20:38
387 查看
源码是xen-3.1.0
xen支持很多种平台:x86_32、x86_64、powerpc等
下面代码的分析都是基于x86_32的。虽然现在服务器绝大多数已经是64位的,但自己使用的环境是32位的,对32位平台比较熟悉。
xen内核是通过修改Linux内核实现的,只做了部分修改,启动过程与Linux很像。
首先是xen-3.1.0-src\xen\arch\x86\boot\x86_32.S
系统启动时处于实模式,在这个文件里,设置一些寄存器以及一些重要的表的值。然后进入保护模式。最后调用__start_xen()函数,这个函数位于xen-3.1.0-src\xen\arch\x86\setup.c里。
__start_xen()函数需要初始化很多东西,比如分页初始化、IRQ中断初始化、调度程序初始化。然后调用init_idle_domain()函数来初始化一个idle域,这个函数会调用domain_create()来创建domain结构体,用于管理各个domain。在创建的过程中,会将各个domain设置成paused状态(idle域除外)。
再回到__start_xen()函数里。在进行一些其他的初始化后,会调用domain_create()来创建dom0,并将dom0至于paused状态。由于domain_create()函数只创建domain管理结构体,并进行一些初始化。但仅仅是个管理结构,不具备实体。这就好比一个进程,只有一个PCB有鸟用??因此需要调用construct_dom0()来填充这个实体。这个函数会用xen内核来启动dom0。紧接着调用domain_unpause_by_systemcontroller()来unpause dom0。这样dom0就处于可调度状态了!然后调用startup_cpu_idle_loop(),这个函数会在系统没有domain可调度的时候运行。就相当于Windows的idle进程,Linux的idle循环。
这样xen内核就开始启动了.....
Xen Hypervisor运行在Ring0,在启动过程中,Xen首先被引导:系统由Grub启动,遵循Multiboot引导规范;然后Linux内核做为module也被引导入内存,同时initrd镜像文件也一样。整个引导过程如下图示:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
1 当加电后首先是BIOS自检、Grub引导。Xen遵循Multiboot引导规范,它需要从Grub读入内存信息,通过置位标志位第1位来实现的。
主要过程是从grub-xen(head.S, trampoline.S, x86_32.S,位于\xen\arch\x86\boot中:),
head.S:装入GDT(trampoline_gdt); 进入保护模式;初始化页表,将线性空间的0-12M和__PAGE_OFFSET-__PAGE_OFFSET+12M都映射到物理地址的0-12M;而将线性空间的12M-16M映射到物理地址的12M-16M;解析早期命令行参数;跳转到trampoline_boot_cpu_entry;
trampoline.S:进入实模式,读取内存,磁盘,显示信息;再次进入保护模式,装入新的GDT(gdt_table);加载前面初始化了的页表,启用分页机制,跳转到__high_start。然后就是x86_32.S文件。
2.x86_32.S是从Grub进入Xen的入口文件。Grub根据镜像头信息获得入口地址,然后读入整个镜像,最后把控制权交给Xen。
可以使用readelf命令来查看编译后生成的Xen的内核,它表明文件类型为可执行文件,并且程序的入口点是Oxl0000(原本这是Linux内核的位置),这表明Xen被引导程序放在了物理内存1M的位置上。
在x86_32.S的start入口点上,主要是为进行后续工作做准备,包括简单地设置GDT、IDT以及初始化分页等。然后start将保存着引导程序启动信息地址的EBX压栈,再调用真正的初始化流程函数。<?xml:namespace
prefix = o ns = "urn:schemas-microsoft-com:office:office" />
3.__startxen()函数中首先会从启动信息中获取物理内存分配情况,初始化E820内存图。
物理内存是只有Xen才有权限进行管理和分配的,无论是Domain0还是DomainU,它们得到的都是Xen给它们的物理内存假相。
4.之后是分页初始化、IRQ中断初始化、调度程序初始化、异常处理程序表初始化、时间设置、安全机制设置等初始化工作,并且Xen会初始化一个空闲虚拟域(Idle
Domain),当没有合适的虚拟域可以运行的时候,Xen会选择空闲虚拟域来运行,这很类似于Linux中的init进程。
5.当Xen初始化工作结束后,便开始设置Domain0的数据结构。
每个虚拟域都有一个struct domain结构体,在这里主要定义了它的ID、共享信息、内存分配、虚拟CPU、事件通道和授权表等。分配好DomainO的数据结构,Xen将通过construct_dom0()函数来将主控域的运行环境设置好。
6。然后Xen将控制权交给Domain0中的Linux,而自己进入idie_loop。主控域得到控制权后,开始自己的引导过程,只是它需要的信息是从xen_start_info数据结构中获取。进入Domain0的EIP指向_start_32,它会再跳转到start_kernel,之后的启动流程就和Linux的正常启动流程基本一样了。
启动汇编部分代码是xen 的引导启动程序,位于./xen/arch/x86/boot目录下。代码描述了从xen加载到调用第一个C函数“__start_xen”之间的初始化系统环境过程。主要涉及的文件流程为head.S->trampoline.S->x86_32.s,其中head.s为冲GRUB进入XEN的入口文件,首先看看head.s部分都做了什么(只看32位体系)。
汇编文件trampoline.s,为启动汇编程序第二阶段,主要工作为进入实模式,读取内存,磁盘,视频信息然后再次进入保护模式装入新的GDT(gdt_table),英文注释了很大部分,很容易理解。下面的代码注释中,从标号0开始运行,然后是标号1。
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
xen支持很多种平台:x86_32、x86_64、powerpc等
下面代码的分析都是基于x86_32的。虽然现在服务器绝大多数已经是64位的,但自己使用的环境是32位的,对32位平台比较熟悉。
xen内核是通过修改Linux内核实现的,只做了部分修改,启动过程与Linux很像。
首先是xen-3.1.0-src\xen\arch\x86\boot\x86_32.S
系统启动时处于实模式,在这个文件里,设置一些寄存器以及一些重要的表的值。然后进入保护模式。最后调用__start_xen()函数,这个函数位于xen-3.1.0-src\xen\arch\x86\setup.c里。
__start_xen()函数需要初始化很多东西,比如分页初始化、IRQ中断初始化、调度程序初始化。然后调用init_idle_domain()函数来初始化一个idle域,这个函数会调用domain_create()来创建domain结构体,用于管理各个domain。在创建的过程中,会将各个domain设置成paused状态(idle域除外)。
再回到__start_xen()函数里。在进行一些其他的初始化后,会调用domain_create()来创建dom0,并将dom0至于paused状态。由于domain_create()函数只创建domain管理结构体,并进行一些初始化。但仅仅是个管理结构,不具备实体。这就好比一个进程,只有一个PCB有鸟用??因此需要调用construct_dom0()来填充这个实体。这个函数会用xen内核来启动dom0。紧接着调用domain_unpause_by_systemcontroller()来unpause dom0。这样dom0就处于可调度状态了!然后调用startup_cpu_idle_loop(),这个函数会在系统没有domain可调度的时候运行。就相当于Windows的idle进程,Linux的idle循环。
这样xen内核就开始启动了.....
Xen Hypervisor运行在Ring0,在启动过程中,Xen首先被引导:系统由Grub启动,遵循Multiboot引导规范;然后Linux内核做为module也被引导入内存,同时initrd镜像文件也一样。整个引导过程如下图示:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
1 当加电后首先是BIOS自检、Grub引导。Xen遵循Multiboot引导规范,它需要从Grub读入内存信息,通过置位标志位第1位来实现的。
主要过程是从grub-xen(head.S, trampoline.S, x86_32.S,位于\xen\arch\x86\boot中:),
head.S:装入GDT(trampoline_gdt); 进入保护模式;初始化页表,将线性空间的0-12M和__PAGE_OFFSET-__PAGE_OFFSET+12M都映射到物理地址的0-12M;而将线性空间的12M-16M映射到物理地址的12M-16M;解析早期命令行参数;跳转到trampoline_boot_cpu_entry;
trampoline.S:进入实模式,读取内存,磁盘,显示信息;再次进入保护模式,装入新的GDT(gdt_table);加载前面初始化了的页表,启用分页机制,跳转到__high_start。然后就是x86_32.S文件。
2.x86_32.S是从Grub进入Xen的入口文件。Grub根据镜像头信息获得入口地址,然后读入整个镜像,最后把控制权交给Xen。
可以使用readelf命令来查看编译后生成的Xen的内核,它表明文件类型为可执行文件,并且程序的入口点是Oxl0000(原本这是Linux内核的位置),这表明Xen被引导程序放在了物理内存1M的位置上。
在x86_32.S的start入口点上,主要是为进行后续工作做准备,包括简单地设置GDT、IDT以及初始化分页等。然后start将保存着引导程序启动信息地址的EBX压栈,再调用真正的初始化流程函数。<?xml:namespace
prefix = o ns = "urn:schemas-microsoft-com:office:office" />
3.__startxen()函数中首先会从启动信息中获取物理内存分配情况,初始化E820内存图。
物理内存是只有Xen才有权限进行管理和分配的,无论是Domain0还是DomainU,它们得到的都是Xen给它们的物理内存假相。
4.之后是分页初始化、IRQ中断初始化、调度程序初始化、异常处理程序表初始化、时间设置、安全机制设置等初始化工作,并且Xen会初始化一个空闲虚拟域(Idle
Domain),当没有合适的虚拟域可以运行的时候,Xen会选择空闲虚拟域来运行,这很类似于Linux中的init进程。
5.当Xen初始化工作结束后,便开始设置Domain0的数据结构。
每个虚拟域都有一个struct domain结构体,在这里主要定义了它的ID、共享信息、内存分配、虚拟CPU、事件通道和授权表等。分配好DomainO的数据结构,Xen将通过construct_dom0()函数来将主控域的运行环境设置好。
6。然后Xen将控制权交给Domain0中的Linux,而自己进入idie_loop。主控域得到控制权后,开始自己的引导过程,只是它需要的信息是从xen_start_info数据结构中获取。进入Domain0的EIP指向_start_32,它会再跳转到start_kernel,之后的启动流程就和Linux的正常启动流程基本一样了。
Xen源代码分析(一)——head.s
启动汇编部分代码是xen 的引导启动程序,位于./xen/arch/x86/boot目录下。代码描述了从xen加载到调用第一个C函数“__start_xen”之间的初始化系统环境过程。主要涉及的文件流程为head.S->trampoline.S->x86_32.s,其中head.s为冲GRUB进入XEN的入口文件,首先看看head.s部分都做了什么(只看32位体系)。
Xen源代码分析(二)——trampoline.s
汇编文件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"
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
相关文章推荐
- Windows XP Professional计算机启动过程概述
- Windows XP Professional计算机启动过程概述
- linux内核学习(12)启动全过程概述之三
- rails启动过程(一)代码流程概述
- xen虚拟机的启动过程
- WindowsXP启动过程概述
- 简要概述Linux的启动过程
- linux内核学习(10)启动全过程概述之一
- linux内核学习(9)启动全过程概述之内核映像结构
- Linux文件系统和启动过程概述
- 笔记:Windows XP 启动过程概述 剖析Linux系统启动过程--redhat
- Windows XP系统启动过程概述
- 2.6.27.7启动过程概述
- linux内核学习(11)启动全过程概述之二
- linux内核学习(10)启动全过程概述之一
- WinXP Pro计算机启动过程概述
- Windows XP Professional计算机启动过程概述
- XEN下的网络的启动过程
- XEN启动过程分析
- Windows启动过程概述