誰もこれに答えていないことに本当に驚いているので、ここでは非 Linux 固有の答えに進みます (より具体的にするには、Linux カーネル自体について十分な知識がありません) ...
キャッシュ スヌーピングは、DMA コントローラーに、DMA されるメモリのすべての CPU にキャッシュ無効化要求を送信するように指示するだけです。これは明らかにキャッシュ コヒーレンシ バスに負荷を追加し、すべての CPU がスヌープを発行する DMA コントローラーとのシングル ホップ接続を持つわけではないため、プロセッサを追加すると特にスケールが悪くなります。したがって、「キャッシュ スヌーピングを無効にしても安全な場合」に対する簡単な答えは、DMA されるメモリがどの CPU キャッシュにも存在しないか、そのキャッシュ ラインが無効としてマークされている場合です。つまり、DMA 領域からの読み取りを試みると、常にメイン メモリからの読み取りになります。
では、DMA 領域からの読み取りが常にメイン メモリに行われるようにするにはどうすればよいでしょうか?
DMA キャッシュ スヌーピングのような高度な機能が登場する前の時代、私たちが行っていたのは、次のように分割された一連のステージを介して DMA メモリを供給することで、DMA メモリをパイプライン化することでした。
ステージ 1: 「ダーティでクリーニングが必要な」DMA メモリ リストに「ダーティ」DMA メモリ領域を追加します。
ステージ 2: 次回、デバイスが新しい DMA 処理されたデータで割り込みを行うとき、それらのブロックにアクセスする可能性のあるすべての CPU (多くの場合、各 CPU はそのローカルメモリブロックで構成される独自のリスト)。上記のセグメントを「クリーン」リストに移動します。
ステージ 3: 次の DMA 割り込み (もちろん、前のキャッシュの無効化が完了する前に発生しないことは確かです)、「クリーン」リストから新しい領域を取得し、次の DMA がそれに入る必要があることをデバイスに伝えます。汚れたブロックをリサイクルします。
ステージ 4: 繰り返します。
これは手間がかかる分、いくつかの大きな利点があります。まず、DMA 処理を単一の CPU (通常はプライマリ CPU0) または単一の SMP ノードにピン留めできます。つまり、単一の CPU/ノードだけがキャッシュの無効化について心配する必要があります。次に、時間の経過とともに操作の間隔を空け、キャッシュ コヒーレンシ バスの負荷を分散することで、メモリ サブシステムがメモリのレイテンシを隠す機会を大幅に増やします。パフォーマンスの鍵は、一般に、関連する DMA コントローラにできるだけ近い CPU で DMA を発生させ、その CPU にできるだけ近いメモリに発生させることです。
新しく DMA されたメモリを常にユーザー空間や他の CPU に渡す場合は、非同期キャッシュ無効化パイプラインの前に新しく取得したメモリを挿入するだけです。一部のOS(Linuxについては不明)には、ゼロ化されたメモリを事前注文するための最適化されたルーチンがあるため、OSは基本的にバックグラウンドでメモリをゼロ化し、迅速な満足キャッシュを維持します。は非常に遅いです。ハードウェア オフロード メモリのゼロ化を使用する過去 10 年間に作成されたプラットフォームを認識していないため、すべての新しいメモリには、無効化が必要な有効なキャッシュ ラインが含まれている可能性があると想定する必要があります。
これがあなたの質問の半分にしか答えていないことを感謝しますが、何もないよりはましです. 幸運を!
ニール