> For the complete documentation index, see [llms.txt](https://richardweiyang-2.gitbook.io/understanding_qemu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://richardweiyang-2.gitbook.io/understanding_qemu/00-as/05-ramblock.md).

# RAMBlock

对于一个地址空间，我们有了树状的MemoryRegion，有了一维的FlatView，但是还没有讲真正对应的内存在哪里。

在qemu中，这部分的工作交给了RAMBlock。

## 虚拟机内存的分配流程

按照惯例，我们来看一眼一台虚拟机是如何获得对应的内存的。这个过程有点长，在这里只列出关键的部分。

```
pc_memory_init()
  memory_region_allocate_system_memory()
    allocate_system_memory_nonnuma()
      memory_region_init_ram_nomigrate()
        memory_region_init_ram_shared_nomigrate()
        {
          mr->ram = true;
          mr->destructor = memory_region_destructor_ram;
          mr->ram_block = qemu_ram_alloc(size, share, mr, errp);
        }
```

埋得很深，最终还是找到。主要工作还是和MemoryRegion相关，设置了其中几个关键的成员：

* ram: 表示有内存对应
* destructor: 释放时的操作
* ram\_block: 这个就是本节要讲的RAMBlock了

## ram\_list按照空间大小排序的链表

其实到这里已经没啥好多说的了，RAMBlock数据结构就是描述虚拟机在主机上对应的内存空间的。不过呢，在qemu上还用了一个链表把他们连起来。这说明qemu上可以分配不止一个RAMBlock。而且在链表上，他们是按照空间大小排序的。

这部分可以看ram\_block\_add()函数的注释。

```
/* Keep the list sorted from biggest to smallest block.  Unlike QTAILQ,
 * QLIST (which has an RCU-friendly variant) does not have insertion at
 * tail, so save the last element in last_block.
 */
RAMBLOCK_FOREACH(block) {
    last_block = block;
    if (block->max_length < new_block->max_length) {
        break;
    }
}
```

用一张图来让大家增加一些直观印象。

```
  ram_list (RAMList)
  +------------------------------+
  |dirty_memory[]                |
  |    (unsigned long *)         |
  +------------------------------+
  |blocks                        |
  |    QLIST_HEAD                |
  +------------------------------+
   |
   |     RAMBlock                                     RAMBlock
   |     +---------------------------+                +---------------------------+
   +---> |next                       | -------------> |next                       |
         |    QLIST_ENTRY(RAMBlock)  |                |    QLIST_ENTRY(RAMBlock)  |
         +---------------------------+                +---------------------------+
         |offset                     |                |offset                     |
         |used_length                |                |used_length                |
         |max_length                 |                |max_length                 |
         |    (ram_addr_t)           |                |    (ram_addr_t)           |
         +---------------------------+                +---------------------------+
```

## 地址对应关系

有了RAMBlock后，其中关键的一点就是GPA(Guest Physical Address)是如何和HVP(Host Virtual Address)的映射关系就建立了。

我们用一张图来解释。

```
         RAMBlock                                                     RAMBlock
         +---------------------------+                                +---------------------------+
         |next                       | -----------------------------> |next                       |
         |    QLIST_ENTRY(RAMBlock)  |                                |    QLIST_ENTRY(RAMBlock)  |
         +---------------------------+                                +---------------------------+
         |offset                     |                                |offset                     |
         |used_length                |                                |used_length                |
         |max_length                 |                                |max_length                 |
         |    (ram_addr_t)           |                                |    (ram_addr_t)           |
         +---------------------------+                                +---------------------------+
         |host                       |  virtual address of a ram      |host                       |  
         |    (uint8_t *)            |  in host (mmap)                |    (uint8_t *)            |
         +---------------------------+                                +---------------------------+
         |mr                         |                                |mr                         |
         |    (struct MemoryRegion *)|                                |    (struct MemoryRegion *)|
         +---------------------------+                                +---------------------------+
          |                                                            |
          |                                                            |
          |                                                            |
          |   struct MemoryRegion                                      |   struct MemoryRegion
          +-->+------------------------+                               +-->+------------------------+
              |name                    |                                   |name                    |
              |  (const char *)        |                                   |  (const char *)        |
              +------------------------+                                   +------------------------+
              |addr                    |  physical address in guest        |addr                    |
              |  (hwaddr)              |  (offset in RAMBlock)             |  (hwaddr)              |
              |size                    |                                   |size                    |
              |  (Int128)              |                                   |  (Int128)              |
              +------------------------+                                   +------------------------+
```

GPA -> HVA 的映射由MemoryRegion->addr到RAMBlock->host完成。

是不是有种明心见性的感觉～


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://richardweiyang-2.gitbook.io/understanding_qemu/00-as/05-ramblock.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
