将缓存刷新到DRAM

Bri*_*son 8 arm linux-kernel xilinx zynq

我正在使用Xilinx Zynq平台,在可编程HW和ARM处理器之间共享一个内存区域.

我在内核命令行上使用memmap保留了这个内存,然后通过我的驱动程序中的mmap/io_remap_pfn_range调用将它暴露给用户空间.

我遇到的问题是,写入显示在DRAM中需要一些时间,我认为它存在于dcache中.有一堆flush_cache_*调用被定义,但没有一个被导出,这是我的一个线索,我正在咆哮错误的树...

作为试验,我在本地导出了flush_cache_mm,只是为了看看会发生什么,没有快乐.

简而言之,我怎样才能确定对这个mmap'd区域的任何写入都已提交给DRAM?

谢谢.

art*_*ise 8

ARM处理器通常同时具有I/d高速缓存写缓存.写缓冲区的想法是将顺序写入组合在一起(非常适用于同步DRAM),并且不会延迟CPU等待写入完成.

通用,您可以刷新d缓存写缓冲区.以下是一些内联ARM汇编程序,它应该适用于许多体系结构和内存配置.

 static inline void dcache_clean(void)
 {
     const int zero = 0;
     /* clean entire D cache -> push to external memory. */
     __asm volatile ("1: mrc p15, 0, r15, c7, c10, 3\n"
                     " bne 1b\n" ::: "cc");
     /* drain the write buffer */
    __asm volatile ("mcr 15, 0, %0, c7, c10, 4"::"r" (zero));
 }
Run Code Online (Sandbox Code Playgroud)

如果您有L2缓存,则可能需要更多.

要在Linux上下文中回答,根据内存/ MMU配置甚至CPU勘误,有不同的CPU变体和不同的例程.例如,见

这些例程可以直接调用,也可以在cpu信息结构中查找,其中包含指向检测到的CPU和配置的相应例程的函数指针; 取决于内核是否是单个CPU专用多功能Ubuntu发行版.

要专门针对您的情况回答问题,我们需要了解L2缓存,写入缓冲内存,CPU架构细节; 可能包括勘误表的硅修订版.另一种策略是通过使用将内存标记为不可缓存不可缓冲dma_alloc_XXX() 例程来完全避免这种情况,以便立即从外部推送CPU写入.根据您的内存访问模式,任一解决方案都有效.如果只需要在某个检查点同步内存(vsync/*hsync*用于视频等),您可能希望缓存.

  • 清理整个D-cache在ARMv7上不起作用(我认为Zynq是Cortex-A9).此外,它是一个特权操作,因此来自用户空间的undef也是如此. (3认同)
  • 是的,我已经在我的驱动程序中将“flush”功能实现为 ioctl。到目前为止,我还没有看到行为有任何改善。不过这里有很多好信息。现在我一直在尝试使用flush_cache_all()。我看到在cache-v7.S中声明了v7_flush_dcache_all,但我不清楚如何从我的驱动程序调用这个asm函数...... (2认同)