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