hva的创建过程

眉间皱痕 提交于 2020-02-15 08:28:16

 其创建流程如下图所示:

 ppc架构的处理器的在mac_newworld.c文件中ppc_core99_init函数中调用memory_region_allocate_system_memory函数创建ram,ram属于实体MemoryRegion,有自己的内存(从QEMU进程的中分配内存空间)。源代码分析如下:

memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
                                          const char *name,
                                          uint64_t ram_size)
{
    uint64_t addr = 0;
    int i;

    if (nb_numa_nodes == 0 || !have_memdevs) {
        allocate_system_memory_nonnuma(mr, owner, name, ram_size);//hva内存的创建通过该函数完 
                                                           //成,对于其它代码不做解析
        return;
    }
    ……
}

 在下面函数中可以从文件恢复hva内存,也可以直接分配hva内存,memory_region_init_ram_from_file函数用于从文件恢复,而memory_region_init_ram_nomigrate用于分配内存。

static void allocate_system_memory_nonnuma(MemoryRegion *mr, Object *owner,
                                           const char *name,
                                           uint64_t ram_size)
{
    if (mem_path) {
#ifdef __linux__
        Error *err = NULL;
        memory_region_init_ram_from_file(mr, owner, name, ram_size, 0, 0,
                                         mem_path, &err);  //从文件中恢复hva
        if (err) {
            error_report_err(err);
            if (mem_prealloc) {
                exit(1);
            }
            error_report("falling back to regular RAM allocation.");

            /* Legacy behavior: if allocation failed, fall back to
             * regular RAM allocation.
             */
            mem_path = NULL;
            memory_region_init_ram_nomigrate(mr, owner, name, ram_size, &error_fatal);
        }
#else
        fprintf(stderr, "-mem-path not supported on this host\n");
        exit(1);
#endif
    } 
   else 
    {
  memory_region_init_ram_nomigrate(mr, owner, name, ram_size, &error_fatal);//分配hva内存
    }
    vmstate_register_ram_global(mr);
}

 以下主要分析memory_region_init_ram_nomigrate函数分配内存

void memory_region_init_ram_nomigrate(MemoryRegion *mr,
                                      Object *owner,
                                      const char *name,
                                      uint64_t size,
                                      Error **errp)
{
    memory_region_init_ram_shared_nomigrate(mr, owner, name, size, false, errp);
}
void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr,
                                             Object *owner,
                                             const char *name,
                                             uint64_t size,
                                             bool share,
                                             Error **errp)
{
    Error *err = NULL;
    memory_region_init(mr, owner, name, size);//创建RAM的memoryregion(QOM的创建过程)
    mr->ram = true;                           //完成MemoryRegion的成员变量的初始化
    mr->terminates = true;
    mr->destructor = memory_region_destructor_ram;
    mr->ram_block = qemu_ram_alloc(size, share, mr, &err);//hva内存的分配通过该函数完成
    mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
    if (err) {
        mr->size = int128_zero();
        object_unparent(OBJECT(mr));
        error_propagate(errp, err);
    }
}
RAMBlock *qemu_ram_alloc(ram_addr_t size, bool share,
                         MemoryRegion *mr, Error **errp)
{
    return qemu_ram_alloc_internal(size, size, NULL, NULL, false,
                                   share, mr, errp);
}

 创建RamBlock,并完成Ram的MemoryRegion与RamBlock的连接

static
RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
                                  void (*resized)(const char*,
                                                  uint64_t length,
                                                  void *host),
                                  void *host, bool resizeable, bool share,
                                  MemoryRegion *mr, Error **errp)
{
    RAMBlock *new_block;
    Error *local_err = NULL;

    size = HOST_PAGE_ALIGN(size);
    max_size = HOST_PAGE_ALIGN(max_size);
    new_block = g_malloc0(sizeof(*new_block));//动态创建RAMBlock
    new_block->mr = mr;                       //完成各个元素的初始化
    new_block->resized = resized;
    new_block->used_length = size;
    new_block->max_length = max_size;
    assert(max_size >= size);
    new_block->fd = -1;
    new_block->page_size = getpagesize();    //获取系统的页大小
    new_block->host = host;
    if (host) {
        new_block->flags |= RAM_PREALLOC;
    }
    if (resizeable) {
        new_block->flags |= RAM_RESIZEABLE;
    }
    ram_block_add(new_block, &local_err, share);//通过该函数完成hva的分配
    if (local_err) {
        g_free(new_block);
        error_propagate(errp, local_err);
        return NULL;
    }
    return new_block;
}
static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared)
{
    RAMBlock *block;
    RAMBlock *last_block = NULL;
    ram_addr_t old_ram_size, new_ram_size;
    Error *err = NULL;

    old_ram_size = last_ram_page();

    qemu_mutex_lock_ramlist();
    new_block->offset = find_ram_offset(new_block->max_length);

    if (!new_block->host) {
        if (xen_enabled()) {
            xen_ram_alloc(new_block->offset, new_block->max_length,
                          new_block->mr, &err);
            if (err) {
                error_propagate(errp, err);
                qemu_mutex_unlock_ramlist();
                return;
            }
        } else {
            new_block->host = phys_mem_alloc(new_block->max_length,
                                             &new_block->mr->align, shared);//该函数完成 
                                                            //hva的创建
    ……
}

 phys_mem_alloc函数在exec.c文件中指向qemu_anon_ram_alloc函数,该函数调用系统函数VirtualAlloc在进程中创建内存。

 

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!