- x86的内存虚拟化支持
x86 的 内存虚拟化支持
1. 第一代
GVA->GPA 利用 MMU 访问 guest OS 中的 页表(GPT)
GPA->HVA 利用 host os 中的 软件代码 访问 host OS 中的 kvm_memory_slot
HVA->HPA 利用 MMU 访问 hostOS中虚拟机进程的 页表(HPT)
2. 第二代 : 影子页表(SPT)
GVA->HPA 利用 host OS 中的软件代码 访问 host OS 中的影子页表(SPT)
3. 第三代
GVA->GPA 利用 MMU 访问 guest OS 中的 页表(GPT)
GPA->HPA 利用 MMU 访问 hostOS中的专门为虚拟机做的 页表(EPT)
ARMv7 的 内存虚拟化支持
1. 第一代
GVA->GPA 利用 MMU 访问 guest OS 中的 页表A
GPA->HPA 利用 Second-stage of translation 机制 访问 hostOS中的专门为虚拟机做的 页表B
// 页表格式 和 GVA->GPA 页表不同
// GPA 在 ARM 中被称为 IPA
// 建立的过程 是 在 user_mem_fault 中
// 建立 是 解析了 memslot 找到了 IPA 与 HVA的关系 , 并通过 host 中的页表C 找到了 HVA 与 HPA 的关系 , 从而建立了 IPA 与 HPA 的关系(页表B)
ARM内存地址转换
为什么需要内存地址转换
实体机是这样子跑的
host_VA -> host_PA
虚拟机是这样跑
guest_VA -> guest_PA //guest_PA 在 arm 手册中被称为 IPA ,在 kvm 代码中也被称为fault_ipa // guest_PA 与 host_VA 一一对应
guest_PA -> host_PA
ARM提供了对虚拟物理内存的硬件支持。
通过 二级地址转换(遍历二级页表) 提供的 // 二级转换可以在HYP模式中被禁止或使能。
二级地址机制 的原理 (以虚拟机运行时为例)
虚拟机管理的物理地址实际是中间物理地址(IPA),也被称作客户物理地址。// 客户物理地址 需要被转换成实际物理地址,即主机物理地址。
ARM提供了 二级页表,根据客户物理地址将IPA转换成PA
二级页表机制的限制与特点
二级页表使用ARM的新的LPAE页表格式,与内核模式使用的页表格式略有不同
二级地址转换只能在HYP模式下进行配置,它的使用对虚拟机时透明的。
二级地址机制 的应用
当实体机运行时
二级地址转换 是关闭的 // vm exit 时 关闭
当虚拟机运行时
二级地址转换 是开启的 // vm entry 时 开启
二级页表的地址被写入 基寄存器(VTTBR) // vm entry 时 写入
highvisor管理二级转换页表,只允许访问专门为一个虚拟机配置的内存;其他的访问操作将导致二级页错误,该错误将被hypervisor捕获。
这种机制确保一个虚拟机不能访问属于hypervisor或其他虚拟机的内存和任何敏感数据。
内存异常
TODO
缺页异常
MMU异常
内存不够怎么向host索取
虚拟机是一个进程,那么虚拟机内存的物理内存也是 malloc 申请出来的, 用到了 才会分配给虚拟机
内存分配
KVM/ARM 利用现有的内核内存分配、页引用计数和页表操作的代码。
KVM/ARM通过判定IPA的错误来处理二级页错误,如果出错的地址属于虚拟机内存映射中的正常内存,KVM/ARM只需调用现有的内核函数,如get_user_pages来为虚拟机分配一页,同时将该分配的页映射到虚拟机的二级页表中。
ARMv7 手册
DDI0406C_D_armv7_AR_architecture_reference_manual.pdf 中 P1346
Stage 1 translations
Non-secure PL1&0 stage 1 translation
// host linux 用户态和 内核态(不包括hyp mode) 下的内存访问
// guest linux 用户态 和 内核态的内存访问(不包括hyp mode) // 现在不考虑嵌套虚拟化
The stage 1 translation for memory accesses from Non-secure modes other than Hyp
mode. In an implementation that includes the Virtualization Extensions, this translates
a VA to an IPA, otherwise it translates a VA to a PA. For this translation:
• Non-secure TTBR0 or TTBR1 holds the translation table base address.
• Non-secure TTBCR determines which TTBR is used.
• The input address range is up to 32 bits, as determined by either:
— TTBCR.T0SZ or TTBCR.T1SZ, for a PL1&0 stage 1 translation.
— HTCR.T0SZ, for a PL2 stage 1 translation.
• The output address range is 40 bits.
Non-secure PL2 stage 1 translation
// host linux hyp mode 下的内存访问
The stage 1 translation for memory accesses from Hyp mode. Supported only if the
implementation includes the Virtualization Extensions, and translates a VA to a PA. For
this translation, HTTBR holds the translation table base address.
• The input address range is up to 32 bits, as determined by either:
— TTBCR.T0SZ or TTBCR.T1SZ, for a PL1&0 stage 1 translation.
— HTCR.T0SZ, for a PL2 stage 1 translation.
• The output address range is 40 bits.
Stage 2 translation
Non-secure PL1&0 stage 2 translation
// guest linux 用户态 和 内核态的内存访问
The stage 2 translation for memory accesses from Non-secure modes other than Hyp
mode. Supported only if the implementation includes the Virtualization Extensions, and
translates an IPA to a PA. For this translation:
• The input address range is 40 bits, as determined by VTCR.T0SZ.
• The output address range depends on the implemented memory system, and is up
to 40 bits.
• VTTBR holds the translation table base address.
• VTCR specifies the required input address range, and whether the first lookup is
at the first level or at the second level.
综上
host 下的内存访问 有两个页表基址
TTBR0或TTBR1 用于 内核态与用户态下的内存访问第一步,共一步 , 里面有 HVA -> HPA 的 映射关系
HTTBR 用于 hyp mode 下的 内存访问
guest 下的内存访问 有 2个 页表基址
TTBR0或TTBR1 用于 内核态与用户态下的内存访问第一步,共两步 , 里面有 GVA -> GPA 的 映射关系
VTTBR 用于 内核态与用户态下的内存访问第二步,共两步 , 里面有 GPA -> HPA 的 映射关系
---
host linux 本身要维护
TTBR0或TTBR1 及 内核 及各个进程的页目录表(页表)
如果添上虚拟机,则需要添加
1. host 设置 虚拟机进程的 TTBR0或TTBR1 及 其中的 页目录表基址 和 相应的页表 // 对应B
2. host 设置 HTTBR 及 HTTBR 中的页目录表基址 和 相应的页表 // 对应A
3. host 设置 虚拟机进程所需要的 VTTBR 及 其中的 页目录表基址 和 相应的页表 // 对应D
4. guest 设置 自身用到 的 TTBR0或TTBR1 及 其中的 页目录表基址 和 相应的页表 // 对应C
- 内存访存流程伪代码
if (in host hyp mode){
search table base addr in HTTBR & Start MMU memory access process // A
}else if (in host other mode){
search table base addr in TTBR0/TTBR1 & Start MMU memory access process // B
}else if (in guest hyp mode){
... // TODO
}else if (in guest other mode){
search table base addr in TTBR0/TTBR1 & Start MMU memory access process // C
search table base addr in VTTBR & Start MMU memory access process // D
}