我正在开发通过直接内存访问(DMA)事务与PCI卡通信的软件。我的程序使用一套驱动程序和一个处理DMA的库。所有东西都运行在Red上。
为了测试和测量我的程序的性能,我想跟踪DMA事务的开始和结束。现在,我通过查看库中的几个函数来做到这一点:
dma_from_host和dma_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寄存器的值?这是一个可行的方法吗?有这种已知的追踪器吗?
发布于 2020-08-17 17:08:29
受到@dirkt的评论的鼓舞,我更好地查看了驱动程序,并发现了与这些DMA事务相对应的PCI中断。
驱动程序通过调用启用这些中断。
pci_enable_msix(.., msixTable,..)它设置了struct msix_entry msixTable[MAXMSIX]。然后,通过在循环中调用static irqreturn_t irqHandler(),将它们分配给处理程序request_irq():
request_irq(msixTable[interrupt].vector, irqHandler, 0, devName,...)处理程序只对本地int数组中的中断进行计数。这些计数器是在这个驱动程序为诊断等创建的/proc/文件中导出的。实际上,proc文件是从我开始搜索中断的地方开始的。
但是有一个更好的方法:/proc/interrupts文件。启用的MSI中断显示在下面这样的行中:
$ 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目录中的卡的中断:
$ 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工具跟踪这个中断:
# 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"好的是你得到了中断的时间戳。例如:
$ 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卡本身。
此外,中断当然不能让您访问有关事务本身的信息,比如传输的内存大小。您需要确保卡中没有错误可以防止中断,并且在交易结束后立即触发它们。
https://unix.stackexchange.com/questions/604585
复制相似问题