Linux内核flush_cache_range()调用似乎什么都不做

时间:2013-06-04 18:28:55

标签: linux-device-driver flush dma arm9

简介:

我们有一个应用程序,其中在ARM上运行的Linux接受来自外部处理器的数据,该数据将DMA数据存入ARM的内存空间。然后,ARM需要从用户模式代码访问该数据。

地址范围必须是物理连续的,因为外部处理器中的DMA引擎不支持分散/聚集。此内存范围最初是通过__get_free_pages(GFP_KERNEL | __GFP_DMA,order)调用从ARM内核分配的,因为这可以确保分配的内存在物理上是连续的。然后对返回的指针进行virt_to_phys()调用,为我们提供物理地址,然后在进程开始时将其提供给外部处理器。

此物理地址也为Linux用户模式代码所知,该代码使用它(在用户模式下)调用mmap()API以获取指向此内存区域的用户模式指针。然后,我们的Linux内核驱动程序会在驱动程序的file_operations结构中看到对其mmap例程的相应调用。然后驱动程序保留vm_area_struct“vma”指针,该指针在调用其mmap例程时传递给它,以供稍后使用。

当用户模式代码接收到新数据已经DMA到该存储器地址的信号时,它需要通过我们从上面提到的mmap()调用获得的用户模式指针从用户模式访问它。在用户模式代码执行此操作之前,必须刷新与此内存范围对应的高速缓存。要完成此刷新,用户模式代码将调用驱动程序(通过ioctl),并在内核模式下调用flush_cache_range():

flush_cache_range(VMA,开始,结束);

传递给上面调用的参数是驱动程序在调用mmap例程时捕获的“vma”,“start”和“end”是从用户模式代码传入驱动程序的用户模式地址提供给ioctl()调用的结构。

问题:

我们看到的是缓冲区似乎没有被刷新,因为当我们看到从用户模式进行访问时看起来似乎是陈旧的数据。作为测试而不是从mmap()调用我们的驱动程序获取用户模式地址,我们将mmap()API调用到/ dev / mem。在这种情况下,我们获得了对缓冲区的非缓存访问(不需要刷新),然后一切都运行良好。

我们的内核版本是3.8.3并且它在ARM 9上运行。我们正在尝试的方法是否存在逻辑错误?

谢谢!

1 个答案:

答案 0 :(得分:0)

我有几个问题,之后我可能会回答: 1)你如何在mmap()调用中使用“PHYSICAL”地址? mmap应该与物理地址无关。 2)您到底如何在驱动程序中获取用户虚拟地址? 3)如何将这些用户虚拟地址映射到物理地址以及在何处执行此操作? 4)由于您使用get_free_pages()预分配,是否使用ioremap_cache()将其映射到内核空间?