kvm和qemu交互處理io流程

一、IO虛擬化的分類 前端

(1)全虛擬化:宿主機截獲客戶機對I/O設備的訪問請求,而後經過軟件模擬真實的硬件。這種方式對客戶機而言很是透明,無需考慮底層硬件的狀況,不須要修改操做系統。 後端

QEMU模擬I/O的狀況下,當客戶機中的設備驅動程序(device driver)發起I/O操做請求之時,KVM模塊中的I/O操做捕獲代碼會攔截此次I/O請求,而後通過處理後將本次I/O請求的信息存放到I/O共享頁,並通知用戶控件的QEMU程序。QEMU模擬程序得到I/O操做的具體信息以後,交由硬件模擬代碼來模擬出本次的I/O操做,完成以後,將結果放回到I/O共享頁,並通知KVM模塊中的I/O操做捕獲代碼。最後,由KVM模塊中的捕獲代碼讀取I/O共享頁中的操做結果,並把結果返回到客戶機中。固然,這個操做過程當中客戶機做爲一個QEMU進程在等待I/O時也可能被阻塞。函數

另外,當客戶機經過DMADirect Memory Access【DMA外接設備能夠不用CPU干預,直接把數據傳輸到內存的技術,儘可能減小CPU干預的輸入/輸出操做方式。(使用連續物理內存,kmalloc分配)。不然外設一有數據就要中斷通知CPU,CPU去讀,若是頻繁就時間浪費在處理中斷,IO速度慢】訪問大塊I/O之時,QEMU模擬程序將不會把操做結果放到I/O共享頁中,而是經過內存映射的方式將結果直接寫到客戶機的內存中去,而後經過KVM模塊告訴客戶機DMA操做已經完成。 性能

  • 優勢是能夠模擬出各類各樣的硬件設備;
  • 缺點是每次 I/O 操做的路徑比較長,須要屢次上下文切換、屢次數據複製和VM-Entry/Exit,性能較差。 

(2)半虛擬化:經過前端驅動/後端驅動模擬實現I/O虛擬化。客戶機中的驅動程序virtio-blk/net/pci/scsi爲前端,宿主機提供的與客戶機通訊的驅動程序vhost爲後端。先後端驅動經過 virtio-ring 直接通訊,繞過了通過 KVM 內核模塊的過程,達到提升 I/O 性能的目的。 spa

  • 優勢快。vring實現了環形緩衝區(ring buffer),用於保存前端驅動和後端處理程序執行的信息,而且它能夠一次性保存前端驅動的屢次I/O請求,而且交由後端去動去批量處理,最後實際調用宿主機中設備驅動實現物理上的I/O操做,這樣作就能夠根據約定實現批量處理而不是客戶機中每次I/O請求都須要處理一次,從而提升客戶機與hypervisor信息交換的效率。
  • 缺點:須要客戶機中virtio相關驅動的支持(較老的系統默認沒有自帶這些驅動,Windows系統中須要額外安裝virtio驅動),故兼容性較差,並且I/O頻繁時的CPU使用率較高 

(3)IO透傳:直接把物理設備分配給虛擬機使用,這種方式須要硬件平臺具有I/O透傳技術,例如Intel VT-d技術。它能得到近乎本地的性能,而且CPU開銷不高。操作系統

  

二、kvm和qemu的交互線程

Qemu建立虛擬機進入kvm:main函數經過調用kvm_init 和 machine->init來初始化kvm. 其中, machine->init會建立vcpu, 用一個線程去模擬vcpu, 該線程執行的函數爲qemu_kvm_cpu_thread_fn, 而且該線程最終kvm_cpu_exec,該函數調用kvm_vcpu_ioctl切換到kvm中。code

Kvm運行並因io退出:在kvm中看到參數KVM_RUN,最後調用vcpu_enter_guest,而後 vmx_vcpu_run設置好寄存器狀態以後調用VM_LAUNCH或者VM_RESUME進入guest vm。若是vm進行IO操做須要訪問設備時,就會觸發vm exit 返回到vmx_vcpu_run, vmx保存好vmcs而且記錄下VM_EXIT_REASON後返回到調用該函數的vcpu_enter_guest, 在vcpu_enter_guest函數末尾調用了r = kvm_x86_ops->handle_exit(vcpu), 該函數對應於vmx_handle_exit函數, vmx_handle_exit 調用kvm_vmx_exit_handlers[exit_reason](vcpu),該語句根據exit_reason調用不一樣的函數。io操做則是handle_io把數據填充到vcpu->run,就一路return到kvm_vcpu_ioctl,就ioctl返回到qemu的kvm_cpu_exec中。blog

