use*_*504 4 android kernel kernel-module linux-kernel
设备地址,物理地址和虚拟地址有什么区别?
其实我mmap在司机中试图,我坚持这个概念.
该文件说:
内核通常使用虚拟地址.kmalloc(),vmalloc()和类似接口返回的任何地址都是虚拟地址,可以存储在"void*"中.
虚拟存储器系统(TLB,页表等)将虚拟地址转换为CPU物理地址,其存储为"phys_addr_t"或"resource_size_t".内核管理设备资源,如寄存器作为物理地址.这些是/ proc/iomem中的地址.物理地址对驱动程序没有直接用处; 它必须使用ioremap()来映射空间并生成虚拟地址.
I/O设备使用第三种地址:"总线地址"或"DMA地址".如果设备在MMIO地址处具有寄存器,或者如果它执行DMA以读取或写入系统存储器,则设备使用的地址是总线地址.在某些系统中,总线地址与CPU物理地址相同,但通常它们不是.IOMMU和主桥可以在物理地址和总线地址之间产生任意映射.
这是一张图片和一些例子:
Run Code Online (Sandbox Code Playgroud)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,则内核从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的缓冲区.
| 归档时间: |
|
| 查看次数: |
2270 次 |
| 最近记录: |