ユーザー空間ドライバーを備えた PCIe デバイスがあります。BAR を介してデバイスにコマンドを書き込んでいます。コマンドは遅延の影響を受けやすく、データ量が少ない (~64 バイト) ため、DMA を使用したくありません。
を使用してカーネル内の BAR の物理アドレスを再マップし、カーネル内ioremap_wc
の BAR に 64バイトを書き込むと、64 バイトが PCIe 経由で単一の TLP として書き込まれていることがわかります。ユーザー空間プログラムをフラグ付きの領域に許可してから64 バイトを書き込むと、単一のトランザクションではなく、PCIe バス上に複数の TPL が表示されます。mmap
MAP_SHARED
カーネルPATのドキュメントによると、書き込み結合ページをユーザー空間にエクスポートできるはずです。
一部のページをユーザー空間にエクスポートしたいドライバーは、mmap インターフェイスとの組み合わせを使用してそれを行います
1)
pgprot_noncached()
2)
io_remap_pfn_range()
またはremap_pfn_range()
またはvm_insert_pfn()
PAT のサポートにより、新しい API
pgprot_writecombine
が追加されています。そのため、ドライバーは、ステップ 1 のいずれpgprot_noncached()
かpgprot_writecombine()
で上記のシーケンスを使用し、その後にステップ 2 を続けることができます。
このドキュメントに基づいて、私の mmap ハンドラーからの関連するカーネル コードは次のようになります。
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
return io_remap_pfn_range(vma,
vma->vm_start,
info->mem[vma->vm_pgoff].addr >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
PCIe デバイスが lspci に表示され、予想どおりプリフェッチ可能としてマークされた BAR が表示されます。
Latency: 0, Cache Line Size: 64 bytes Interrupt: pin A routed to IRQ 11 Region 0: Memory at d8000000 (64-bit, prefetchable) [size=32M] Region 2: Memory at d4000000 (64-bit, prefetchable) [size=64M]
ユーザー空間から呼び出すとmmap
、ログ メッセージが表示されます (debugpat カーネル ブート パラメータが設定されています)。
reserve_memtype 追加 [mem 0xd4000000-0xd7ffffff], track write-combining, req write-combining, ret write-combining
/sys/kernel/debug/x86/pat_memtype_list
また、PAT エントリが正しいように見え、重複する領域がないことも確認できます。
write-combining @ 0xd4000000-0xd8000000
uncached-minus @ 0xd8000000-0xda000000
また、PAT 構成と競合する MTRR エントリがないことも確認しました。私が見る限り、書き込み結合がユーザー空間で発生するようにすべてが正しく設定されていますが、PCIe アナライザーを使用して PCIe バス上のトランザクションを観察すると、ユーザー空間のアクセス パターンは、カーネルから実行される同じ書き込みとはまったく異なります。ioremap_wc
電話の後。
書き込み結合がユーザー空間から期待どおりに機能しないのはなぜですか?
さらにデバッグするにはどうすればよいですか?
現在、シングル ソケット 6 コア i7-3930K で実行しています。