vSVA邏輯分析

vSVA邏輯分析

-v0.1 2020.2.29 Sherlock init.
-v0.2 2020.4.16 Sherlock add missing pasid logic in guest.
-v0.3 2020.4.27 Sherlock update vSMMU/SMMU CD base update.

簡介:本文分析Linux vSVA現在的構架邏輯。目前爲止Linux vSVA的代碼還在構架討論和代碼review階段。

  1. qemu基礎認識

qemu裏linux系統的用戶態代碼跑在cpu EL0, qemu裏linux系統的內核態代碼跑在cpu EL1。

qemu創建虛擬機的時候ioctl(CREATE_VM,VCPU,MEMORY)會到cpu EL2創建VM的記錄信息。
ioctl(VM_RUN)會把PC指向虛擬機起始地址,然後退出到EL1。EL2只起到虛擬機管理的作用,
虛擬機上的代碼正常運行時,代碼佔據真實的CPU,並且如果是用戶態代碼,跑在物理CPU
的EL0, 如果是內核態代碼就直接跑到物理CPU的EL1。當CPU訪問物理內存的時候,VA->IPA
的轉換由MMU S1直接支持, 當IPA的地址落在之前ioctl註冊的虛擬機地址空間時,硬件自動
完成MMU S2的轉換。可見,虛擬機裏的進程頁表是直接放到虛擬機內核地址空間的。

虛擬機裏的代碼運行在CPU EL0/EL1。當有IO訪問的時候, 因爲之前創建虛擬機的時候
已經把IO地址空間配置給虛擬機,這裏有IO訪問的時候會觸發CPU異常,虛擬機退出,CPU
進入EL2, CPU在EL2處理後退出到虛擬機qemu裏,qemu可以具體去處理這個IO,比如是一個
網絡IO,那qemu可以直接起socket,把報文發出去。注意,這裏的虛擬機退出是指CPU不再
運行虛擬機裏執行的代碼,因爲CPU並不知道如果控制IO。

  1. vSVA

vSVA的目標是在虛擬機裏(qemu),使的IO設備可以直接使用進程VA。所以,我們這裏的
假設是物理IO設備已經通過host上vfio驅動直通給虛擬機。

要實現vSVA的目標,我們需要同時使能SMMU的S1,S2地址翻譯,S1進行VA->IPA翻譯,S2
進行IPA->PA翻譯,如果是host vfio使能,我們認爲S2的翻譯已經通過vfio配置在SMMU裏。

所以,vSVA的方案需要把虛擬機系統裏的進程頁表同步到host SMMU上。因爲是vSVA,就
有可能出現設備發起內存訪問的時候,host SMMU上虛擬機裏的進程頁表項不存在的情況,
所以,host上的SMMU要可以支持S1缺頁。因爲,S2用vfio支持,vfio採用pin內存的方式,
暫時我們不需要S2的缺頁。這裏說的host上SMMU支持S1缺頁,並不是在host系統上做S1缺頁,
我們這裏討論的是nested SMMU, 所以在host SMMU硬件檢測到S1缺頁的時候,應該把這個
信息上報給guest裏的SMMU,guest裏使用和host一樣的SMMU驅動處理缺頁,當guest處理完
這個缺頁後,應該把對應的頁表信息同步到SMMU的物理硬件上(SMMU.CD.TT0裏)。因爲,
guest裏的進程頁表和SMMU CD上的頁表物理上不是一個,很明顯這裏有一個設備和vcpu頁
表的同步問題,在host SVA上這個問題不存在,因爲host SVA上cpu和SMMU是物理上共用
相同頁表。因此,在需要在vcpu無效化頁表的時候,需要把信息同步到host的SMMU上,
這個信息包括頁表項和TLB。host SVA上也有這個問題,但是如果用SMMU stall mode, 可
以配置DVM,把CPU側TLB invalidate廣播到SMMU,這樣就不需要軟件同步。

