物理地址,设备地址和虚拟地址之间的差异

use*_*504 4 android kernel kernel-module linux-kernel

设备地址,物理地址和虚拟地址有什么区别?

其实我mmap在司机中试图,我坚持这个概念.

CL.*_*CL. 8

该文件说:

内核通常使用虚拟地址.kmalloc(),vmalloc()和类似接口返回的任何地址都是虚拟地址,可以存储在"void*"中.

虚拟存储器系统(TLB,页表等)将虚拟地址转换为CPU物理地址,其存储为"phys_addr_t"或"resource_size_t".内核管理设备资源,如寄存器作为物理地址.这些是/ proc/iomem中的地址.物理地址对驱动程序没有直接用处; 它必须使用ioremap()来映射空间并生成虚拟地址.

I/O设备使用第三种地址:"总线地址"或"DMA地址".如果设备在MMIO地址处具有寄存器,或者如果它执行DMA以读取或写入系统存储器,则设备使用的地址是总线地址.在某些系统中,总线地址与CPU物理地址相同,但通常它们不是.IOMMU和主桥可以在物理地址和总线地址之间产生任意映射.

这是一张图片和一些例子:

             CPU                  CPU                  Bus
           Virtual              Physical             Address
           Address              Address               Space
            Space                Space

          +-------+             +------+             +------+
          |       |             |MMIO  |   Offset    |      |
          |       |  Virtual    |Space |   applied   |      |
        C +-------+ --------> B +------+ ----------> +------+ A
          |       |  mapping    |      |   by host   |      |
+-----+   |       |             |      |   bridge    |      |   +--------+
|     |   |       |             +------+             |      |   |        |
| CPU |   |       |             | RAM  |             |      |   | Device |
|     |   |       |             |      |             |      |   |        |
+-----+   +-------+             +------+             +------+   +--------+
          |       |  Virtual    |Buffer|   Mapping   |      |
        X +-------+ --------> Y +------+ <---------- +------+ Z
          |       |  mapping    | RAM  |   by IOMMU
          |       |             |      |
          |       |             |      |
          +-------+             +------+
Run Code Online (Sandbox Code Playgroud)

在枚举过程中,内核会了解I/O设备及其MMIO空间以及将它们连接到系统的主桥.例如,如果PCI设备具有BAR,则内核从BAR读取总线地址(A)并将其转换为CPU物理地址(B).地址B存储在struct资源中,通常通过/ proc/iomem公开.当驱动程序声明设备时,它通常使用ioremap()将物理地址B映射到虚拟地址(C).然后,它可以使用例如ioread32(C)来访问总线地址A处的设备寄存器.

如果设备支持DMA,则驱动程序使用kmalloc()或类似的接口设置缓冲区,该接口返回虚拟地址(X).虚拟内存系统将X映射到系统RAM中的物理地址(Y).驱动程序可以使用虚拟地址X来访问缓冲区,但设备本身不能,因为DMA不通过CPU虚拟内存系统.

在一些简单的系统,该设备可以做DMA直接到物理地址Y.但在许多其他国家,有一个转换总线地址到物理地址,IOMMU如硬件,其转换Z到Y.这是对DMA的部分原因API:驱动程序可以将虚拟地址X提供给dma_map_single()这样的接口,该接口设置任何所需的IOMMU映射并返回总线地址Z.然后驱动程序告诉设备执行DMA到Z,并且IOMMU将其映射到系统RAM中地址Y的缓冲区.