欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

address_space_init源码分析(GPA的生成)

程序员文章站 2024-02-27 13:06:39
...

参考博客https://www.cnblogs.com/ccxikka/p/9477530.html

目的原本AS是树状结构通过该方式将其展开成平面结构,最终得到的FlatView相当于一个内存条

 最终生成的结构体间关系如下图所示

address_space_init源码分析(GPA的生成)

 具体实现步骤分析:

//exec.c中memory_map_init函数
static void memory_map_init(void)
{
    system_memory = g_malloc(sizeof(*system_memory));//动态分配system_memory这memory_region
    memory_region_init(system_memory, NULL, "system", UINT64_MAX);//创建system_memory的qom
    address_space_init(&address_space_memory, system_memory, "memory");//地址空间初始化
    system_io = g_malloc(sizeof(*system_io));
    memory_region_init_io(system_io, NULL, &unassigned_io_ops, NULL, "io",
                          65536);
    address_space_init(&address_space_io, system_io, "I/O");
}

 地址空间即CPU所能看到的空间,包括Io空间和memory空间,IO空间使用in、out指令访问,有回掉函数。Memory空间使用mov等指令访问。

void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
{
    memory_region_ref(root);
    as->root = root;                      //指向system_meomory这个memory region
    as->current_map = NULL;
    as->ioeventfd_nb = 0;
    as->ioeventfds = NULL;
    QTAILQ_INIT(&as->listeners);
    QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
    as->name = g_strdup(name ? name : "anonymous");
    address_space_update_topology(as);    //完成内存空间的渲染使映射到GPA
    address_space_update_ioeventfds(as);
}
static void address_space_update_topology(AddressSpace *as)
{
    MemoryRegion *physmr = memory_region_get_flatview_root(as->root);//获取as指向的mr

    flatviews_init();
    if (!g_hash_table_lookup(flat_views, physmr)) {
        generate_memory_topology(physmr);//主要解析这个
    }
    address_space_set_flatview(as);
}

 

static FlatView *generate_memory_topology(MemoryRegion *mr)
{
    int i;
    FlatView *view;

    view = flatview_new(mr);

    if (mr) {
        render_memory_region(view, mr, int128_zero(),
                             addrrange_make(int128_zero(), int128_2_64()), false);
    }
    flatview_simplify(view);

    view->dispatch = address_space_dispatch_new(view);
    for (i = 0; i < view->nr; i++) {
        MemoryRegionSection mrs =
            section_from_flat_range(&view->ranges[i], view);
        flatview_add_to_dispatch(view, &mrs);
    }
    address_space_dispatch_compact(view->dispatch);
    g_hash_table_replace(flat_views, mr, view);

    return view;
}
static void render_memory_region(FlatView *view,
                                 MemoryRegion *mr,
                                 Int128 base,
                                 AddrRange clip,
                                 bool readonly)
{
    MemoryRegion *subregion;
    unsigned i;
    hwaddr offset_in_region;
    Int128 remain;
    Int128 now;
    FlatRange fr;
    AddrRange tmp;

    if (!mr->enabled) {
        return;
    }

    int128_addto(&base, int128_make64(mr->addr));//base=base+mr->addr
    readonly |= mr->readonly;                    //它的读写模式就是mr的读写模式
    //找出当前的mr落在父mr的地址区间
    tmp = addrrange_make(base, mr->size);        //返回base以及大小即start&size
    if (!addrrange_intersects(tmp, clip)) {      //计算结果true因此不执行这里。继续向下执行
        return;
    }

    clip = addrrange_intersection(tmp, clip);//结果为start=0,size=0xffffffffffffffffui64
    //对别名空间进行渲染
    if (mr->alias) {
        int128_subfrom(&base, int128_make64(mr->alias->addr));
        int128_subfrom(&base, int128_make64(mr->alias_offset));//以上两行的计算得出别名空间的大小
        render_memory_region(view, mr->alias, base, clip, readonly);//渲染别名空间
        return;
    }
    //渲染子region
    /* Render subregions in priority order. */
    QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
        render_memory_region(view, subregion, base, clip, readonly);
    }
    //teminates为false表示该容器为纯容器只需要渲染不需要生成flatrange
    if (!mr->terminates) {
        return;
    }
    //计算Mr在线性空间的大小和偏移
    offset_in_region = int128_get64(int128_sub(clip.start, base));//返回结果为0
    base = clip.start;//为0
    remain = clip.size;//为0xffffffffffffffffui64
    //Flatrange成员的初始化
    fr.mr = mr;
    fr.dirty_log_mask = memory_region_get_dirty_log_mask(mr);
    fr.romd_mode = mr->romd_mode;
    fr.readonly = readonly;
    //flatview的nr什么时候初始化?
    /* Render the region itself into any gaps left by the current view. */
    for (i = 0; i < view->nr && int128_nz(remain); ++i) {
        if (int128_ge(base, addrrange_end(view->ranges[i].addr))) {
            continue;
        }
        if (int128_lt(base, view->ranges[i].addr.start)) {
            now = int128_min(remain,   //找出两个中小的赋值给now
                             int128_sub(view->ranges[i].addr.start, base));
            fr.offset_in_region = offset_in_region;
            fr.addr = addrrange_make(base, now);  //完成fr的addrfange的赋值
            flatview_insert(view, i, &fr);
            ++i;
            int128_addto(&base, now);
            offset_in_region += int128_get64(now);
            int128_subfrom(&remain, now);
        }
        now = int128_sub(int128_min(int128_add(base, remain),
                                    addrrange_end(view->ranges[i].addr)),
                         base);
        int128_addto(&base, now);
        offset_in_region += int128_get64(now);
        int128_subfrom(&remain, now);
    }
    if (int128_nz(remain)) {
        fr.offset_in_region = offset_in_region;
        fr.addr = addrrange_make(base, remain);
        flatview_insert(view, i, &fr);
    }
}

 

相关标签: qemu学习