免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2628 | 回复: 0
打印 上一主题 下一主题

半虚拟化的一个实现——Lguest [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-02-23 21:35 |只看该作者 |倒序浏览
1.  Lguest 总架构:

  • Hardware:指 CPU,内存,硬盘等等
  • Hardware API:指硬件提供给软件访问硬件的编程接口
  • Host OS Kernel:指直接运行在硬件之上的操作系统。注意:host OS kernel 和 guest OS kernel必须是同一版本
  • Lg hypervisor module:指加载到 Host OS 的 lguest 模块,用于处理必须由hypervisor完成的工作
  • launcher:Lguest hypervisor 和 guest OS的中间层 2.  guset:
    Lguest属于半虚拟化虚拟机。因此guest OS  kernel需要修改才能够运行在  host OS 之上。VMware  起先提出了  VMI  半虚拟化接口。后来经过经过开源社区的努力,设计出了paravirt_ops 接口。 Paravirt_ops 在linux 内核中的初始化: 摘自:linux 2.6.23.13\arch\i386
    struct paravirt_ops paravirt_ops = {
    ......
    };
    Paravirt_ops 在 lguest 中的只用:
    摘自:lguest
    /*G:030 Once we get to lguest_init(), we know we're a Guest.  The paravirt_ops
    * structure in the kernel provides a single point for (almost) every routine
    * we have to override to avoid privileged instructions. */  
    __init void lguest_init(void *boot)
    {      /* Copy boot parameters first: the Launcher put the physical location
    * in %esi, and head.S converted that to a virtual address and handed
    * it to us.  We use "__memcpy" because "memcpy" sometimes tries to do
    * tricky things to go faster, and we're not ready for that. */
    __memcpy(&boot_params, boot, PARAM_SIZE);
    /* The boot parameters also tell us where the command-line is: save
    * that, too. */  
    __memcpy(boot_command_line, __va(boot_params.hdr.cmd_line_ptr),
    COMMAND_LINE_SIZE);
    /* We're under lguest, paravirt is enabled, and we're running at
    * privilege level 1, not 0 as normal. */
    paravirt_ops.name = "lguest";
    paravirt_ops.paravirt_enabled = 1;
    paravirt_ops.kernel_rpl = 1;
    /* We set up all the lguest overrides for sensitive operations.  These
    * are detailed with the operations themselves. */  
    ........
    /* Now is a good time to look at the implementations of these functions
    * before returning to the rest of lguest_init(). */
    /*G:070 Now we've seen all the paravirt_ops, we return to
    * lguest_init() where the rest of the fairly chaotic boot setup
    * occurs.
    *
    * The Host expects our first hypercall to tell it where our "struct
    * lguest_data" is, so we do that first. */
    hcall(LHCALL_LGUEST_INIT, __pa(&lguest_data), 0, 0);
    /* The native boot code sets up initial page tables immediately after
    * the kernel itself, and sets init_pg_tables_end so they're not
    * clobbered.  The Launcher places our initial pagetables somewhere at
    * the top of our physical memory, so we don't need extra space: set
    * init_pg_tables_end to the end of the kernel. */  
    init_pg_tables_end = __pa(pg0);
    /* Load the %fs segment register (the per-cpu segment register) with
    * the normal data segment to get through booting. */
    asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory");
    /* Clear the part of the kernel data which is expected to be zero.
    * Normally it will be anyway, but if we're loading from a bzImage with
    * CONFIG_RELOCATALE=y, the relocations will be sitting here. */
    memset(__bss_start, 0, __bss_stop - __bss_start);
    /* The Host uses the top of the Guest's virtual address space for the      * HostGuest Switcher, and it tells us how much it needs in
    * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */
    reserve_top_address(lguest_data.reserve_mem);
    /* If we don't initialize the lock dependency checker now, it crashes
    * paravirt_disable_iospace. */
    lockdep_init();
    /* The IDE code spends about 3 seconds probing for disks: if we reserve
    * all the I/O ports up front it can't get them and so doesn't probe.
    * Other device drivers are similar (but less severe).  This cuts the
    * kernel boot time on my machine from 4.1 seconds to 0.45 seconds. */
    paravirt_disable_iospace();
    /* This is messy CPU setup stuff which the native boot code does before
    * start_kernel, so we have to do, too: */
    cpu_detect(&new_cpu_data);
    /* head.S usually sets up the first capability word, so do it here. */
    new_cpu_data.x86_capability[0] = cpuid_edx(1);
    /* Math is always hard! */
    new_cpu_data.hard_math = 1;
    #ifdef CONFIG_X86_MCE
    mce_disabled = 1;
    #endif
    #ifdef CONFIG_ACPI
    acpi_disabled = 1;
    acpi_ht = 0;
    #endif
    /* We set the perferred console to "hvc".  This is the "hypervisor
    * virtual console" driver written by the PowerPC people, which we also
    * adapted for lguest's use. */
    add_preferred_console("hvc", 0, NULL);
    /* Last of all, we set the power management poweroff hook to point to
    * the Guest routine to power off. */
    pm_power_off = lguest_power_off;
    /* Now we're set up, call start_kernel() in init/main.c and we proceed
    * to boot as normal.  It never returns. */
    start_kernel();
    }
    Lguest 在 guest os 中初始化的流程图:

    3. Launcher:
    This is the Launcher code, a simple program which lays out the "physical" memory for the new Guest by mapping the kernel image and the virtual devices, then reads repeatedly from /dev/lguest to run the Guest.
    launcher 初始化流程图:



    4. host:
    This contains run_guest() which actually calls into the HostGuest Switcher and analyzes the return, such as determining if the Guest wants the Host to do something.  This file also contains useful helper routines, and a couple of non-obvious setup and teardown pieces which were implemented after days of debugging pain.  
    host端的初始化流程图:

    下面给出运行guest的流程图:
    int run_guest(struct lguest *lg, unsigned long __user *user):runs the Guest



    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/110913/showart_2185411.html
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP