これは ARM 用です。
GCC は __builtin___clear_cache
を提供します 行う syscall cacheflush
を実行する必要があります .ただし、注意点がある場合があります。
ここで重要なことは、Linux がキャッシュをフラッシュするためのシステム コール (ARM 固有) を提供していることです。このシステム コールの使用方法については、Android/Bionic の flushcache を参照してください。ただし、Linux を呼び出したときに Linux がどのような保証を提供するのか、内部の仕組みを通じてどのように実装されるのかはわかりません。
このブログ投稿キャッシュと自己変更コードがさらに役立つ場合があります。
Linux カーネルで使用可能なフラッシュ方法のリストについては、このページを確認してください:https://www.kernel.org/doc/Documentation/cachetlb.txt
<ブロック引用>Linux でのキャッシュと TLB のフラッシュ。デビッド・S・ミラー
範囲フラッシュ関数のセットがあります
2) flush_cache_range(vma, start, end);
change_range_of_page_tables(mm, start, end);
flush_tlb_range(vma, start, end);
<ブロック引用> 3) void flush_cache_range(struct vm_area_struct *vma,unsigned long start, unsigned long end)
Here we are flushing a specific range of (user) virtual
addresses from the cache. After running, there will be no
entries in the cache for 'vma->vm_mm' for virtual addresses in
the range 'start' to 'end-1'.
関数の実装を確認することもできます - http://lxr.free-electrons.com/ident?a=sh;i=flush_cache_range
たとえば、腕の場合 - http://lxr.free-electrons.com/source/arch/arm/mm/flush.c?a=sh&v=3.13#L67
67 void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
68 {
69 if (cache_is_vivt()) {
70 vivt_flush_cache_range(vma, start, end);
71 return;
72 }
73
74 if (cache_is_vipt_aliasing()) {
75 asm( "mcr p15, 0, %0, c7, c14, 0\n"
76 " mcr p15, 0, %0, c7, c10, 4"
77 :
78 : "r" (0)
79 : "cc");
80 }
81
82 if (vma->vm_flags & VM_EXEC)
83 __flush_icache_all();
84 }
Linux の x86 バージョンでは、関数 void clflush_cache_range(void *vaddr, unsigned int size)
も見つけることができます これは、キャッシュ範囲をフラッシュする目的で使用されます。この関数は CLFLUSH
に依存しています または CLFLUSHOPT
指示。理論的にはオプションであるため、プロセッサが実際にそれらをサポートしているかどうかを確認することをお勧めします。
CLFLUSHOPT
順序が弱い。 CLFLUSH
MFENCE
のみが注文したと最初に指定されました 、しかしそれを実装するすべてのCPUは、強い順序付けでそうします。書き込みおよびその他の CLFLUSH
指示。 Intel は、新しい命令 (CLFLUSHOPT
) を追加することを決定しました。 ) CLFLUSH
の動作を変更する代わりに 、およびマニュアルを更新して、将来の CPU が CLFLUSH
を実装することを保証します。 強く命じられたように。この用途では、MFENCE
する必要があります。 いずれかを使用した後、(ストアだけでなく) ベンチマークからのロードの前にフラッシュが確実に行われるようにします。
実際、x86 には、役立つ命令がもう 1 つあります:CLWB
. CLWB
(必ずしも) データを削除せずにキャッシュからメモリにデータをフラッシュし、クリーンな状態のままキャッシュします。 clwb
SKX では clflushopt
のように削除します 、しかし
これらの命令はキャッシュ コヒーレントであることにも注意してください。それらの実行は、システム内のすべてのプロセッサ (プロセッサ コア) のすべてのキャッシュに影響します。
これら 3 つの命令はすべて、ユーザー モードで使用できます。したがって、アセンブラ (または _mm_clflushopt
のような組み込み関数) を使用できます。 ) 独自の void clflush_cache_range(void *vaddr, unsigned int size)
を作成します ユーザー空間アプリケーションで (ただし、実際に使用する前に、それらの可用性を確認することを忘れないでください)。
私の理解が正しければ、この点に関して ARM について推論するのははるかに困難です。 ARM プロセッサのファミリは、IA-32 プロセッサのファミリよりも一貫性が低くなります。 1 つの ARM にはフル機能のキャッシュがあり、別の ARM には完全にキャッシュがありません。さらに、多くのメーカーは、カスタマイズされた MMU および MPU を使用できます。そのため、特定の ARM プロセッサ モデルについて推論することをお勧めします。
残念ながら、一部のデータをフラッシュするのに必要な時間を合理的に見積もることはほとんど不可能のようです。この時間は、フラッシュされたキャッシュ ラインの数、順序付けされていない命令の実行、TLB の状態 (命令は引数として仮想アドレスを使用しますが、キャッシュは物理アドレスを使用するため)、システム内の CPU の数など、非常に多くの要因の影響を受けます。システム内の他のプロセッサでのメモリ操作に関する実際の負荷、プロセッサによって実際にキャッシュされる範囲のライン数、最後に CPU、メモリ、メモリ コントローラ、およびメモリ バスのパフォーマンス。その結果、実行時間は環境や負荷によって大きく異なると思います。唯一の妥当な方法は、ターゲット システムと同様の負荷で、システムのフラッシュ時間を測定することです。
最後に、メモリ キャッシュと TLB を混同しないでください。どちらもキャッシュですが、異なる方法で編成され、異なる目的を果たします。 TLB は、仮想アドレスと物理アドレスの間で最近使用された変換のみをキャッシュしますが、そのアドレスが指すデータはキャッシュしません。
また、メモリ キャッシュとは対照的に、TLB はコヒーレントではありません。 TLB エントリをフラッシュしても、メモリ キャッシュから適切なデータがフラッシュされないため、注意してください。