# 上帝视角

名字起的大了点，所谓上帝视角就是看看nvdimm总线驱动设备中都有哪些东西。

## 驱动和设备的对应关系

先来看看sysfs下，nvdimm驱动和设备之间的对应关系。

```
                                           /sys/                                              
                                            |                                                 
                   +------------------------+------------------------------------------+      
                   |                                                                   |      
                  bus/                                                              devices/  
                   |                                                                   |      
                   |                                                                   .
                   |                                                                   .
                   |                                                                   .
                   |                                                                   |
           --------+-------                                                       -----+-----
                   |                                                                   |
                  nd                                                                   |
            (nvdimm_bus_type)                                          +--------->  ndbus0/
                   |                                                   |          (nvdimm_bus)
                   |                                                   |               |
            -------+-------                                            |               |
                   |                                                   |               |
                drivers/                                               |       +-------+------+
                   |                                                   |       |              |
           +-------+-------+--------+--------------+-------------+     |       |              |
           |       |       |        |              |             |     |       |              |
           |     nd_pmem   |    nd_region          |         nd_bus ---+   +-> nmem0    +--> region0/
           |  (nd_pmem_driver) (nd_region_driver)  |     (nd_bus_driver)   |  (nvdimm)  |  (nd_region)
           |       |       |        |              |                       |            |     |
           |       |    nd_blk      |              |                       |            |     |
           |       | (nd_blk_driver)|            nvdimm -------------------+            |     |
           |       |       |        |        (nvdimm_driver)                            |     |
           |       |       |        |                                                   |     |
           |       |       |        +---------------------------------------------------+     |
           |       |       |                                                                  |
           |       |       |                                 +----------------+-------------+-+---------+
           |       |       |                                 |                |             |           |
           |       |       |                             namespace0.0         |             |           |
           |       |       +---------------------------> (nd_namespace_blk)   |             |           |
           |       |                                                          |             |           |
           |       +-----------------------------------> (nd_namespace_io)    |             |           |
           |       |                                     (nd_namespace_pmem)  |             |           |
           |       |                                                          |             |           |
           |       |                                                          |             |           |
           |       +-------------------------------------------------------> btt0.0         |           |
           |       |                                                         (nd_btt)       |           |
           |       |                                                                        |           |
           |       +----------------------------------------------------------------->  pfn0.0          |
           |                                                                            (nd_pfn)        |
           |                                                                                            |
           |                                                                                            |
           dax_pmem   -----------------------------------------------------------------------------> dax0.0      
          (dax_pmem_driver)                                                                          (nd_dax)    
                                                                                                        |
                                                                                                        |
                                                                                                       dax
                                                                                                        |
                                                                                                        |
                                                                                                      dax0.0
                                                                                                     (dax_fops)
```

暂时这个图还不全，后续会再加进来。

可以看到的是在nvdimm\_bus\_type下有多个驱动分别对应了设备目录下不同类型的nvdimm设备。 而设备这边各自并不是完全独立，而是形成了一颗设备树。

所以说这玩意还真有点复杂。

## 数据结构的层次关系

出了驱动和设备之间的关系，还可以从另一个视角去观察这些重要的数据结构。那就是系统分层的角度。

```

                                                                          nd_btt
                                                                          nd_pfn
                                                                          nd_dax
                                                                              |
                                                                              |
                                                                              v
                                                                          nd_namespace_pmem
                                                                          nd_namespace_io
                                                                          nd_namespace_blk
                                                                              |
                                                                              |
                                                                              v
 Kernel                    nvdimm_bus               nvdimm                nd_regioin
 Data                       .nd_desc                 .provider_data        .provider_data --+
                              |                       |                                     |
                              |                       |                                     |
 ............................................................................................
                              |                                                             |
                              v                       |                                     |
 Hardware                  nvdimm_bus_descriptor                          nd_region_desc    |
 Abstract                   .provider_name =          |                    .provider_data <-+
                                "ACPI.NFIT"                                  |
                                                      |                      |
                                                                             |
 ............................................................................................
                                                      |                      |
        +---------------------------------------------|----------------------|---------+
        |                                             v                      v         |
 ACPI   | acpi_nfit_desc                            nfit_mem              nfit_spa     |     
 Data   |                                                                              |
        |                                                                              |
        +------------------------------------------------------------------------------+
```

这张图从另一个角度展示了数据结构生成之间的依赖关系，以及内核如何通过数据结构的抽象将软件和硬件实现隔离。

## 总体流程

最开始抓瞎的就是不知道初始化的流程是从哪里开始的，看到哪觉得都是起始点。终于找到的时候才有种柳暗花明的感觉。

首先需要说的是，nvdimm初始化的地方现在看有三个，也就是有三个不同的来源建立nvdimm。这里列出的是从acpi\_nfit获取信息建立的过程。

```
acpi_nfit_init(struct acpi_nfit_desc *acpi_desc)
  nvdimm_bus_register()                            create nvdimm_bus
  add_table()
  nfit_mem_init()
  acpi_nfit_register_dimms()                       create nvdimm
  acpi_nfit_register_regions()                     create nd_region
```

现在看还是挺简单的。

大家可以看到的是在这个函数中创建了上一节设备树中的前三个设备：nvdimm\_bus, nvdimm, nd\_region。 而挂在nd\_region下的其他设备则由其余的驱动来处理了。

对于从acpi\_nfit中获取的nvdimm信息，有一个关键的数据结构acpi\_nfit\_desc。接着我们就围绕着这个数据结构来看看这些设备是怎么来的。
