DMA 操作中のキャッシュ データのフラッシュ

一部のプラットフォームでは、プロセッサとシステム DMA コントローラー (またはバス マスター DMA アダプター) がキャッシュの一貫性の異常を示します。 以下のガイドラインに従うと、DMA 操作インターフェイスのバージョン 1 または 2 を使用するドライバー (DMA_OPERATIONS を参照) が、サポートされているすべてのプロセッサ アーキテクチャ (キャッシュの一貫性を自動的に適用するハードウェアを含まないアーキテクチャを含む) にわたって一貫性のあるキャッシュ状態を維持できるようになります。

このトピックのガイドラインは、DMA 操作インターフェイスのバージョン 1 とバージョン 2 を使用するドライバーにのみ適用されます。 このインターフェイスのバージョン 3 を使用するドライバーは、別のガイドライン セットに従う必要があります。 詳しくは、「DMA 操作インターフェイスのバージョン 3」をご覧ください。

DMA 操作中にデータ整合性を維持するには、最下位レベルのドライバーが以下のガイドラインに従う必要があります

  1. 転送操作を開始する前に KeFlushIoBuffers を呼び出し、プロセッサにキャッシュされる可能性があるデータとメモリ内のデータの整合性を維持します。

    ドライバーは、CacheEnabled パラメーターを TRUE に設定した状態で AllocateCommonBuffer を呼び出した場合、バッファーとの間で転送操作を開始する前に KeFlushIoBuffers を呼び出す必要があります。

  2. 各デバイス転送操作の終了時に FlushAdapterBuffers を呼び出して、システム DMA コントローラーのバッファー内の残りのバイトがメモリまたは下位デバイスに書き込まれていることを確認します。

    または、特定の IRP の各転送操作の最後に FlushAdapterBuffers を呼び出し、すべてのデータがシステム メモリに読み取られたか、バス マスター DMA デバイスに書き出されたことを確認します。

次の図は、ホスト プロセッサと DMA コントローラーがキャッシュの一貫性を自動的に維持しない場合、DMA を使用した読み取りまたは書き込み操作の前にプロセッサ キャッシュをフラッシュすることが重要な理由を示しています。

diagram illustrating read and write operations using dma.

非同期 DMA の読み取りまたは書き込み操作は、プロセッサ キャッシュではなくメモリ内のデータにアクセスします。 読み取りの直前に KeFlushIoBuffers を呼び出してこのキャッシュがフラッシュされた場合を除き、後でプロセッサ キャッシュがフラッシュされると、DMA 操作によってシステム メモリに転送されたデータが古いデータで上書きされる可能性があります。 書き込みの直前に KeFlushIoBuffers を呼び出してプロセッサ キャッシュがフラッシュされた場合を除き、このキャッシュ内のデータはメモリ内のコピーよりも最新である可能性があります。

キャッシュの一貫性を維持する点でプロセッサと DMA コントローラーに依存できる場合、KeFlushIoBuffers は何も行わないため、このサポート ルーチンの呼び出しによるオーバーヘッドは、このようなプラットフォームにおいてほとんどありません。

前の図に示すように、アダプター オブジェクトで表される DMA コントローラーには内部バッファーを含めることができます。 このような DMA コントローラーは、キャッシュされたデータを固定サイズのチャンクで転送できます (通常は一度に 8 バイト以上)。 さらに、これらの DMA コントローラーは、各転送操作の前に、内部バッファーがいっぱいになるまで待機できます。

下位 DMA を使用して、システム DMA コントローラーのキャッシュ サイズの整数倍数ではない可変サイズのチャンクまたは固定サイズのチャンクでデータを読み取る最下位レベルのドライバーのケースを考えてみましょう。 このドライバーが各デバイス転送の最後に FlushAdapterBuffers を呼び出した場合を除き、ドライバーが実際に要求したすべてのバイトが転送されるタイミングを確認することはできません。

バス マスター DMA デバイスのドライバーも、すべてのデータがシステム メモリまたはデバイスに転送されたことを確認するため、IRP の各転送操作の終了時に FlushAdapterBuffers を呼び出す必要があります。

FlushAdapterBuffers は、要求されたフラッシュ操作が成功したかどうかを示すブール値を返します。 DMA の読み取りまたは書き込み操作の IRP を完了するとき、ドライバーが I/O 状態ブロックを設定する方法を決定するには、この値を使用できます。