QEMU KVM框架總結

2022-01-10 06:17:34 字數 4497 閱讀 7401

arch/x86/kvm/vmx/vmx.c

載入kvm模組時,呼叫順序為module_init()->vmx_init()->kvm_init(),所以kvm_init()為核心函式

int kvm_init()

kvm模組載入完成後,在系統的/dev目錄下出現kvm裝置,用於外界與kvm互動

virt/kvm/kvm_main.c

分為3大類,大多都在kvm_main.c中實現,剩餘一小部分在arch/x86/kvm/vmx/vmx.c中.3類ioctl分別為裝置、虛擬機器、虛擬cpu級別.3個層次逐級概念變小,虛擬機器由裝置層面的ioctl建立,而虛擬cpu由虛擬機器級別的ioctl建立.

kvm_dev_ioctl為字首,負責以下通用裝置級別的ioctl功能的處理

其餘裝置級別的ioctl功能與架構有關,因此在kvm_arch_dev_ioctl()中實現.

kvm_vm_ioctl為字首,負責以下通用虛擬機器級別的ioctl功能的處理

其餘虛擬機器級別的ioctl功能與架構有關,因此在kvm_arch_vm_ioctl()中實現.

kvm_vcpu_ioctl為字首,負責以下通用虛擬cpu級別的ioctl功能的處理

其餘虛擬cpu級別的ioctl功能與架構有關,因此在kvm_arch_vcpu_ioctl()中實現.

主要建立流程就是dev->vm->vcpu,這期間最重要的資料結構為kvm_x86_ops(在vmx.c中定義),但是在ioctl函式中展現的形式與實際呼叫的函式形式有些許不同. 如在建立vm時,函式呼叫流程為:

kvm_dev_ioctl_create_vm()->kvm_create_vm()->kvm_arch_alloc_vm()

kvm_arch_alloc_vm()中,具體實現只有一句return kvm_x86_ops->vm_alloc(),此時使用vim外掛程式無法找到vm_alloc()的定義,但在vmx.c中可以看到類似.vm_alloc = vmx_vm_alloc, 因此其實vm_alloc()呼叫的是vmx_vm_alloc,其它kvm_x86_ops的子方法也可以使用類似的方法找到.

kvm_dev_ioctl_create_vm()->kvm_create_vm()->kvm_arch_alloc_vm()->vmx_vm_alloc()

​ | ->kvm_arch_init_vm()| ->vmx_vm_init()

因此可以通過呼叫kvm_dev_ioctl_create_vm()完成對乙個vm的記憶體分配和初始化,最終返回的是乙個kvm_vmx結構的結構.

kvm_vm_ioctl_create_vcpu()->kvm_arch_vcpu_create()->vmx_create_vcpu()

​ | ->kvm_arch_vcpu_setup()->vmx_vcpu_setup()

​ | ->create_vcpu_fd

kvm_arch_vcpu_create()vcpu_vmx結構申請空間,初始化vcpu,為guest_msr,vmcs結構申請空間,並利用vmx_vcpu_setup()vmcs設定為實模式狀態,利用vmx_vcpu_put()準備將vcpu切換至host狀態.

kvm_vcpu_ioctl(...,kvm_run,...)->kvm_arch_vcpu_ioctl_run()->vcpu_run()->vcpu_enter_guest()|

​ ->need_resched()

vcpu_enter_guest()使虛擬vcpu進入non-root操作,退出該函式等效於執行了vm exit,如果退出該函式時返回1,即代表guest無法處理本次exit reasion,需要進入到使用者空間(qemu),使用qemu對本次exit reason進行處理,處理完成之後再進入vcpu_enter_guest().

由於這部分與qemu有互動的部分,因此我提前對qemu進行了學習.

qemu與kvm對應有4大類的ioctl,用於對kvm提供的3個級別的fd進行控制.

用於對device_fd(/dev/kvm)進行操作 --->hypervisor

用於對kvmstate結構體中的fd進行操作 ---> 對應kvm的device級別

用於對kvmstate結構體中vmfd進行操作 ---> 對應kvm的vm級別

用於對cpustate結構體中的kvm_fd進行操作 ---> 對應kvm的vcpu級別

kvm的kvm_vcpu結構體中含有kvm_run結構,用於qemu的使用者空間和kvm模組的互動. 例如在vm exit時,為了對虛擬硬體的訪問進行模擬,kvm必須返回到qemu使用者空間中,因此kvm將相關資訊儲存到kvm_run結構中,留給qemu獲取資訊.

【update】 2019.11.22

qemu使用了大量物件導向的程式設計方式,並用c語言實現了類的構建、析構函式等。

qemu將kvm定義為一種加速型別(accelclass),註冊到了type_table中,因此通過初始化物件就可以直接呼叫物件所屬類的方法。

accelclassinit_machine()方法可以獲得vm_fd.

與加速器類似,vcpu也被設計為一種cpu型別(x86_vcpu_type), 將qemu的main函式中的current_machine->type指向x86_vcpu_type,即可呼叫該類的方法使用vcpu.

x86_vcpu_typex86_vcpu_common_class_init()方法可以獲得vcpu的inode(qemu中稱為kvm_fd).

值得注意的是qemu為每個vcpu申請了乙個執行緒(thread),所佔空間在qemu本身在host上所佔的空間中.

qemu的main函式中與kvm有關的部分對應的為配置加速器設定vcpu兩部分,以及最後的迴圈執行vcpu,主要函式為:

configure_accelerator();

current_machine->cpu_type的賦值;

main_loop();

我對qemu-kvm框架整理後,畫了以下結構圖.

解除安裝qemu kvm

由於通過原始碼安裝的qemu沒有辦法通過系統工具進行解除安裝,也沒有辦法通過make uninstall方法解除安裝,所以只能通過刪除檔案的方式進行解除安裝。qemu可執行檔案預設放在 usr local bin,庫檔案預設放在 usr local libexec,配置檔案預設放在 usr loca...

如何編譯qemu kvm

在rhel上編譯社群最新版本的qemu,並且保持原有rhel的版本,方便在環境上除錯社群qemu最新的功能。git clone git git.qemu project.org qemu.git 2.執行configure配置,這個步驟會提示安裝依賴包,按照說明進行安裝即可。選擇只編譯x86架構,減...

QEMU KVM無法啟動

今天在把qemu kvm上的乙個虛擬機器shutdown後總是無法啟動,使用virt manager管理工具啟動時總是導致該工具意外終止,如果是使用virsh命令列管理工具啟動時總是報錯 root db1 virsh start oneracvm error failed to start doma...