0
点赞
收藏
分享

微信扫一扫

Qemu源码分析(10)—Apple的学习笔记

IT影子 2023-10-03 阅读 40

一,前言

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);
}

  1. 主要的类对象

Qemu源码分析(10)—Apple的学习笔记_qemu

三,小结

这个内容还是很多的,我主要看了开头,也就是MCU是怎么添加内存定义的一些高层级的API,及通过网上找到了些资料来了解映射机制。

举报

相关推荐

0 条评论