QEMU global var ``system_memory`` ================================= source code:: ./exec.c ./memory.c global variable:: 1. static MemoryRegion *system_memory; 2. AddressSpace address_space_memory; extern AddressSpace address_space_memory; // in include/exec/address-spaces.h 3. static QTAILQ_HEAD(, AddressSpace) address_spaces = QTAILQ_HEAD_INITIALIZER(address_spaces); set value:: // 1. system_memory && 2. address_space_memory 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"); } // 3. address_spaces // 當 AddressSpace 使用 address_space_init() 初始化自己時, 就會順便把自己放入 address_spaces 這個 Tail Queue 當中 void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name){ // init code of as // as->(root, name) = (root, name) // as->current_map; g_new() + flatview_init() // ... // insert as to Tail Queue address_spaces QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); memory_region_update_pending |= root->enabled; memory_region_transaction_commit(); } AddressSpace *address_space_init_shareable(MemoryRegion *root, const char *name); void address_space_destroy(AddressSpace *as): get value:: // 1. system_memory MemoryRegion *get_system_memory(void){ return system_memory; } void cpu_exec_init(CPUState *cpu, Error **errp){ cpu->memory = system_memory; } // 2. address_space_memory void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, int len, int is_write){ address_space_rw(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED, buf, len, is_write); } void cpu_flush_icache_range(hwaddr start, int len); // calls cpu_physical_memory_write_rom_internal() cpu_physical_memory_map()/cpu_physical_memory_unmap(): address_space_map/unmap(&address_space_memory) bool cpu_physical_memory_is_io(hwaddr phys_addr){ MemoryRegion mr = address_space_translate(&address_space_memory, phys_addr, &phys_addr, &l, false); return !(memory_region_is_ram(mr) || memory_region_is_romd(mr)); } // 看起來操作 address_space_memory 的函式, 基本上都是操作 struct AddressSpace 的函式的再包裝, 而且大部份都有使用 // AddressSpace to MemoryRegion 的 API: address_space_translate() // 3. address_spaces // QTAILQ_FOREACH + address_spaces static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) void memory_region_transaction_commit(void); void memory_region_sync_dirty_bitmap(MemoryRegion *mr); static void memory_region_update_coalesced_range(MemoryRegion *mr); void memory_listener_register(MemoryListener *listener, AddressSpace *filter); void mtree_info(fprintf_function mon_printf, void *f); // 4. struct AddressSpace API Misc ---- - address_space_memory: 是系統 memory 用的 AddressSpace - address_space_rw() parameter: 當 MMIO 發生時, 會從 address_space_memory 搜尋對應的 MemoryRegion - system_memory: 是系統 memory 的 root MemoryRegion - memory_region_add_subregion_*() parameter: device 產生 MMIO 的 MemoryRegion, 會放入 system_memory 當中 - address_spaces: 是所有 AddressSpace 的集合, 包含 address_space_memory - address_space_init(): 當 AddressSpace init 時, 就會被放入 address_spaces. - memory_region_to_address_space(): 尋找 MemoryRegion 隸屬的 AddressSpace, 會從 address_spaces 做搜尋. - memory_listeners