Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1292036
  • 博文数量: 196
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 虚拟化

2009-03-22 16:13:39

摘自:linux 2.6.23.13\arch\i386\kernel
struct paravirt_ops paravirt_ops = {
    .name = "bare hardware",
    .paravirt_enabled = 0,
    .kernel_rpl = 0,
    .shared_kernel_pmd = 1,    /* Only used when CONFIG_X86_PAE is set */

     .patch = native_patch,
    .banner = default_banner,
    .arch_setup = paravirt_nop,
    .memory_setup = machine_specific_memory_setup,
    .get_wallclock = native_get_wallclock,
    .set_wallclock = native_set_wallclock,
    .time_init = hpet_time_init,
    .init_IRQ = native_init_IRQ,

    .cpuid = native_cpuid,
    .get_debugreg = native_get_debugreg,
    .set_debugreg = native_set_debugreg,
    .clts = native_clts,
    .read_cr0 = native_read_cr0,
    .write_cr0 = native_write_cr0,
    .read_cr2 = native_read_cr2,
    .write_cr2 = native_write_cr2,
    .read_cr3 = native_read_cr3,
    .write_cr3 = native_write_cr3,
    .read_cr4 = native_read_cr4,
    .read_cr4_safe = native_read_cr4_safe,
    .write_cr4 = native_write_cr4,
    .save_fl = native_save_fl,
    .restore_fl = native_restore_fl,
    .irq_disable = native_irq_disable,
    .irq_enable = native_irq_enable,
    .safe_halt = native_safe_halt,
    .halt = native_halt,
    .wbinvd = native_wbinvd,
    .read_msr = native_read_msr_safe,
    .write_msr = native_write_msr_safe,
    .read_tsc = native_read_tsc,
    .read_pmc = native_read_pmc,
    .sched_clock = native_sched_clock,
    .get_cpu_khz = native_calculate_cpu_khz,
    .load_tr_desc = native_load_tr_desc,
    .set_ldt = native_set_ldt,
    .load_gdt = native_load_gdt,
    .load_idt = native_load_idt,
    .store_gdt = native_store_gdt,
    .store_idt = native_store_idt,
    .store_tr = native_store_tr,
    .load_tls = native_load_tls,
    .write_ldt_entry = write_dt_entry,
    .write_gdt_entry = write_dt_entry,
    .write_idt_entry = write_dt_entry,
    .load_esp0 = native_load_esp0,

    .set_iopl_mask = native_set_iopl_mask,
    .io_delay = native_io_delay,

#ifdef CONFIG_X86_LOCAL_APIC
    .apic_write = native_apic_write,
    .apic_write_atomic = native_apic_write_atomic,
    .apic_read = native_apic_read,
    .setup_boot_clock = setup_boot_APIC_clock,
    .setup_secondary_clock = setup_secondary_APIC_clock,
    .startup_ipi_hook = paravirt_nop,
#endif
    .set_lazy_mode = paravirt_nop,

    .pagetable_setup_start = native_pagetable_setup_start,
    .pagetable_setup_done = native_pagetable_setup_done,

    .flush_tlb_user = native_flush_tlb,
    .flush_tlb_kernel = native_flush_tlb_global,
    .flush_tlb_single = native_flush_tlb_single,
    .flush_tlb_others = native_flush_tlb_others,

    .alloc_pt = paravirt_nop,
    .alloc_pd = paravirt_nop,
    .alloc_pd_clone = paravirt_nop,
    .release_pt = paravirt_nop,
    .release_pd = paravirt_nop,

    .set_pte = native_set_pte,
    .set_pte_at = native_set_pte_at,
    .set_pmd = native_set_pmd,
    .pte_update = paravirt_nop,
    .pte_update_defer = paravirt_nop,

#ifdef CONFIG_HIGHPTE
    .kmap_atomic_pte = kmap_atomic,
#endif

#ifdef CONFIG_X86_PAE
    .set_pte_atomic = native_set_pte_atomic,
    .set_pte_present = native_set_pte_present,
    .set_pud = native_set_pud,
    .pte_clear = native_pte_clear,
    .pmd_clear = native_pmd_clear,

    .pmd_val = native_pmd_val,
    .make_pmd = native_make_pmd,
#endif

    .pte_val = native_pte_val,
    .pgd_val = native_pgd_val,

    .make_pte = native_make_pte,
    .make_pgd = native_make_pgd,

    .irq_enable_sysexit = native_irq_enable_sysexit,
    .iret = native_iret,

    .dup_mmap = paravirt_nop,
    .exit_mmap = paravirt_nop,
    .activate_mm = paravirt_nop,
};

摘自: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. */
    paravirt_ops.save_fl = save_fl;
    paravirt_ops.restore_fl = restore_fl;
    paravirt_ops.irq_disable = irq_disable;
    paravirt_ops.irq_enable = irq_enable;
    paravirt_ops.load_gdt = lguest_load_gdt;
    paravirt_ops.memory_setup = lguest_memory_setup;
    paravirt_ops.cpuid = lguest_cpuid;
    paravirt_ops.write_cr3 = lguest_write_cr3;
    paravirt_ops.flush_tlb_user = lguest_flush_tlb_user;
    paravirt_ops.flush_tlb_single = lguest_flush_tlb_single;
    paravirt_ops.flush_tlb_kernel = lguest_flush_tlb_kernel;
    paravirt_ops.set_pte = lguest_set_pte;
    paravirt_ops.set_pte_at = lguest_set_pte_at;
    paravirt_ops.set_pmd = lguest_set_pmd;
#ifdef CONFIG_X86_LOCAL_APIC
    paravirt_ops.apic_write = lguest_apic_write;
    paravirt_ops.apic_write_atomic = lguest_apic_write;
    paravirt_ops.apic_read = lguest_apic_read;
#endif
    paravirt_ops.load_idt = lguest_load_idt;
    paravirt_ops.iret = lguest_iret;
    paravirt_ops.load_esp0 = lguest_load_esp0;
    paravirt_ops.load_tr_desc = lguest_load_tr_desc;
    paravirt_ops.set_ldt = lguest_set_ldt;
    paravirt_ops.load_tls = lguest_load_tls;
    paravirt_ops.set_debugreg = lguest_set_debugreg;
    paravirt_ops.clts = lguest_clts;
    paravirt_ops.read_cr0 = lguest_read_cr0;
    paravirt_ops.write_cr0 = lguest_write_cr0;
    paravirt_ops.init_IRQ = lguest_init_IRQ;
    paravirt_ops.read_cr2 = lguest_read_cr2;
    paravirt_ops.read_cr3 = lguest_read_cr3;
    paravirt_ops.read_cr4 = lguest_read_cr4;
    paravirt_ops.write_cr4 = lguest_write_cr4;
    paravirt_ops.write_gdt_entry = lguest_write_gdt_entry;
    paravirt_ops.write_idt_entry = lguest_write_idt_entry;
    paravirt_ops.patch = lguest_patch;
    paravirt_ops.safe_halt = lguest_safe_halt;
    paravirt_ops.get_wallclock = lguest_get_wallclock;
    paravirt_ops.time_init = lguest_time_init;
    paravirt_ops.set_lazy_mode = lguest_lazy_mode;
    paravirt_ops.wbinvd = lguest_wbinvd;
    /* 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();
}
/*
 * This marks the end of stage II of our journey, The Guest.
 *
 * It is now time for us to explore the nooks and crannies of the three Guest
 * devices and complete our understanding of the Guest in "make Drivers".
 */

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