web-dev-qa-db-ja.com

Linuxでアドレス空間の領域のCPUキャッシュをフラッシュする方法は?

アドレス空間の領域、たとえばアドレスAからアドレスBへのすべてのキャッシュエントリに対してのみキャッシュ(L1、L2、およびL3)をフラッシュすることに興味があります。Linuxでユーザーまたはカーネル空間からフラッシュするメカニズムはありますか? ?

14
aminfar

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 }
10
osgx

これはARM用です。

GCCは __builtin___clear_cache これ しますかsyscall cacheflush を実行する必要があります。ただし、 警告 の場合があります。

ここで重要なのは、Linuxがキャッシュをフラッシュするためのシステムコール(ARM固有)を提供することです。このシステムコールの使用方法については、Android/Bionic flushcache を確認できます。ただし、Linuxを呼び出すときにどのような保証が提供されるのか、またはLinuxが内部動作を通じてどのように実装されるのかはわかりません。

このブログ投稿 キャッシュと自己変更コード はさらに役立つかもしれません。

7
auselen

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つの命令を提供します: CLWBCLWBは、データを(必要に応じて)削除せずにキャッシュからメモリにフラッシュし、クリーンなままでキャッシュされたままにします。 SKXのclwbclflushoptのように立ち退きますが

これらの命令はキャッシュコヒーレントであることにも注意してください。それらの実行は、システム内のすべてのプロセッサ(プロセッサコア)のすべてのキャッシュに影響します。

これら3つの命令はすべて、ユーザーモードで使用できます。したがって、アセンブラ(または__mm_clflushopt_などの組み込み関数)を使用して、ユーザースペースアプリケーションで独自のvoid clflush_cache_range(void *vaddr, unsigned int size)を作成できます(ただし、実際に使用する前に、それらの可用性を確認することを忘れないでください)。


私が正しく理解していれば、この点に関してARMについて推論することははるかに困難です。 ARMプロセッサのファミリは、IA-32プロセッサのファミリよりもはるかに一貫性がありません。 1つはフル機能のキャッシュを備えたARMで、もう1つは完全にキャッシュを備えていないものです。さらに、多くのメーカーはカスタマイズされたMMUおよびMPUを使用できます。したがって、特定のARMプロセッサモデルについて推論することをお勧めします。

残念ながら、一部のデータをフラッシュするために必要な時間の合理的な見積もりを実行することはほとんど不可能であるように思われます。この時間は、フラッシュされるキャッシュラインの数、命令の順序付けられていない実行、TLBの状態(命令は仮想アドレスを引数として取りますが、キャッシュは物理アドレスを使用するため)、システム内のCPUの数など、非常に多くの要因の影響を受けます。システム内の他のプロセッサでのメモリ操作に関する実際の負荷、および範囲内の行数が実際にプロセッサによってキャッシュされ、最後にCPU、メモリ、メモリコントローラ、およびメモリバスのパフォーマンスによってキャッシュされます。その結果、実行時間は環境や負荷によって大きく異なると思います。唯一の合理的な方法は、システム上で、ターゲットシステムと同様の負荷でフラッシュ時間を測定することです。


最後に、メモリキャッシュとTLBを混同しないでください。これらは両方ともキャッシュですが、さまざまな方法で編成され、さまざまな目的を果たします。 TLBは、仮想アドレスと物理アドレスの間で最近使用された変換をキャッシュしますが、そのアドレスが指すデータはキャッシュしません。

また、メモリキャッシュとは対照的に、TLBはコヒーレントではありません。 TLBエントリのフラッシュは、メモリキャッシュからの適切なデータのフラッシュにはつながらないため、注意してください。

4
ZarathustrA

何人かの人々がclear_cacheについて不安を表明しています。以下は、非効率的ですが、任意のユーザースペースタスク(任意のOS)から可能であるキャッシュを削除するための手動プロセスです。


PLD/LDR

mis-pld命令を使用して、キャッシュを削除することができます。 pldはキャッシュラインをフェッチします。特定のメモリアドレスを削除するには、キャッシュの構造を知る必要があります。たとえば、cortex-a9には、1行あたり8ワードの4ウェイデータキャッシュがあります。キャッシュサイズは、16KB、32KB、または64KBに構成できます。つまり、512、1024、または2048行です。方法は常に下位アドレスビットにとって重要ではありません(したがって、シーケンシャルアドレスは競合しません)。したがって、memory offset + cache size / waysにアクセスして新しい方法を入力します。つまり、cortex-a9の場合は4KB、8KB、16KBごとです。

