3

序章:

ARM 上で実行されている Linux が外部プロセッサからデータを受け取り、データを ARM のメモリ空間に DMA するアプリケーションがあります。次に、ARM はユーザー モード コードからそのデータにアクセスする必要があります。

外部プロセッサの DMA エンジンはスキャッター/ギャザーをサポートしていないため、アドレスの範囲は物理的に連続している必要があります。このメモリ範囲は、最初に __get_free_pages(GFP_KERNEL | __GFP_DMA,order) 呼び出しを介して ARM カーネルから割り当てられます。これにより、割り当てられたメモリが物理的に連続することが保証されます。次に、返されたポインターで virt_to_phys() を呼び出すと、プロセスの開始時に外部プロセッサーに提供される物理アドレスが得られます。

この物理アドレスは、(ユーザー モードで) これを使用して mmap() API を呼び出し、このメモリ領域へのユーザー モード ポインターを取得する Linux ユーザー モード コードにも認識されます。次に、Linux カーネル ドライバーは、ドライバーの file_operations 構造体で、対応する mmap ルーチンへの呼び出しを確認します。ドライバーは、後で使用するために、mmap ルーチンへの呼び出しで渡された vm_area_struct "vma" ポインターを保持します。

ユーザーモードコードは、新しいデータがこのメモリアドレスに DMA されたという信号を受信すると、上記の mmap() への呼び出しから取得したユーザーモードポインターを介して、ユーザーモードからアクセスする必要があります。もちろん、ユーザーモードコードがこれを行う前に、このメモリ範囲に対応するキャッシュをフラッシュする必要があります。このフラッシュを実行するために、ユーザー モード コードは (ioctl を介して) ドライバーを呼び出し、カーネル モードでは flush_cache_range() への呼び出しが行われます。

flush_cache_range (vma、開始、終了);

上記の呼び出しに渡された引数は、mmap ルーチンが呼び出されたときにドライバーがキャプチャした "vma" であり、"start" と "end" は、ドライバーに提供された構造体でユーザー モード コードからドライバーに渡されたユーザー モード アドレスです。 ioctl() 呼び出し。

問題:

ユーザー モードからのアクセスが行われたときに古いデータのように見えるものを確認しているため、バッファーがフラッシュされていないように見えます。ドライバーへの mmap() 呼び出しからユーザー モード アドレスを取得するのではなく、テストとして、代わりに mmap() API を /dev/mem に呼び出します。この場合、キャッシュされていないバッファーへのアクセス (フラッシュは必要ありません) が得られ、すべてが完全に機能します。

カーネル バージョンは 3.8.3 で、ARM 9 で実行されています。試みているアプローチに論理的なエラーはありますか?

ありがとう!

4

1 に答える 1

0

答えられるかもしれないいくつかの質問があります: 1) mmap() 呼び出しで「PHYSICAL」アドレスをどのように使用しますか? mmap は、物理アドレスとは何の関係もありません。2)ドライバーでユーザーの仮想アドレスを取得するために正確に何をしますか? 3) これらのユーザーの仮想アドレスを物理アドレスにどのようにマッピングしますか? どこで行いますか? 4) get_free_pages() を使用して事前に割り当てたので、ioremap_cache() を使用してカーネル空間にマップしますか?

于 2013-06-28T19:33:12.077 に答える