address_space_init源码分析(GPA的生成)
程序员文章站
2024-02-27 13:06:39
...
参考博客https://www.cnblogs.com/ccxikka/p/9477530.html
目的原本AS是树状结构通过该方式将其展开成平面结构,最终得到的FlatView相当于一个内存条
最终生成的结构体间关系如下图所示
具体实现步骤分析:
//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);
}
}
上一篇: 关于前导零和内外码的转换的机制
下一篇: 正则表达式的总结
推荐阅读
-
address_space_init源码分析(GPA的生成)
-
模仿Spring事件机制实现自定义事件驱动编程--Spring的事件机制源码分析(一)
-
通过源码分析Python中的切片赋值
-
Android Glide 基于4.8.0的源码分析
-
使用maven 如何生成源代码的jar包 博客分类: Java WebJava maven打包源码打包源代码sourcejarsources.jar
-
使用maven 如何生成源代码的jar包 博客分类: Java WebJava maven打包源码打包源代码sourcejarsources.jar
-
简略分析Android的Retrofit应用开发框架源码
-
从源码分析Android的Volley库的工作流程
-
shuffle的关键阶段sort(Map端和Reduce端)源码分析
-
Java 中的FileReader和FileWriter源码分析_动力节点Java学院整理