在guest裏多進程使用一個設備的資源,就需要支持PASID。這裏的邏輯和上面的是一樣的,
只不過擴展到多進程。

  1. 軟件框架

      +----------------------+
      | guest           user |
      |                      |
      |                      |
      |                      |
      |----------------------|   --------------------    VA
      |               kernel |                                 +------------+
      |                      |                                 | page table |
      |                      |                                 +------------+
      |                      |                                         ^
      +----------------------+                                         |
      +----------------------+         --------------------  IPA       |
      | host                 |                                         |
      |                      |                                         |
      |                      |             +---------+                 |
      |                      |             | DDR     |        PA       |
      |                      |             +---------+                 |
      |                      |                                         |
      |                      |                                         |
      |                      |                                         |
      |                      |                                         |
      +----------------------+                                         |
              |                                                        |
              |                   +-----+                              |
              |          +------> | S1  |  VA->IPA  <------------------+
           +--+---+ -----+        +-----+                  
	   | SMMU |
           +------+ -----+        +-----+
              ^          +------> | S2  |  IPA->PA
              |                   +-----+
           +-----+
	   | dev |
           +-----+

我們順着具體的數據流看看需要的接口,在dev的控制寄存器被map到guest的用戶態後,
用戶態可以直接給guest VA配置給dev,啓動dev從VA處讀寫數據。dev發出的訪問到達
SMMU後首先要進過S1的翻譯,得到IPA,所以S1需要guest裏的進程的頁表。

目前Redhat的Eric在做ARM nested SMMU的支持,他把相關的補丁集合到了他的分支裏,
你可以在這個地方看到完整的內核補丁:https://github.com/eauger/linux branch:
v5.6-2stage-v11_10.1。這組補丁裏給vfio加了一個ioctl(VFIO_IOMMU_SET_PASID_TABLE),
用這個ioctl把虛擬機裏的SMMU的CD地址(IPA)直接傳給host,並且配置給物理SMMU的CD
基地址。對於預先在vcpu一側有缺頁的情況,這裏S1可以查頁表翻譯,SMMU硬件在nested
模式下,會對CD基地址做S2翻譯的到CD的真正物理地址,然後找見頁表做翻譯。可見qemu
裏的SMMU驅動使用和host SMMU相同的驅動,初始化qemu裏SMMU的CD.TT0, 然後把CD直接
通過系統調用配置到物理SMMU上。需要注意,這裏CD裏的頁表基地址是IPA,SMMU硬件
會先根據S2頁表翻譯IPA到PA得到頁表物理基地址。

對於dev傳給SMMU的VA沒有頁表的情況, S1要做缺頁處理。這裏的缺頁處理在邏輯上應該
上報給guest,因爲要做vSVA,是要給虛擬機裏的進程的頁表加頁表項。Eric這組補丁裏,
在vfio里加了一個event queue的隊列,mmap到host用戶態,用來傳遞這個信息。邏輯上看,
qemu應該處理並上報這個缺頁請求,qemu裏的SMMU驅動做缺頁處理。在qemu的SMMU驅動做
缺頁處理的時候,來自dev的請求是stall在SMMU裏的,所以,SMMU缺頁處理完畢後,應該
有通知機制通知到host SMMU,使能stall的請求繼續。

可以看到當頁表有變動的時候,在guest和物理SMMU上同步頁表的開銷是很大的。

當guest裏的進程有退出或者內存有釋放時,需要更新guest裏進程的頁表,vcpu tlb,
host SMMU上相關進程頁表和tlb。Eric補丁裏vfio裏提供了ioctl(VFIO_IOMMU_CACHE_INVALIDATE)
用來更新host SMMU上的相關tlb。這裏vcpu可以做帶VMID/ASID的DVM, 直接無效化相關的tlb。

  1. virtio iommu

以上的分析都是基於nested IOMMU/SMMU的方案。目前Jean在做virtio iommu的方案。
這個方案在qemu裏實現一個virtio iommu的虛擬設備qemu/hw/virtio/virtio-iommu.c,
虛擬機內核裏的drivers/iommu/virtio-iommu.c驅動這個虛擬設備,現在看來這個是
用純軟件實現VA->IPA的映射。

基於以上的分析,可以基於vfio接口在virtio iommu裏實現有物理SMMU支持的virtio-iommu。
但是,這個需要virtio-iommu協議的支持。目前,Jean在搞virt-iommu的協議
jpbrucker.net/virtio-iommu/spec, 目前看virtio iommu spec中PASID/fault的支持
還不完善。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章