linux 虚拟接口,linux 半虚拟化接口(paravirt_ops)

摘自: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

* 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();

}

/*

* 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".

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值