# 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

希望这么解释能够在一定程度上帮助理解。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://richardweiyang-2.gitbook.io/understanding_qemu/00-as/04-flatview.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
