一、DMA
DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高.
看到STM32内核,存储器,外设及DMA的连接,这些硬件最终通过各种各样的线连接到总线矩阵中,硬件结构之间的数据转移都经过总线矩阵的协调,使各个外设和谐的使用总线来传输数据。
AHB介绍:
1
2
3
4
AHB总线规范是AMBA总线规范的一部分,AMBA总线规范是ARM公司提出的总线规范,被大多数SoC设计采用,它规定了AHB (Advanced High-performance Bus)、ASB (Advanced System Bus)、APB (Advanced Peripheral Bus)。AHB用于高性能、高时钟频率的系统结构,典型的应用如ARM核与系统内部的高速RAM、NAND FLASH、DMA、Bridge的连接。APB用于连接外部设备,对性能要求不高,而考虑低功耗问题。ASB是AHB的一种替代方案。
AHB总线的架构
AHB总线的强大之处在于它可以将微控制器(CPU)、高带宽的片上RAM、高带宽的外部存储器接口、DMA总线master、各种拥有AHB接口的控制器等等连接起来构成一个独立的完整的SOC系统,不仅如此,还可以通过AHB-APB桥来连接APB总线系统。AHB可以成为一个完整独立的SOC芯片的骨架。 ![image-20221130161933206](.\images\dma-and-iommu\AHB总线.png)
二、IOMMU
1、DMA做地址翻译,用来解决DMA的安全性问题,DMA API同时肩负起了设置IOMMU的职责。
2、做设备虚拟化直通。
三、DMA-IOMMU
IOMMU:DMA (iova)-> memory port -> iommu(pa) -> 总线 -> 内存控制器 存/取主存内容
代码分析:
设备attach iommu时install ops,
arm64: iommu_dma_ops
intel: intel_dma_ops
1、dma ops接口
dma_ops接口 | 功能 | dma ops | iommu ops | iova分配 |
---|---|---|---|---|
alloc(*dev, size, *dma_handle, gfp) | 申请物理页 + 申请iova + iommu mapm | map | Y | |
free(*dev, size, *vaddr, dma_handle, attr) | iommu unmap + 释放iova + 释放物理页 | unmap | Y | |
alloc_pages(*dev, size, *dma_handle, dir, gfp) | 申请dma连续物理页 + dma map_page | map_page | Y | |
free_pages(*dev, size, *vaddr, dma_handle, dir) | dma unmap_page + 释放连续物理页 | unmap_page | Y | |
alloc_noncoherent(*dev, size, *dma_handle, dir, gfp) | 与alloc_pages一致 | noblock: map_page | block: map | Y |
free_noncoherent(*dev, size, *vaddr, dma_handle, dir) | 与free_pages一致 | noblock: unmap_page | block: unmap | Y |
mmap | mmu mmap | |||
get_sgtable | ||||
map_page(*dev, *page, offset, size, dir, attrs) | 申请iova + iommu map | map | Y | |
unmap_page(*dev, dma_handle, size, dir, attrs) | iommu unmap + 释放iova | unmap | Y | |
map_sg(*dev, *sg, nents, dir, attrs) | 与map_page一致 | map | Y | |
unmap_sg(*dev, *sg, nents, dir, attrs) | 与unmap_page一致 | unmap | Y | |
map_resource(*dev, phys, size, dir, attrs) | 申请iova + iommu map | Y | ||
unmap_resource(*dev, dma_handle, size, dir, attrs) | iommu unmap + 释放iova | Y | ||
sync_single_for_cpu | iova_to_phys + inv Dcache 保证cache一致性 | iova_to_phys | ||
sync_single_for_device | iova_to_phys + inv Dcache + clear Dcache 保证cache一致性 | iova_to_phys | ||
sync_sg_for_cpu | 与sync_single_for_cpu一致 | iova_to_phys | ||
sync_sg_for_device | 与sync_single_for_device一致 | iova_to_phys | ||
cache_sync | ||||
dma_supported | ||||
get_required_mask | ||||
max_mapping_size | ||||
get_merge_boundary | 获取iommu在使用的page size |
2、iommu ops
iommu ops接口 | 功能 | 分类 |
---|---|---|
capable | check capability | iommu基础能力check |
domain_alloc | allocate iommu domain | 管理dev集合 |
domain_free | free iommu domain | 管理dev集合 |
attach_dev | attach device to an iommu domain | 管理dev集合 |
detach_dev | detach device from an iommu domain | 管理dev集合 |
map | map a physically contiguous memory region to an iommu domain | iommu page table操作 |
unmap | unmap a physically contiguous memory region from an iommu domain | iommu page table操作 |
flush_iotlb_all | Synchronously flush all hardware TLBs for this domain | iommu page table操作 |
iotlb_sync_map | Sync mappings created recently using @map to the hardware | iommu page table操作 |
iotlb_sync | Flush all queued ranges from the hardware TLBs and empty flush queue | iommu page table操作 |
iova_to_phys | translate iova to physical address | iommu page table操作 |
probe_device | Add device to iommu driver handling | 管理dev集合 |
release_device | Remove device from iommu driver handling | 管理dev集合 |
probe_finalize | Do final setup work after the device is added to an IOMMU group and attached to the groups domain | 管理dev集合 |
device_group | find iommu group for a particular device | 管理dev集合 |
domain_get_attr | Query domain attributes | 管理dev集合 |
domain_set_attr | Change domain attributes | 管理dev集合 |
support_dirty_log | Check whether domain supports dirty log tracking | iommu page table操作 |
switch_dirty_log | Perform actions to start|stop dirty log tracking | iommu page table操作 |
sync_dirty_log | Sync dirty log from IOMMU into a dirty bitmap | iommu page table操作 |
clear_dirty_log | Clear dirty log of IOMMU by a mask bitmap | iommu page table操作 |
get_resv_regions | Request list of reserved regions for a device | iova预留 |
put_resv_regions | Free list of reserved regions for a device | iova预留 |
apply_resv_region | Temporary helper call-back for iova reserved ranges | iova预留 |
domain_window_enable | Configure and enable a particular window for a domain | NA |
domain_window_disable | Disable a particular window for a domain | NA |
of_xlate | add OF master IDs to iommu grouping | NA |
is_attach_deferred | Check if domain attach should be deferred from iommu driver init to device driver init (default no) | 管理dev集合 |
dev_has/enable/disable_feat | per device entries to check/enable/disable iommu specific features. | 管理dev集合 |
dev_feat_enabled | check enabled feature | iommu能力check |
aux_attach/detach_dev | aux-domain specific attach/detach entries. | aux |
aux_get_pasid | get the pasid given an aux-domain | aux |
sva_bind | Bind process address space to device | sva |
sva_unbind | Unbind process address space from device | sva |
sva_get_pasid | Get PASID associated to a SVA handle | sva |
page_response | handle page request response | sva |
cache_invalidate | invalidate translation caches | sva vfio |
sva_bind_gpasid | bind guest pasid and mm | sva vfio |
sva_unbind_gpasid | unbind guest pasid and mm | sva vfio |
attach_pasid_table | attach a pasid table | sva vfio |
detach_pasid_table | detach the pasid table | sva vfio |
bind_guest_msi | provides a stage1 giova/gpa MSI doorbell mapping | NA |
unbind_guest_msi | withdraw a stage1 giova/gpa MSI doorbell mapping | NA |
def_domain_type | device default domain type, return value | 管理dev集合 |
dirty_log的使用
1
2
3
HTTU Hardware Translation Table Update. The act of updating the Access flag or Dirty
state of a page in a given TTD which is automatically done in hardware, on an
access or write to the corresponding page.
参考:SMMU的spec 3.13 Translation table entries and Access/Dirty flags章节
qemu/kvm dirty pages tracking in migration
热迁移虚拟机还是要短暂停止的,只是时间很短,影响比较小,给人感觉服务没有中断。 dirty log就是记录哪些页被修改。
1
2
DMA iommu的page write, live migrate dma dirty log trace if iommu support dirty log:
live migrate start -> switch iommu dirty log on -> sync dirty log to bitmap -> clear dirty log ->sync to qemu to copy memory