# 创建ACPI表

在x86带有acpi支持的系统上，如果去要加入内存numa的支持，除了上述的步骤之外好要添加相应的acpi表。这样才能在内核中获取相关的numa信息。

## 内核需要什么acpi信息

在看Qemu中干了什么之前我们先看看内核中是需要什么acpi的信息。

```
int __init acpi_numa_init(void)
{
    int cnt = 0;

    if (acpi_disabled)
        return -EINVAL;

    /*
     * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
     * SRAT cpu entries could have different order with that in MADT.
     * So go over all cpu entries in SRAT to get apicid to node mapping.
     */

    /* SRAT: System Resource Affinity Table */
    if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
        struct acpi_subtable_proc srat_proc[3];

    ...
        cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
                        acpi_parse_memory_affinity, 0);
    }

    /* SLIT: System Locality Information Table */
    acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);

  ...
    return 0;
}
```

简化后的代码如上，主要就是解析了两张表：

* SRAT: System Resource Affinity Table
* SLIT: System Locality Information Table

你要问我这是啥我也不懂，反正就是他们俩没错了～

## Qemu中模拟ACPI表

这个工作在下面的函数中执行。

```
acpi_build
  if (pcms->numa_nodes) {
    acpi_add_table(table_offsets, tables_blob);
    build_srat(tables_blob, tables->linker, machine);
    if (have_numa_distance) {
        acpi_add_table(table_offsets, tables_blob);
        build_slit(tables_blob, tables->linker);
    }
  }
```

你看，是不是qemu也是创建了两张表？

* 至于这个acpi\_build是什么时候调用的，请看下一节。

那这个表是不是就是内核中解析的表呢？我们来看看两个数据结构是不是能够对上就好。

Qemu中有 AcpiSratMemoryAffinity

```
struct AcpiSratMemoryAffinity {
    ACPI_SUB_HEADER_DEF
    uint32_t    proximity;
    uint16_t    reserved1;
    uint64_t    base_addr;
    uint64_t    range_length;
    uint32_t    reserved2;
    uint32_t    flags;
    uint32_t    reserved3[2];
} QEMU_PACKED;
```

而内核中有 acpi\_srat\_mem\_affinity

```
struct acpi_srat_mem_affinity {
    struct acpi_subtable_header header;
    u32 proximity_domain;
    u16 reserved;        /* Reserved, must be zero */
    u64 base_address;
    u64 length;
    u32 reserved1;
    u32 flags;
    u64 reserved2;        /* Reserved, must be zero */
};
```

这两个正好一摸一样。这下放心了。

## 附带一个ACPI System Description Tables

多次需要对ACPI Table进行操作，总是要去找什么表在什么地方。很费时间，干脆做个总结。没有单独开一章节，就先放在这里了。

下图的内容在ACPI SPEC 5.2 ACPI System Description Tables中可以找到细节。

```
     RSDP                      
     +--------------+               RSDT / XSDT
     |RSDT Addr  ---|-------+------>+--------------+
     |              |       |       |Head          |
     +--------------+       |       |              |
     |XSDT Addr  ---|-------+       |              |
     |              |               |              |             
     +--------------+         Entry +--------------+           FADT
                                    |FADT Addr  ---|---------->+--------------+
                                    |              |           |Head          |
                                    +--------------+           |              |
                                    |              |           |              |
                                    |              |           |              |
                                    +--------------+           +--------------+
                                    |MADT Addr     |           |FACS Addr     |
                                    |              |           |              |
                                    +--------------+           +--------------+
                                    |MCFG Addr     |           |DSDT Addr     |
                                    |              |           |              |
                                    +--------------+           +--------------+
                                    |              |           |X_DSDT Addr   |
                                    |              |           |              |
                                    +--------------+           +--------------+
                                    |SSDT Addr     |                       
                                    |              |                       
                                    +--------------+
```


---

# 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:

```
GET https://richardweiyang-2.gitbook.io/understanding_qemu/00-devices/00-an_example/04-dimm_acpi.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.
