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.22qemu使用了大量
物件導向
的程式設計方式,並用c語言實現了類
和類的構建、析構函式
等。
qemu將kvm定義為一種加速型別(accelclass)
,註冊到了type_table
中,因此通過初始化物件就可以直接呼叫物件所屬類的方法。
accelclass
的init_machine()
方法可以獲得vm_fd
.
與加速器類似,vcpu也被設計為一種cpu型別(x86_vcpu_type)
, 將qemu的main函式中的current_machine->type
指向x86_vcpu_type
,即可呼叫該類的方法使用vcpu.
x86_vcpu_type
的x86_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...