其創建流程如下圖所示:
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在進程中創建內存。