6

Linuxカーネル用のFPGAドライバーに取り組んでいます。コードは x86 では問題なく動作するようですが、x86_64 ではいくつか問題があります。ストリーミング DMA を実装しました。だからそれは次のようになります

get_user_pages(...);
for (...) {
    sg_set_page();
}
pci_map_sg();

しかし、pci_map_sg返された のようなアドレスは0xbd285800によって整列されていPAGE_SIZEないため、最初のページ全体を送信できません。PCIE 仕様によると

「要求は、メモリ空間アクセスが 4 KB 境界を越える原因となるアドレス/長さの組み合わせを指定してはなりません。」

アラインされたアドレスを取得する方法はありますか、それとも重要なことを見逃しただけですか?

DMA のソースコード

4

1 に答える 1

3

頭に浮かぶ最初の可能性は、入ってくるユーザーバッファーがページ境界で始まっていないということです。開始アドレスがページ全体で 0x800 バイトの場合、最初のsg_set_page呼び出しのオフセットは 0x800 になります。これにより、0x800 で終わる DMA アドレスが生成されます。これは正常な動作であり、バグではありません。

ページを結合すると、このpci_map_sg最初のセグメントは 1 ページより大きくなる場合があります。重要なことはpci_map_sg、DMA アドレス可能なメモリの連続したブロックを生成することですが、低レベルの PCIe トランザクションのリストは生成しません。x64 では、ほとんどの x64 プラットフォームに IOMMU があるため、リージョンが大きくなる可能性が高くなります。

私が扱っている多くのデバイスには、数メガバイトの論理転送長を指定できる DMA エンジンが搭載されています。通常、PCIe エンドポイントの DMA 実装は、4kB 境界ごとに新しい PCIe トランザクションを開始する責任があり、プログラマはその制約を無視できます。FPGA のリソースが制限されすぎて処理できない場合は、ドライバー コードを記述して、メモリ ブロックの Linux リストを PCIe トランザクションの (はるかに長い) リストに変換することを検討できます。

于 2012-02-22T09:06:48.537 に答える