'C'または 'C++'でldrを使用するのは簡単です。配列のサイズを適切に設定してアクセスするだけです。

参照: プログラムでキャッシュラインサイズを取得しますか?

たとえば、0x12345を削除する場合、行は0x12340で始まり、16KBのラウンドロビンキャッシュの場合はpld on0x133400x143400x15340、および0x16340は、その方法で任意の値を削除します。同じプリンシパルをエビクトL2(多くの場合統合されている)に適用できます。すべてのキャッシュサイズを繰り返すと、キャッシュ全体が削除されます。キャッシュ全体を削除するには、キャッシュのサイズの未使用のメモリを割り当てる必要があります。これはL2ではかなり大きいかもしれません。 pldを使用する必要はありませんが、フルメモリアクセス(ldr/ldm)を使用します。複数のCPU(スレッド化されたキャッシュエビクション)の場合、各CPUでエビクションを実行する必要があります。通常、L2はすべてのCPUに対してグローバルであるため、実行する必要があるのは1回だけです。

NB:このメソッドは[〜#〜] lru [〜#〜](最近使用されていない)またはラウンドロビンキャッシュ。疑似ランダム置換の場合、エビクションを確実にするために、より多くのデータを読み書きする必要があります。正確な量はCPU固有です。 ARMランダム置換は、CPUに応じて8〜33ビットのLFSRに基づいています。一部のCPUでは、デフォルトでround-robinなどはデフォルトでpseudo-randomモードになります。一部のCPUでは、Linuxカーネル構成がモードを選択します。 参照: CPU_CACHE_ROUND_ROBIN ただし、新しいCPUの場合、Linuxはブートローダーやシリコンのデフォルトを使用します。言い換えると、完全に汎用的である必要がある場合、またはキャッシュを確実にクリアするために多くの時間を費やす必要がある場合は、clear_cache OS呼び出しを機能させるように試みる価値があります(他の回答を参照)。

コンテキストスイッチ

一部のMMU CPUおよび特定のOSではARM)を使用してOSをだますことにより、キャッシュを回避することができます。* nixシステムでは、複数のプロセスが必要です。 。プロセスを切り替える必要があり、OSはキャッシュをフラッシュする必要があります。通常、これは、OSがキャッシュをフラッシュする必要がある古いARM CPU(pldをサポートしないCPU)でのみ機能します)プロセス間で情報が漏洩しないようにするため。移植性がなく、OSについて十分に理解している必要があります。

ほとんどの明示的なキャッシュフラッシュレジスタは、プロセス間のサービス拒否タイプの攻撃を防ぐためにシステムモードに制限されています。一部のエクスプロイトは、他のプロセスによって削除された行を確認することで情報を取得しようとする可能性があります(これにより、別のプロセスがアクセスしているアドレスに関する情報が得られます)。これらの攻撃は、疑似ランダム置換を使用するとより困難になります。

3
artless noise

X86では、キャッシュ階層全体をフラッシュするためにこれを使用できます

native_wbinvd()

これはArch/x86/include/asm /special_insns.hで定義されています。その実装を見ると、WBINVD命令を呼び出すだけです。

static inline void native_wbinvd(void)
{
        asm volatile("wbinvd": : :"memory");
}

[〜#〜] wbinvd [〜#〜] X86命令を実行するには、特権モードである必要があることに注意してください。これは、単一のキャッシュラインをクリアし、呼び出し元が特権モードである必要がない[〜#〜] clflush [〜#〜] x86命令とは対照的です。

X86 Linuxカーネルコードを見ると、この命令のほんの一握り(私がこれを書いているときは6か所)しか見えません。これは、そのシステムで実行されているすべてのエンティティの速度が低下するためです。 100MBLLCのサーバーでこれを実行することを想像してみてください。この命令は、100MB以上をキャッシュからRAMに移動することを意味します。さらに、この命令は中断できないことに気づきました。したがって、その使用法は、RTシステムの決定論に大きな影響を与える可能性があります。

(元の質問は特定のアドレス範囲をクリアする方法について尋ねていますが、キャッシュ階層全体をクリアすることに関する情報も一部の読者にとって役立つと思いました)

1
jithu83