首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何追踪DMA?

如何追踪DMA?
EN

Unix & Linux用户
提问于 2020-08-14 23:27:06
回答 1查看 1.1K关注 0票数 5

我正在开发通过直接内存访问(DMA)事务与PCI卡通信的软件。我的程序使用一套驱动程序和一个处理DMA的库。所有东西都运行在Red上。

为了测试和测量我的程序的性能,我想跟踪DMA事务的开始和结束。现在,我通过查看库中的几个函数来做到这一点:

  • dma_from_hostdma_to_host,它们通过配置卡片寄存器中的值并将1写入名为DMA_DESC_ENABLE的寄存器来启动事务
  • dma_wait,它通过不断检查DMA_DESC_ENABLE寄存器的值来等待事务完成。

但我希望有一个更有力的确认事务已经启动,更准确的信号,什么时候交易已经结束。Linux或硬件本身的一些东西将是最好的。

我知道原则上这是一个累赘的情况。DMA的思想是硬件( PCI卡或主板上的DMA控制器)将东西直接复制到进程的内存中,绕过CPU和OS。但我希望它不只是在不通知CPU的情况下就把东西复制到RAM中。是否有一些标准的方法来跟踪这些事务,或者它非常特定于平台?

是否有一些特殊的中断通知CPU DMA的开始和结束?在我使用的司机中,我找不到这样的东西。但我对司机没有经验,所以我很容易找错地方。

另一个想法是,是否有类似PMU的硬件监视器可以提供这些信息?在PCI专用线上只计算交易的东西?

还有一个想法,我是否理解一个人可以写一个定制的DMA追踪器作为一个Linux模块或者一个BPF程序来不断地检查DMA_DESC_ENABLE寄存器的值?这是一个可行的方法吗?有这种已知的追踪器吗?

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2020-08-17 17:08:29

受到@dirkt的评论的鼓舞,我更好地查看了驱动程序,并发现了与这些DMA事务相对应的PCI中断。

驱动程序通过调用启用这些中断。

代码语言:javascript
复制
pci_enable_msix(.., msixTable,..)

它设置了struct msix_entry msixTable[MAXMSIX]。然后,通过在循环中调用static irqreturn_t irqHandler(),将它们分配给处理程序request_irq()

代码语言:javascript
复制
request_irq(msixTable[interrupt].vector, irqHandler, 0, devName,...)

处理程序只对本地int数组中的中断进行计数。这些计数器是在这个驱动程序为诊断等创建的/proc/文件中导出的。实际上,proc文件是从我开始搜索中断的地方开始的。

但是有一个更好的方法:/proc/interrupts文件。启用的MSI中断显示在下面这样的行中:

代码语言:javascript
复制
$ cat /proc/interrupts 
            CPU0       CPU1  ...  CPU5       CPU6       CPU7       
  66:          0          0  ...     0          0          0  IR-PCI-MSI-edge      
  67:          0          0  ...     0          0          0  IR-PCI-MSI-edge      
  68:         33          0  ...     0          0          0  IR-PCI-MSI-edge      
  69:          0          0  ...     0          0          0  IR-PCI-MSI-edge      
  70:          0          0  ...     0          0          0  IR-PCI-MSI-edge      
  71:          0          0  ...     0          0          0  IR-PCI-MSI-edge      
  72:          0          0  ...     0          0          0  IR-PCI-MSI-edge      
  73:          0          0  ...     0          0          0  IR-PCI-MSI-edge      

另一种方法是在lspci输出中查找卡的PCI地址,并检查分配给/sys目录中的卡的中断:

代码语言:javascript
复制
$ ls  /sys/bus/pci/devices/0000:17:00.0/msi_irqs
66  67  68  69  70  71  72  73

# but these are empty
$ cat  /sys/bus/pci/devices/0000:17:00.0/irq
0

到事务结束时,中断号68就会启动。在Linux中,中断处理程序有一个静态跟踪点irq:irq_handler_entry/sys/kernel/debug/tracing/events/irq/irq_handler_entry/format中的跟踪点参数在int irq字段中有中断号。因此,这个带有过滤器条件的跟踪点可以用标准的Linux工具跟踪这个中断:

代码语言:javascript
复制
# setup the ftrace
trace-cmd start -e irq:irq_handler_entry -f "irq == 68"
# for live stream
cat /sys/kernel/debug/tracing/trace_pipe
# or just
trace-cmd stop
trace-cmd show
trace-cmd reset

# with perf
perf record -e "irq:irq_handler_entry" --filter "irq == 68"

好的是你得到了中断的时间戳。例如:

代码语言:javascript
复制
$ sudo trace-cmd start -e irq:irq_handler_entry -f "irq == 99"
$ sudo trace-cmd stop
$ sudo trace-cmd show | head -n 20
# tracer: nop
#
# entries-in-buffer/entries-written: 860/860   #P:12
#
#                                _-----=> irqs-off
#                               / _----=> need-resched
#                              | / _---=> hardirq/softirq
#                              || / _--=> preempt-depth
#                              ||| /     delay
#           TASK-PID     CPU#  ||||   TIMESTAMP  FUNCTION
#              | |         |   ||||      |         |
          -0       [009] d.H.  6090.224339: irq_handler_entry: irq=99 name=xhci_hcd
...

有一点仍然值得确认的是,这些中断对于DMA是必不可少的,以确保我监视与系统相关的内容,而不是只监视在另一种情况下可能无法实现的proc文件的一个方便的计数器。但我看不出其他任何相关的干扰是如何在/proc/interrupts中增加的。对于设备dmar[0123]来说,有些中断看起来像是DMA,但它们从未增加过。这是意料之中的,因为在这种情况下,DMA引擎必须作为FPGA核心实现在PCI卡本身。

此外,中断当然不能让您访问有关事务本身的信息,比如传输的内存大小。您需要确保卡中没有错误可以防止中断,并且在交易结束后立即触发它们。

票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/604585

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档