ARMV8 用户态DMA cache一致性问题和解决

原因:
dma和cpu都有操作内存的能力,dma操作内存不通过cpu和cache,即cpu cache感知不到dma对内存的操作
因此cpu和dma合作时,就会存在cpu cache和内存的一致性问题,原因是dma对内存操作无法被cache感知。
当然如果给dma的内存是no cache的,cpu不会使用cache,也就不存在相关问题。
如果给dma的是带cache内存,那么cpu访问的时候就需要注意。

armv8提供了cache相关指令解决上述问题,比如下面2条:
dc civac Data or unified Cache line Clean and Invalidate by VA to PoC
dc ivac Data or unified Cache line Invalidate by VA to PoC
但是请注意,dc ivac是特权指令,在el0可以执行的只有dc civac。

问题:
在驱动中,如果要读取dma存放到内存中的数据,在读取之前需要先让cache无效才可以,
这在linux中很好实现,读之前调用一次dc ivac即可。
如果由于某种原因,给dma的内存是cache的,而且驱动是在用户态(典型如微内核),
那么就存在无法在用户态使用dc ivac而导致数据不一致的问题。

解决这个问题方法:
在cpu告诉dma内存地址之前,对这段地址使用dc civac!
在dma操作之前使用dc civac很好理解,clean(flush)和invalid,保证了cache已经回写内存,这里回写的数据是什么不重要,
重要的确保不会在dma操作期间cache回写内存。另外这个指令也会无效内存对应的cache。
当然使用dc civac代替dc ivac还需要一个前提,即这期间除了dma,没有其他cpu会访问这段内存。

另外,如果cpu要交给dma一段数据,一定要注意cache line对齐,原因是硬件底层cache的操作最小单位是cache line大小。
否则有可能导致dc civac的时候没有把需要的数据真正刷新到内存的问题。

猜你喜欢

转载自blog.csdn.net/wdjjwb/article/details/87713477
今日推荐