從kvm返回到qemu後的處理:Qemu在kvm_cpu_exec中會看kvm_run的run->exit_reason若是是KVM_EXIT_IO就進入kvm_handle_io裏處理。 當qemu完成IO操做後,會在kvm_cpu_exec函數的循環中,調用kvm_vcpu_ioctl從新進入kvm。進程

kvm_run,這是用於vcpu和應用層的程序(典型如qemu)通訊的一個結構,user space的 程序經過KVM__VCPU_MMAP_SIZE這個ioctl獲得大小,而後映射到用戶空間。

 

三、kvm的io處理流程

static int handle_io(struct kvm_vcpu *vcpu) { unsigned long exit_qualification; int size, in, string; unsigned port; exit_qualification = vmcs_readl(EXIT_QUALIFICATION);  //獲取exit qualification

         string = (exit_qualification & 16) != 0; //判斷是否爲string io (ins, outs)

         in = (exit_qualification & 8) != 0; //判斷io方向,是in 仍是out

 

         ++vcpu->stat.io_exits; if (string || in) //若是是輸入類的指令,或者是string io,就進入emulator處理

                   return emulate_instruction(vcpu, 0) == EMULATE_DONE; port = exit_qualification >> 16; //獲得端口號
 size = (exit_qualification & 7) + 1; //大小
 skip_emulated_instruction(vcpu); //跳過這個指令

 

         return kvm_fast_pio_out(vcpu, size, port); //進行out操做
 }

Guest執行io指令 -> 發生vmexit-> 返回qemu -> 處理io

一、out指令虛擬:虛擬單個out指令,在KVM中能夠直接把out的數據返回給qemuqemu完成out操做

流程:KVM的handle_io->kvm_fast_pio_out->emulator_pio_out_emulated後面是vcpu->arch.pio.count = 0函數中非string類型的 out操做能夠一步完成,因此從qemu處理完返回kvm後不須要再進入emulator。在emulator_pio_out_emulated中,將IO數據memcpy到kvm和qemu共享buffer中,而後emulator_pio_in_out,將相應數據保存到kvm_run中就返回到qemu的kvm_cpu_exec的switch看run->exit_reason,若是是KVM_EXIT_IO則進入kvm_handle_io中和設備交互。

二、Stringin指令虛擬:若是是in指令,qemu只能把獲得的數據寫到kvm_run中,kvm必須在下一次vmentry的時候,將qemu獲得的數據放到相應的位置,因此,在handle_io中,若是是in或者string指令,沒有調用skip_emulated_instruction,這樣,qemu完成in或者一次out以後,還會在一樣的地方發生vmexit,這樣再由emulator完成相應的處理,針對string類型的指令,emulator會進行解碼等操做,確認io的次數和源操做數、目的操做數等。

流程:handle_io->emulate_instruction->x86_emulate_instruction對指令的decode,在過程當中會調用到em_in和em_out(這兩個函數最後調用的emulator_pio_in_emulated中先經過和上面PIO同樣的函數emulator_pio_in_out,正確返回代表qemu已經將模擬出的數據返回到參數val了,則可直接memcpy完成具體的將從qemu中獲得的數據寫到正確位置vcpu->arch.pio_data),設置若是是out,下次到KVM時直接進入emulator,若是是in,註冊vcpu->arch.complete_userspace_io = complete_emulated_pio;須要在下次qemu進入kvm的時候,完成io,實際上就是將qemu獲得的數據寫到正確的位置。下次進入kvm,若是要完成in指令,會在函數kvm_arch_vcpu_ioctl_run中調用註冊的complete_emulated_pio會再次調用emulate_instruction將數據寫到正確位置(此次不用解碼,而是直接em_in)。

相關文章
相關標籤/搜索