Qemu-KVM虛擬機器初始化及建立過程原始碼簡要分析(一)
阿新 • • 發佈:2019-01-05
我們知道,Qemu-KVM實際上包括Qemu和KVM兩部分,那麼在建立以及初始化虛擬機器時,實際上也是在這兩部分進行的。
KVM實際上就是kvm核心模組,包括kvm.ko、kvm-intel.ko、kvm-amd.ko三部分,後兩部分分別對應Intel體系的VMX技術以及AMD體系的SVM技術。
首先,我們需要載入模組,當我們載入kvm-xxx.ko模組時,會呼叫對應的module_init()函式,然後呼叫vmx_init()或者svm_init()函式,最後進入到統一的kvm.ko模組中的kvm_init()函式,現在正式開始進行虛擬機器的初始化工作。
module_init(vmx_init) //位於vmx.c檔案
static int __init vmx_init(void) //位於vmx.c檔案
{
..............//省略部分程式碼
r= kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx),
__alignof__(struct vcpu_vmx),THIS_MODULE);
................//省略部分程式碼
}
int kvm_init(void *opaque, unsigned vcpu_size,unsigned vcpu_align, struct module *module) //位於kvm_main.c檔案 { ......................//省略部分程式碼 r= kvm_arch_init(opaque); ........................//省略部分程式碼 }
在進入到kvm_init()函式後,進行了很多初始化的相關工作,這裡單獨強調一下kvm_arch_init()函式。
在vmx.c檔案中宣告並定義了一個結構體vmx_x86_ops,這是函式指標的集合,其實就是各種操作的一個集合。內部很多函式是後續的初始化工作需要具體呼叫到的,比如很多Qemu層的ioctl呼叫到核心層實際上就是執行這內部的一些函式。具體的內容如下:
static struct kvm_x86_ops vmx_x86_ops = { .cpu_has_kvm_support= cpu_has_kvm_support, .disabled_by_bios= vmx_disabled_by_bios, .hardware_setup= hardware_setup, .hardware_unsetup= hardware_unsetup, .check_processor_compatibility= vmx_check_processor_compat, .hardware_enable= hardware_enable, .hardware_disable= hardware_disable, .cpu_has_accelerated_tpr= report_flexpriority, .vcpu_create= vmx_create_vcpu, .vcpu_free= vmx_free_vcpu, .vcpu_reset= vmx_vcpu_reset, .prepare_guest_switch= vmx_save_host_state, .vcpu_load= vmx_vcpu_load, .vcpu_put= vmx_vcpu_put, .update_db_bp_intercept= update_exception_bitmap, .get_msr= vmx_get_msr, .set_msr= vmx_set_msr, .get_segment_base= vmx_get_segment_base, .get_segment= vmx_get_segment, .set_segment= vmx_set_segment, .get_cpl= vmx_get_cpl, .get_cs_db_l_bits= vmx_get_cs_db_l_bits, .decache_cr0_guest_bits= vmx_decache_cr0_guest_bits, .decache_cr3= vmx_decache_cr3, .decache_cr4_guest_bits= vmx_decache_cr4_guest_bits, .set_cr0= vmx_set_cr0, .set_cr3= vmx_set_cr3, .set_cr4= vmx_set_cr4, .set_efer= vmx_set_efer, .get_idt= vmx_get_idt, .set_idt= vmx_set_idt, .get_gdt= vmx_get_gdt, .set_gdt= vmx_set_gdt, .set_dr7= vmx_set_dr7, .cache_reg= vmx_cache_reg, .get_rflags= vmx_get_rflags, .set_rflags= vmx_set_rflags, .fpu_activate= vmx_fpu_activate, .fpu_deactivate= vmx_fpu_deactivate, .tlb_flush= vmx_flush_tlb, .run= vmx_vcpu_run, .handle_exit= vmx_handle_exit, .skip_emulated_instruction= skip_emulated_instruction, .set_interrupt_shadow= vmx_set_interrupt_shadow, .get_interrupt_shadow= vmx_get_interrupt_shadow, .patch_hypercall= vmx_patch_hypercall, .set_irq= vmx_inject_irq, .set_nmi= vmx_inject_nmi, .queue_exception= vmx_queue_exception, .cancel_injection= vmx_cancel_injection, .interrupt_allowed= vmx_interrupt_allowed, .nmi_allowed= vmx_nmi_allowed, .get_nmi_mask= vmx_get_nmi_mask, .set_nmi_mask= vmx_set_nmi_mask, .enable_nmi_window= enable_nmi_window, .enable_irq_window= enable_irq_window, .update_cr8_intercept= update_cr8_intercept, .set_virtual_x2apic_mode= vmx_set_virtual_x2apic_mode, .vm_has_apicv= vmx_vm_has_apicv, .load_eoi_exitmap= vmx_load_eoi_exitmap, .hwapic_irr_update= vmx_hwapic_irr_update, .hwapic_isr_update= vmx_hwapic_isr_update, .sync_pir_to_irr= vmx_sync_pir_to_irr, .deliver_posted_interrupt= vmx_deliver_posted_interrupt, .set_tss_addr= vmx_set_tss_addr, .get_tdp_level= get_ept_level, .get_mt_mask= vmx_get_mt_mask, .get_exit_info= vmx_get_exit_info, .get_lpage_level= vmx_get_lpage_level, .cpuid_update= vmx_cpuid_update, .rdtscp_supported= vmx_rdtscp_supported, .invpcid_supported= vmx_invpcid_supported, .set_supported_cpuid= vmx_set_supported_cpuid, .has_wbinvd_exit= cpu_has_vmx_wbinvd_exit, .set_tsc_khz= vmx_set_tsc_khz, .read_tsc_offset= vmx_read_tsc_offset, .write_tsc_offset= vmx_write_tsc_offset, .adjust_tsc_offset= vmx_adjust_tsc_offset, .compute_tsc_offset= vmx_compute_tsc_offset, .read_l1_tsc= vmx_read_l1_tsc, .set_tdp_cr3= vmx_set_cr3, .check_intercept= vmx_check_intercept, .handle_external_intr= vmx_handle_external_intr, };
這個結構體作為引數傳遞到kvm_init()函式,再傳遞到kvm_arch_init()函式,再傳遞到全域性變數kvm_x86_ops中,註冊各種操作函式,後續可以呼叫。隨後還進行了一些內部資料結構以及定時器、除錯資訊等的一些初始化工作。與此同時,qemu層也會進行大部分的初始化工作,這一部分後一篇再講。