启动x86虚拟机
4.2.3 启动x86虚拟机<br />看到arch/x86/kernel/head_32.S的681行:<br />681 #include "../../x86/xen/xen-head.S"<br /> <br />这时候执行arch/x86/xen/xen-head.S下的代码:<br /> <br /> 19#ifdef CONFIG_X86_32<br /> 20 m
4.2.3 启动x86虚拟机
看到arch/x86/kernel/head_32.S的681行:
681 #include "../../x86/xen/xen-head.S"
这时候执行arch/x86/xen/xen-head.S下的代码:
19#ifdef CONFIG_X86_32
20 mov %esi,xen_start_info
21 mov $init_thread_union+THREAD_SIZE,%esp
22#else
23 mov %rsi,xen_start_info
24 mov $init_thread_union+THREAD_SIZE,%rsp
25#endif
26 jmp xen_start_kernel
该文件中有用的就上面几行代码,也就是执行一个xen_start_kernel函数,这个函数的局部变量存放的位置通过重置栈顶指针来设定,更重要的是设计了一个全局变量xen_start_info,其值就是esi的内容。esi可一直没有变过哈,是前面我们研究了很久的boot_params的地址。所以xen_start_info就是执行它的指针。
1057/* First C function to be called on Xen boot */ 1058asmlinkage void __init xen_start_kernel(void) 1059{ 1060 pgd_t *pgd; 1061 …… 1201 1202 /* Start the world */ 1203#ifdef CONFIG_X86_32 1204 i386_start_kernel(); 1205#else 1206 x86_64_start_reservations((char *)__pa_symbol(&boot_params)); 1207#endif 1208} |
整个xen_start_kernel代码是针对Xen的启动代码。这里简单介绍一下Xen,Xen是一个开源的x86体系的para-virtualizing虚拟机监控器(VMM)或者“系统管理程序(hypervisor)”。我们熟悉的Vmware就是以它为基础的。Xen可以安全地在一个物理系统上以接近于本地硬件的性能运行多个虚拟机。Xen具有方便应用的企业级功能,包括:
● 虚拟机的性能接近于本地硬件.
● 在物理机器之间活动迁移正在运行的虚拟机.
● 在每个客户虚拟机支持到32个虚拟CPU, 虚拟CPU(VCPU)热插拔.
● x86/32, 物理地址扩展(PAE)的x86/32 , 和 x86/64 平台支持.
● 不用修改客户操作系统(包括微软的Windows)就能支持因特尔虚拟化技术(VT-x).
● 良好的硬件支持(支持几乎所有的Linux设备驱动).
所以,xen_start_kernel函数完成了Xen的初始化后,就跳到1204行,执行i386_start_kernel函数。该函数来自arch/x86/kernel/head32.c:
31void __init i386_start_kernel(void) 32{ 33#ifdef CONFIG_X86_TRAMPOLINE 34 /* 35 * But first pinch a few for the stack/trampoline stuff 36 * FIXME: Don't need the extra page at 4K, but need to fix 37 * trampoline before removing it. (see the GDT stuff) 38 */ 39 reserve_early_overlap_ok(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, 40 "EX TRAMPOLINE"); 41#endif 42 43 reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); 44 45#ifdef CONFIG_BLK_DEV_INITRD 46 /* Reserve INITRD */ 47 if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) { 48 /* Assume only end is not page aligned */ 49 u64 ramdisk_image = boot_params.hdr.ramdisk_image; 50 u64 ramdisk_size = boot_params.hdr.ramdisk_size; 51 u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); 52 reserve_early(ramdisk_image, ramdisk_end, "RAMDISK"); 53 } 54#endif 55 56 /* Call the subarch specific early setup function */ 57 switch (boot_params.hdr.hardware_subarch) { 58 case X86_SUBARCH_MRST: 59 x86_mrst_early_setup(); 60 break; 61 default: 62 i386_default_early_setup(); 63 break; 64 } 65 66 /* 67 * At this point everything still needed from the boot loader 68 * or BIOS or kernel text should be early reserved or marked not 69 * RAM in e820. All other memory is free game. 70 */ 71 72 start_kernel(); 73} |
由于.config中配置了CONFIG_X86_TRAMPOLINE,所以首先调用reserve_early_overlap_ok函数。这个函数和下面reserve_early一起用于保留一些重叠的空间,他们都会调用__reserve_early。具体的我就不去分析了,感兴趣的同学自己去研究。
47~53行,也是调用__reserve_early函数去保留初始化头中的ramdisk的相关信息。57行,我们可以回头看看header.S的hdr中的hardware_subarch是0,所以直接去调用位于同一文件的i386_default_early_setup函数:
static void __init i386_default_early_setup(void) { /* Initilize 32bit specific setup functions */ x86_init.resources.probe_roms = probe_roms; x86_init.resources.reserve_resources = i386_reserve_resources; x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
reserve_ebda_region(); } |
这个函数就是把虚拟机的x86_init全局变量的一些安装函数设置好,不在话下。以上的函数完成以后,Xen的初始化工作就完了,在i386_start_kernel的最后一行调用start_kernel()函数,终于到了Modern Age。
更多推荐
所有评论(0)