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