有什么区别设备地址, 实际地址 and 虚拟地址?
其实我正在努力mmap
在驱动程序中,我一直坚持这个概念。
The 文档 https://www.kernel.org/doc/Documentation/DMA-API-HOWTO.txt says:
内核通常使用虚拟地址。返回的任何地址
kmalloc()、vmalloc()和类似接口是虚拟地址,可以
存储在“void *”中。
虚拟内存系统(TLB、页表等)将虚拟内存转换为内存
地址到CPU物理地址,存储为“phys_addr_t”或
“资源大小_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
| | | |
| | | |
+-------+ +------+
在枚举过程中,内核了解 I/O 设备并
它们的 MMIO 空间以及将它们连接到系统的主桥。为了
例如,如果 PCI 设备有 BAR,则内核读取总线地址 (A)
从 BAR 并将其转换为 CPU 物理地址 (B)。地址B
存储在结构资源中,通常通过 /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。然后驱动程序告诉设备
对Z进行DMA,IOMMU将其映射到系统中地址Y处的缓冲区
内存。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)