接前一篇文章: QEMU源码全解析 —— 内存虚拟化(9)
本文内容参考:
《 QEMU /KVM源码解析与应用》 —— 李强,机械工业出版社
浅谈QEMU Memory Region 与 Address Space
特此致谢!
2. QEMU虚拟机内存初始化
上一回沿着以下代码路径:
qemu_init()
---> qemu_create_machine()
---> cpu_exec_init_all()
---> memory_map_init()
---> address_space_init()
---> address_space_update_topology()
串讲了一遍cpu_exec_init_all()的流程。但是其中还有一些内容讲得并不细致、有些甚至没有讲到,本回就对这些内容进行精讲。
首当其冲地,要讲一下地址空间(AddressSpace)中与树形结构(MemoryRegion)并列的“平面”结构(FlatView)两者之间的转换,也可以说是讲一下虚拟机内存平坦化过程。
前文提到过,之所以要有两种表示同一事物的结构是因为:
树形内存结构更便于管理;而平的内存结构则更方便与内核通信,以请求物理内存。虽然操作系统内核中也是使用树形结构来表示内存区域的,但是用户态向内核申请内存的时候,会按照平的、连续的模式进行申请。由于QEMU在用户态,因此需要做这样一个转换。
QEMU中的ioctl(KVM_SET_USER_MEMORY_REGION)接口(参见accel/kvm/kvm-all.c的kvm_set_user_memory_region函数中的代码:kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);)用来设置QEMU虚拟地址与虚拟机物理地址的对应关系,这是平坦的。但是,QEMU是以AddressSpace根MemoryRegion为起始的树状结构表示虚拟机的内存的。这就需要将树状结构转换为平坦结构,即虚拟机内存的平坦化。
虚拟机内存的平坦化过程指的是,将AddressSpace根MemoryRegion表示的树形虚拟机内存地址空间转换成一个平坦的线性地址空间。每一段线性地址空间的属性与其所属的MemoryRegion都一致,每一段线性地址空间与虚拟机的物理地址空间都相互关联。
虚拟机内存的平坦化以AddressSpace为单位,也就是以AddressSpace的根MemoryRegion为起点,将其所表示的内存拓扑的无环图结构变为平坦模式。表示虚拟机平坦内存的数据结构已经提到过多次了,是FlatView;相关函数是前文书提到过的generate_memory_topology(参见 QEMU源码全解析 —— 内存虚拟化(8)-CSDN博客 )。
FlatView结构的定义在include/exec/memory.h中,如下:
/* Flattened global view of current active memory hierarchy. Kept in sorted
* order.
*/
struct FlatView {
struct rcu_head rcu;
unsigned ref;
FlatRange *ranges;
unsigned nr;
unsigned nr_allocated;
struct AddressSpaceDispatch *dispatch;
MemoryRegion *root;
};
更多内容请看下回。