一,前言
Qemu的虚化主要包括cpu虚化,内存虚化,io虚化。而且3类虚化都包括了全虚化,半虚化和硬件虚化,这些也是网上看到的,大概了解了下。而我本节看qemu源码主要分析内存虚化,至于内存应该是硬件虚化,也就是多用了也EPT扩展页表,这是内核kvm中的代码不是qemu的代码了,不是我现在关注的内容。
二,分析
Qemu主要是创建内存mapping信息,转换关系应该是GVA->IVA->HPA(客户端物理地址->内部虚拟地址->主机物理地址)若用全虚化,需要用到影子表页,GVA->GPA->HVA->HGA,这样速度就很慢。
1. 初始化memeoryRegion对象,包括内存和io设备,对象名字为system和io,分别再为其设置AddressSpace对象名字分别为memory和I/O。这4个都是全局变量,而且都有链表,所以之后就会在链表后继续添加对象。
static
void memory_map_init(void)
{
system_memory =
g_malloc(sizeof(*system_memory));
memory_region_init(system_memory, NULL,
"system", UINT64_MAX);
address_space_init(&address_space_memory, system_memory,
"memory");
system_io = g_malloc(sizeof(*system_io));
memory_region_init_io(system_io, NULL,
&unassigned_io_ops, NULL, "io",
65536);
address_space_init(&address_space_io,
system_io, "I/O");
}
2.Mcu中内存的创建,先通过memory_region_init_ram进行初始化,然后通过memory_region_add_subregion将对象/memory添加到了内存的root对象system下。vmstate_register_ram_global是在ramblock对象中创建idstr名字。
// Get the system memory region, it must
start at 0.
MemoryRegion *system_memory =
get_system_memory();
int flash_size = cm_state->flash_size_kb
* 1024;
int sram_size = cm_state->sram_size_kb *
1024;
Object *mem_container =
container_get(cm_state->container, "/memory");
MemoryRegion *flash_mem =
&cm_state->flash_mem;
// Flash programming is done via the SCU,
so pretend it is ROM.
memory_region_init_ram(flash_mem,
mem_container, "flash", flash_size,
&error_fatal);
vmstate_register_ram_global(flash_mem);
memory_region_set_readonly(flash_mem,
true);
memory_region_add_subregion(system_memory, 0x00000000, flash_mem);
3.关于memory_region_transaction_begin和memory_region_transaction_commit,只要操作memoryRegion对象就有这2个函数,我没细看代码,直接网上搜索了,主要是region中物理地址更新及进行KVM地址同步。address_space_update_topology函数主要就是将nr指向FlatView,也就是实现GHA->GPA,GPA就是RamBlock对象的list。memory_listener_register用来监听地址空间发送变化,就调用listener的相应函数。从而保持内核和用户空间的内存信息一致性。
4.最后ram的更新都会传给kvm,主要通过此函数的ioctl,KVM_SET_USER_MEMORY_REGION来进行关联,接着就是GPA->HVA。
static int
kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot)
{
KVMState *s = kvm_state;
struct kvm_userspace_memory_region mem;
mem.slot = slot->slot | (kml->as_id
<< 16);
mem.guest_phys_addr = slot->start_addr;
mem.userspace_addr = (unsigned
long)slot->ram;
mem.flags = slot->flags;
if (slot->memory_size &&
mem.flags & KVM_MEM_READONLY) {
/* Set the slot size to 0 before
setting the slot to the desired
* value. This is needed based on KVM
commit 75d61fbc. */
mem.memory_size = 0;
kvm_vm_ioctl(s,
KVM_SET_USER_MEMORY_REGION, &mem);
}
mem.memory_size = slot->memory_size;
return kvm_vm_ioctl(s,
KVM_SET_USER_MEMORY_REGION, &mem);
}
- 主要的类对象
三,小结
这个内容还是很多的,我主要看了开头,也就是MCU是怎么添加内存定义的一些高层级的API,及通过网上找到了些资料来了解映射机制。
标签:10,Apple,mem,region,system,源码,io,memory,虚化 From: https://blog.51cto.com/u_16247275/7694211