
私は直接メモリアクセス(DMA)トランザクションを介してPCIカードと通信するソフトウェアを開発しています。私のプログラムは一連のドライバとライブラリを使ってDMAを処理します。すべてがRed Hat Linuxで実行されます。
私のプログラムのパフォーマンスをテストして測定するために、DMAトランザクションの開始と終了を追跡したいと思います。次に、ライブラリ内のいくつかの関数を見て、これを行います。
dma_from_host
dma_to_host
カードレジスタの値を設定し、名前付き1
レジスタに書き込んで取引を開始します。DMA_DESC_ENABLE
dma_wait
レジスタの値を継続的に確認し、トランザクションが完了するのを待ちますDMA_DESC_ENABLE
。
しかし、取引が始まったというより確実な確認と、取引の終わりにはより正確な信号を受けたいと思います。 Linuxやハードウェア自体の方がベストです。
私はこれが原則として迷惑な状況であることを知っています。 DMAの概念は、ハードウェア(マザーボードのPCIカードまたはDMAコントローラ)がCPUとオペレーティングシステムをバイパスし、プロセスのメモリに直接データをコピーすることです。しかし、何らかの方法でCPUに通知せずに内容をRAMにコピーするだけではありません。これらの取引を追跡する標準的な方法はありますか、それともプラットフォームによって異なりますか?
DMAの開始と終了をCPUに通知する特別な割り込みはありますか?私が使用しているドライバで同様のものが見つかりません。しかし、私はドライバーの経験がないので、簡単に奇妙な場所を見つけることができます。
別の考えでは、この情報を提供できるPMUなどのハードウェアモニターはありますか? PCIレーンのトランザクションのみを計算するのですか?
もう一つ考えてみましょう。カスタムDMAトラッカーをLinuxモジュールまたはBPFプログラムで作成して、DMA_DESC_ENABLE
このレジスタの値を継続的に確認できることを私は正しく理解していますか?これが実現可能なアプローチですか?同様の既知のトラッカーがありますか?
答え1
@dirktのコメントに基づいて、ドライバをより詳しく見て、これらのDMAトランザクションに対応するPCI MSI割り込みを見つけました。
ドライバは以下を呼び出してこれらの割り込みをイネーブルにします。
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/<devName>
診断などのためにドライバによって生成されたファイルにエクスポートされます。実際、procファイルは私の検索が中断され始めた場所です。
しかし、より良い方法があります。/proc/interrupts
まさにファイルです。アクティブなMSI-X割り込みは、次の行に表示されます。
$ cat /proc/interrupts
CPU0 CPU1 ... CPU5 CPU6 CPU7
66: 0 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
67: 0 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
68: 33 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
69: 0 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
70: 0 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
71: 0 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
72: 0 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
73: 0 0 ... 0 0 0 IR-PCI-MSI-edge <devName>
別のアプローチは、出力でカードのPCIアドレスを見つけ、lspci
カードに割り当てられた割り込みのディレクトリを確認することです/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がトリガされます。irq:irq_handler_entry
Linuxの割り込みハンドラには静的トレースポイントがあります。トレースポイントパラメータフィールドに/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
# | | | |||| | |
<idle>-0 [009] d.H. 6090.224339: irq_handler_entry: irq=99 name=xhci_hcd
...
この方法を使用せずに確認する価値がある1つは、これらの割り込みは、DMAが他のproc
方法では不可能な可能性があるファイルの便利なカウンタだけでなく、システム関連の項目も監視していることを確認するために重要であることです。しかし、それらを見るとわかりません/proc/interrupts
。デバイスにはdmar[0123]
DMAのように見える割り込みがありますが、絶対に増加しません。この場合、DMAエンジンはPCIカード自体のFPGAコアとして実装する必要があるため、これは予想されます。
もちろん、割り込みは送信されたメモリサイズなどのトランザクション自体に関する情報へのアクセスも提供しません。中断を防ぐためのカードエラーがないこと、および取引の直後に中断が発生することを確認する必要があります。