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