其创建流程如下图所示:
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在进程中创建内存。
来源:CSDN
作者:cangcun
链接:https://blog.csdn.net/sinat_38205774/article/details/104301375