Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1812874
  • 博文数量: 473
  • 博客积分: 13997
  • 博客等级: 上将
  • 技术积分: 5953
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-22 11:52
文章分类

全部博文(473)

文章存档

2014年(8)

2013年(38)

2012年(95)

2011年(181)

2010年(151)

分类: LINUX

2010-02-23 21:35:01

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      * Host<->Guest 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 Host<->Guest 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

阅读(941) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~