分类: LINUX
2010-02-23 21:35:01
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