FlatView
FlatView,从字面上看意思就是 扁平视图。那是谁的偏平视图呢?
从大了说是地址空间的偏平视图,但是仔细想想它是对应MemoryRegion的。因为MemoryRegion是一颗树,那相应的就可以有一个偏平空间。
说到这儿,其实已经没有什么花头了。不就是一个偏平视图么?但是为了充数,还是要展开讲讲的。突然想到了《三体》世界中的低纬展开,这个MemoryRegion到FlatView的过程还真有点像。
这个过程在qemu中分成了两步:
generate_memory_topology()
address_space_set_flatview()
后者是将AddressSpace和FlatView进行关联。
而前者的工作又分成两部分:
render_memory_region
flatview_add_to_dispatch
render_memory_region
这个函数的作用就是将树状的MemoryRegion展开成一维的FlatView。
因为确实没啥多说的,还是用张图来表示AddressSpace,MemoryRegion和FlatView之间的关系。
AddressSpace
+-------------------------+
|name |
| (char *) | FlatView (An array of FlatRange)
+-------------------------+ +----------------------+
|current_map | -------->|nr |
| (FlatView *) | |nr_allocated |
+-------------------------+ | (unsigned) | FlatRange FlatRange
| | +----------------------+
| | |ranges | ------> +---------------------+---------------------+
| | | (FlatRange *) | |offset_in_region |offset_in_region |
| | +----------------------+ | (hwaddr) | (hwaddr) |
| | +---------------------+---------------------+
| | |addr(AddrRange) |addr(AddrRange) |
| | | +----------------| +----------------+
| | | |start (Int128) | |start (Int128) |
| | | |size (Int128) | |size (Int128) |
| | +----+----------------+----+----------------+
| | |mr |mr |
| | | (MemoryRegion *) | (MemoryRegion *) |
| | +---------------------+---------------------+
| |
| |
| |
| | MemoryRegion(system_memory/system_io)
+-------------------------+ +----------------------+
|root | | | root of a MemoryRegion
| (MemoryRegion *) | -------->| | tree
+-------------------------+ +----------------------+
在AddressSpace中,root和current_map分别指向了树状的地址空间和对应的一维展开。
至于为什么要使用这样两种数据结构,暂时还不知道这样做的好处。等我想明白了再回来解释。
flatview_add_to_dispatch
这个函数的主要任务就是构建AddressSpaceDispatch这个结构了。让人吃惊的是,这是一个庞然大物。
恐怕大家是要缩小了才能看清楚的吧。
AddressSpaceDispatch
+-------------------------+
|as |
| (AddressSpace *) |
+-------------------------+
|mru_section |
| (MemoryRegionSection*)|
| |
| |
| |
| |
| |
+-------------------------+
|map(PhysPageMap) | MemoryRegionSection[]
| +---------------------+ +---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| |sections |-------->|mr = io_mem_unassigned |mr = io_mem_notdirty |mr = io_mem_rom |mr = io_mem_watch |mr = one mr in tree |mr = subpage_t->iomem |
| | MemoryRegionSection*| | (MemoryRegion *) | (MemoryRegion *) | (MemoryRegion *) | (MemoryRegion *) | (MemoryRegion *) | (MemoryRegion *) |
| | | | | | | | | |
| +---------------------+ +---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| |sections_nb | |fv |fv |fv |fv |fv |fv |
| |sections_nb_alloc | | (FlatView *) | (FlatView *) | (FlatView *) | (FlatView *) | (FlatView *) | (FlatView *) |
| | (unsigned) | +---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| +---------------------+ |size (Int128) |size (Int128) |size (Int128) |size (Int128) |size (Int128) |size (Int128) |
| | | +---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| | | |offset_within_region |offset_within_region |offset_within_region |offset_within_region |offset_within_region |offset_within_region |
| | | | (hwaddr) | (hwaddr) | (hwaddr) | (hwaddr) | (hwaddr) | (hwaddr) |
| | | |offset_within_address_space|offset_within_address_space|offset_within_address_space|offset_within_address_space|offset_within_address_space|offset_within_address_space|
| | | | (hwaddr) GPA | (hwaddr) GPA | (hwaddr) GPA | (hwaddr) GPA | (hwaddr) | (hwaddr) |
| | | +---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+
| | | ^
| | | nodes[1] |
| | | +---->+------------------+ |
| | | | |u32 skip:6 | = 0 |
| | | | |u32 ptr:26 | = 4 -----------------------------------------+
| | | P_L2_LEVELS = 6 | +------------------+
| | | nodes[0] = PhysPageEntry[P_L2_SIZE = 2^9] | | |
| +---------------------+ +------------------+ | | ... |
| |nodes | ------->|u32 skip:6 | = 1 | | |
| | (Node *) | |u32 ptr:26 | = 1 -------------+ +------------------+
| +---------------------+ +------------------+ |u32 skip:6 | = 0
| |nodes_nb | | | |u32 ptr:26 | = PHYS_SECTION_UNASSIGNED
| |nodes_nb_alloc | | ... | +------------------+
| | (unsigned) | | |
| +---------------------+ +------------------+
| | | |u32 skip:6 | = 1
| | | |u32 ptr:26 | = PHYS_MAP_NODE_NIL nodes[2]
| | | +------------------+ +---->+------------------+
| | | |u32 skip:6 | = 1 | |u32 skip:6 |
| | | |u32 ptr:26 | = 2 -------------+ |u32 ptr:26 |
| | | +------------------+ +------------------+
| | | ^ | |
| | | | | ... |
| | | | | |
+---+---------------------+ | +------------------+
|phys_map(PhysPageEntry) | | |u32 skip:6 |
| +---------------------+ | |u32 ptr:26 |
| |u32 skip:6 | = 1 | +------------------+
| |u32 ptr:26 | = 0 --------+
+---+---------------------+
简单来说
phys_map 像是CR3
nodes 是一个用链表存储了的页表
sections 是nodes的叶子ptr指向的内容,其中包含了MemoryRegion
希望这么解释能够在一定程度上帮助理解。
Last updated