4.2.3 启动x86虚拟机

看到arch/x86/kernel/head_32.S681

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的启动代码。这里简单介绍一下XenXen是一个开源的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.Shdr中的hardware_subarch0所以直接去调用位于同一文件的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

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