ARM GIC 虛擬化學習筆記【轉】

轉自:https://stdrc.cc/post/2020/09/26/arm-gic-virtualization/

這是一篇學習過程中的筆記,因爲時間原因不再組織成流暢的語言,而是直接分享了~

References

GICv2

Non-virtualization

  • 中斷進入 distributor,然後分發到 CPU interface
  • 某個 CPU 觸發中斷後,讀 GICC_IAR 拿到中斷信息,處理完後寫 GICC_EOIR 和 GICC_DIR(如果 GICC_CTLR.EOImodeNS 是 0,則 EOI 的同時也會 DI)
  • GICD、GICC 寄存器都是 MMIO 的,device tree 中會給出物理地址

Virtualization

  • HCR_EL2.IMO 設置爲 1 後,所有 IRQ 都會 trap 到 HYP
  • HYP 判斷該 IRQ 是否需要插入到 vCPU
  • 插入 vIRQ 之後,在切換到 VM 之前需要 EOI 物理 IRQ,即 priority drop,降低運行優先級,使之後 VM 運行時能夠再次觸發該中斷
  • 回到 VM 後,GIC 在 EL1 觸發 vIRQ,這時候 EOI 和 DI 會把 vIRQ 和物理 IRQ 都 deactivate,因此不需要再 trap 到 HYP,不過如果是 SGI 的話並不會 deactivate,需要 HYP 自己處理(通過 maintenance 中斷?)

HYP interface (GICH)

  • GICH base 物理地址在 device tree 中給出
  • 控制寄存器:GICH_HCR、GICH_VMCR 等
  • List 寄存器:GICH_LRn
  • KVM 中,這些寄存器保存在 struct vgic_cpu 的 vgic_v2 字段,struct vgic_cpu 本身放在 struct kvm_vcpu_arch,每個 vCPU 一份
  • vCPU switch 的時候,需要切換這些寄存器(KVM 在 vgic-v2-switch.S 中定義相關切換函數)
  • VM 無法訪問 GICH 寄存器,因爲根本沒有映射

List register (LR)

vCPU interface (GICV, GICC in VM's view)

  • GICV 也是物理 GIC 上存在的,base 物理地址同樣在 device tree 中給出
  • KVM 在系統全局的一個結構體(struct vgic_params vgic_v2_params)保存了這個物理地址
  • 創建 VM 時 HYP 把一個特定的 GPA(KVM 中通過 ioctl 設置該地址)映射到 GICV base 物理地址,然後把這個 GPA 作爲 GICC base 在 device tree 中傳給 VM
  • VM 以爲自己在訪問 GICC,實際上它在訪問 GICV
  • 目前理解這些 GICV 寄存器在 vCPU switch 的時候是不需要保存的(KVM 裏沒有保存 GICV 相關的代碼),因爲它其實在硬件裏訪問的是 GICH 配置的那些寄存器,比如 LR

Virtual distributor (GICD in VM's view)

  • 實際是內核裏的一個結構體(struct vgic_dist
  • 在 device tree 中給 VM 一個 GICD base,但實際上沒有映射
  • VM 訪問 GICD 時,trap & emulate,直接返回或設置 struct vgic_dist 裏的字段(在 vgic-v2-emul.c 文件中)
  • 每個 VM 一個,而不是每個 vCPU 一個,所以 struct vgic_dist 放在 struct kvm_arch 裏

VM's view

  • 從 device tree 獲得 GICD、GICC base 物理地址(實際是 HYP 僞造的地址)
  • 配置 GICD 寄存器(實際上 trap 到 HYP,模擬地讀寫了內核某 struct 裏的數據)
  • 執行直到發生中斷(中斷先到 HYP,HYP 在 LR 中配置了一個物理 IRQ 到 vIRQ 的映射,並且設置爲 pending,回到 VM 之後 GIC 在 VM 的 EL1 觸發中斷)
  • 讀 GICC_IAR(經過 stage 2 頁表翻譯,實際上讀了 GICV_IAR,GIC 根據 LR 返回 vIRQ 的信息,vIRQ 狀態從 pending 轉爲 active)
  • 寫 GICC_EOIR、GICC_DIR(經過 stage 2 頁表翻譯,實際上寫了 GICV_EOIR、GICV_DIR,GIC EOI 並 deactivate 對應的 vIRQ,並 deactivate vIRQ 對應的物理 IRQ)

GICv3

新特性:

  • CPU interface(GICC、GICH、GICV)通過 system register 訪問(ICC_*_ELnICH_*_EL2ICV_*_ELn,ICC 和 ICV 在指令中的編碼相同,硬件根據當前 EL 和 HCR_EL2 來路由),不再用 MMIO
  • 使用 affinity routing,支持最多 2^32 個 CPU 核心
  • 引入 redistributor,每個 CPU 一個,和各 CPU interface 連接,使 PPI 不再需要進入 distributor
  • 引入一種新的中斷類型 LPI 和一個新的組件 ITS(還沒太看懂是幹啥用的)

Non-virtualization

Virtualization

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