文章目录
- QEMU 内存管理(QEMU 如何管理某个特定 VM 的内存)
- MemoryRegion gpa->hpa
- FlatView:表示MR 树对应的地址空间
- FlatRange:存储不同MR对应的地址信息
- AddressSpace:不同类型的 MemoryRegion树
- RAMBlock
- 总体简化图
- QEMU 设备模拟 (QEMU的模拟IO设备如何与VM交互)
- QEMU 设备 IO 处理
QEMU 内存管理(QEMU 如何管理某个特定 VM 的内存)
QEMU:能够完成gva-gpa=hva-hpa地址的转换
MemoryRegion gpa->hpa
QEMU通过MemoryRegion管理虚拟机内存,每个MemoryRegion对应虚拟机一部分内存,同时还有相关对应Host的虚拟内存相关信息。不同MemoryRegion通过树状组织连接起来,连接到根MemoryRegion下,不同MemoyRegion树代表不同作用的内存,如系统内存空间(system_memorry)或IO内存空间(system_io)
MemoryRegion可以分为以下三种类型
- 根级MemoryRegion:通过memory_region_init初始化,只是个管理用的(如system_memory),没有自已对应的部分内存
- 实体MemoryRegion:通过memory_region_init_ram初始化,有对应的内存,大小为size
- 别名 MemoryRegion:通过 memory_region_init_alias 初始化,没有自己对应的内存,作为一个实体的别名存在,通过alias成员指向对应的实体,alias_offset代表该别名MemoryRegion所代表内存起始GPA相对于实体 MemoryRegion 所代表内存起始GPA的偏移量
FlatView:表示MR 树对应的地址空间
struct FlatView {
struct rcu_head rcu;
unsigned ref;
FlatRange *ranges;
unsigned nr;
unsigned nr_allocated;
struct AddressSpaceDispatch *dispatch;
MemoryRegion *root;
};
FlatRange:存储不同MR对应的地址信息
struct FlatRange {
MemoryRegion *mr;
hwaddr offset_in_region;
AddrRange addr;
uint8_t dirty_log_mask;
bool romd_mode;
bool readonly;
bool nonvolatile;
};
AddressSpace:不同类型的 MemoryRegion树
两种,为address_space_memory 与 address_space_io
/**
* struct AddressSpace: describes a mapping of addresses to #MemoryRegion objects
*/
struct AddressSpace {
/* private: */
struct rcu_head rcu;
char *name;
MemoryRegion *root; //是对应树的根
/* Accessed via RCU. */
struct FlatView *current_map; //对对应树的地址空间表示
int ioeventfd_nb;
struct MemoryRegionIoeventfd *ioeventfds;
QTAILQ_HEAD(, MemoryListener) listeners;
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
};
RAMBlock
MR 对应的 Host 虚拟内存,每个RAMBlock表示单个实体MemoryRegion所占的Host虚拟内存信息,多个RAMBlock构成RAMList
每个RAMBlock都有一个唯一的MemoryRegion对应
总体简化图
大佬勿喷,后续学的更深会完善
QEMU 设备模拟 (QEMU的模拟IO设备如何与VM交互)
QEMU 在用户空间中独立进行设备模拟,虚拟设备被其他的 VM 通过 VMM 提供的接口进行调用。并且设备的模拟是独立于VMM
QEMU 设备 IO 处理
当VM访问某虚拟设备的物理内存/端口时候,控制权由VM转交到VMM,此时QEMU会根据触发VM-exit的事件类型进行不同的处理,即MMIO还是PMIO。
MMIO:对address_space_memory类的地址空间读写
PMIO: 对address_space_io类的地址空间进行读写