hva的創建過程

 其創建流程如下圖所示:

 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在進程中創建內存。

 

 

 

 

發佈了32 篇原創文章 · 獲贊 5 · 訪問量 2597
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章