【问题标题】:How can I force a cache flush for a process from a Linux device driver?如何从 Linux 设备驱动程序强制刷新进程的缓存?
【发布时间】:2019-08-12 19:04:56
【问题描述】:

我正在进行一项研究项目,该项目需要我从自定义硬件执行内存捕获。我正在使用 Zedboard SoC(带有 FPGA 结构的双核 ARM Cortex-A9)。我设计了一个设备驱动程序,允许我执行虚拟内存捕获和物理内存捕获(使用控制Xilinx AXI DMA IP 的 AXI4-Lite 外围设备)。

我的目标是捕获所有映射的页面,因此我检查 /proc/pid/maps 的映射区域,然后从 /proc/pid/pagemaps 获取 PFN,将物理地址传递给我的设备驱动程序,然后将它们传递给我的自定义硬件(它调用 Xilinx AXI DMA 从物理内存中获取内容)。

注意:我使用的是 Xilinx 的 PetaLinux 发行版,它基于 Linux 4.14 版构建。

我的设备驱动程序通过一系列 IOCTL 调用实现以下过程:

  1. 停止目标进程。
  2. 执行虚拟内存捕获(使用access_process_vm() 函数)。
  3. 刷新缓存(使用flush_user_range()函数)。
  4. 执行物理内存捕获。
  5. 恢复目标进程。

然而,我注意到的是,虚拟内存捕获和物理内存捕获在 [heap] 部分(这是扩展超过一页的第一部分)中不同。第一页匹配,但其他页面都没有接近。 [stack] 部分根本不匹配。我应该注意,对于前两个内存部分,.text 和 .rodata,捕获完全匹配。目前的结论是,在运行期间改变的数据在虚拟和物理捕获之间匹配,而确实改变的数据 strong> 在运行时不匹配。

所以这让我想知道:我是否使用了正确的函数来确保缓存和 RAM 之间的一致性?如果不是,用于强制将缓存刷新到 RAM 的正确功能是什么?在目标进程停止时,RAM 中的数据必须是最新的,因为我无法从自定义硬件访问缓存。

编辑 1: 关于这个问题被标记为this question 的可能重复项,我正在使用已接受答案中的一个函数来启动缓存刷新。但是,从我的角度来看,它似乎无法正常工作,因为如果发生缓存刷新,物理内存与虚拟内存不匹配。

【问题讨论】:

  • 听起来你想了解如何在 linux 中实现交换。
  • @Flavius 当我从 /proc/pid/pagemap 获取 PFN 时,我会检查每个页面的交换位以及当前位。我试图从物理内存中提取的每一页都声称存在并且没有交换。是否可以在我检查该位和启动物理内存传输之间交换内存?

标签: linux linux-device-driver xilinx zynq petalinux


【解决方案1】:

对于以后遇到这个问题的人来说,问题不是我想的那样。我提到的 flush_user_range() 函数是用于将页面从缓存推回主内存的正确函数。

但是,我当时没有想到的是,实际上连续的页面不一定(而且通常不是)物理上 连续的。在我的内核代码中,我将映射区域的长度传递给我的硬件,它从 AXI DMA 请求该长度的数据。我应该做的是虚拟到物理的转换,以获取每个区域中每个页面的物理地址,然后从主内存请求一个页面长度的数据,对每个映射区域中的每个页面重复该过程。

我意识到这是一个非常具体的问题,可能不会帮助其他任何人做我正在做的事情,但希望学到的教训可以帮助将来的人:Linux 在物理内存中分配页面(通常是 4kB在大小上,尽管您不应该假设是这种情况),并且物理页面的集合包含在一个映射区域中。如果您正在处理任何需要检查物理内存的代码,请务必注意数据可能跨越物理页面边界的位置并采取相应措施。

【讨论】:

  • 永远不要假设虚拟内存在物理地址空间中是连续的。在内核编程中有几种方法可以解决这个问题。老式的方法是保留内核内存并自己管理(内核参数 memmap=)。这是我通常用于用户模式嵌入式编程的模式。一个相当新的方法是使用连续内存分配器(CMA),它保证内核分配在物理空间中是连续的。 CMA 没有公开的、开源的用户模式界面,但这并不意味着没有。
  • 另一个虚拟与物理领域是 NVIDIA GPUDirect。 GPUDirect 可在支持 GPUDirect 的 GPU 上的 PCIe 总线上提供高达 256MB 的 CUDA 内存资源(Quadro for one - 不支持 GeForce)。这是一种将数据从 DMA 设备(如 Mellanox 网卡)直接驱动到 GPU 的方法。我从来没有发现 GPUDirect 页面不连续,但无论如何我都会检查...
猜你喜欢
  • 2013-04-13
  • 2023-04-07
  • 1970-01-01
  • 2013-07-08
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多