X86/x86_64アーキテクチャーのすべての最新の高性能CPUには、データキャッシュの階層がいくつかあります。L1、L2、場合によってはL3(および非常にまれなケースではL4)で、メインRAMからロードされるデータはそれらのいくつかにキャッシュされています。
プログラマーは、一部のデータを一部またはすべてのキャッシュレベルでキャッシュしないようにする場合があります(たとえば、16 GBのRAMをmemsetして、一部のデータをキャッシュに保持したい場合)。 MOVNTDQA( https://stackoverflow.com/a/37092http://lwn.net/Articles/255364/ )のようなこれに対する一時的な(NT)命令
しかし、プログラムによって(P3、P4、Core、Core i *などの一部のAMDまたはIntel CPUファミリの場合)キャッシュの一部またはすべてのレベルを完全に(ただし一時的に)オフにして、すべてのメモリの方法を変更する方法はありますか?アクセス命令(グローバルまたは一部のアプリケーション/ RAMの領域)はメモリ階層を使用しますか?たとえば、L1をオフにし、L1とL2をオフにしますか?または、すべてのメモリアクセスタイプを「キャッシュされていない」UC(CR0のCD + NWビット??? SDM vol3aページ 42424 、 425 および"第3レベルのキャッシュ無効化フラグ、IA32_MISC_ENABLE MSRのビット6(Intel NetBurstマイクロアーキテクチャーに基づくプロセッサーでのみ使用可能)— L1とは無関係に、L3キャッシュを無効化および有効化できます。 L2キャッシュ。 ")。
このようなアクションは、AESキーの盗用、隠れたキャッシュチャネル、Meltdown/Spectreなどのキャッシュサイドチャネル攻撃/リークからデータを保護するのに役立つと思います。ただし、これを無効にすると、パフォーマンスコストが非常に高くなります。
PS:私はそのようなプログラムを何年も前にいくつかのテクニカルニュースWebサイトに掲載したことを覚えていますが、今は見つかりません。いくつかの魔法の値をMSRに書き込み、すべてのWindowsプログラムの実行を非常に遅くするのは単なるWindows exeでした。再起動するまで、または「元に戻す」オプションを使用してプログラムを起動するまで、キャッシュはオフにされていました。
Intelのマニュアル3A 、セクション11.5.3は、globallyキャッシュを無効にするアルゴリズムを提供します。
11.5.3キャッシングの防止
L1、L2、およびL3キャッシュを有効にして、キャッシュフィルを受け取った後に無効にするには、次の手順を実行します。
- No-fillキャッシュモードに入ります。 (制御レジスタCR0のCDフラグを1に、NWフラグを0に設定します。
- WBINVD命令を使用してすべてのキャッシュをフラッシュします。
- MTRRを無効にし、デフォルトのメモリタイプを非キャッシュに設定するか、キャッシュされていないメモリタイプのすべてのMTRRを設定します(セクション11.11.2.1「IA32_MTRR_DEF_TYPE MSR」のTYPEフィールドとEフラグの説明を参照してください)。
システムメモリーの一貫性を確保するために、CDフラグを設定した後、キャッシュをフラッシュする必要があります(手順2)。キャッシュがフラッシュされない場合でも、読み取り時にキャッシュヒットが発生し、有効なキャッシュラインからデータが読み取られます。
上記の3つの個別のステップの目的は、3つの異なる要件に対処します:(i)キャッシュ内の既存のデータを置き換える新しいデータを中止する(ii)キャッシュ内の既存のデータがメモリに強制的に削除されるようにする、(iii)後続のメモリ参照がUCメモリを監視するようにするタイプのセマンティクス。キャッシング制御ハードウェアの異なるプロセッサー実装により、これら3つの要件のソフトウェア実装にいくつかのバリエーションが可能になる場合があります。以下の注を参照してください。
[〜#〜] notes [〜#〜]コントロールレジスタCR0にCDフラグを設定すると、表11-5に示すように、プロセッサのキャッシュ動作が変更されます。ただし、CDフラグを設定するだけでは、すべてのプロセッサファミリで十分ではなく、すべての物理メモリの実効メモリタイプをUCに強制したり、厳密なメモリ順序を強制したりすることはできません。すべての物理メモリでUCメモリタイプと厳密なメモリ順序を強制するには、すべての物理メモリのMTRRをUCメモリタイプにプログラムするか、すべてのMTRRを無効にするだけで十分です。
Pentium 4およびIntel Xeonプロセッサの場合、上記の一連のステップが実行された後、WBINVD命令の最後とMTRRSが実際に無効になる前のコードを含むキャッシュラインは、キャッシュ階層に保持される場合があります。ここで、キャッシュからコードを完全に削除するには、MTRRを無効にした後で、2番目のWBINVD命令を実行する必要があります。
それは長い引用ですが、このコードに要約されます
;Step 1 - Enter no-fill mode
mov eax, cr0
or eax, 1<<30 ; Set bit CD
and eax, ~(1<<29) ; Clear bit NW
mov cr0, eax
;Step 2 - Invalidate all the caches
wbinvd
;All memory accesses happen from/to memory now, but UC memory ordering may not be enforced still.
;For Atom processors, we are done, UC semantic is automatically enforced.
xor eax, eax
xor edx, edx
mov ecx, IA32_MTRR_DEF_TYPE ;MSR number is 2FFH
wrmsr
;P4 only, remove this code from the L1I
wbinvd
そのほとんどはユーザーモードから実行できません。
AMD's manual 2 セクション7.6.2で同様のアルゴリズムを提供します
7.6.2キャッシュ制御メカニズム
AMD64アーキテクチャは、メモリのキャッシュ可能性を制御するための多数のメカニズムを提供します。これらについては、次のセクションで説明します。キャッシュ無効化。 CR0レジスタのビット30は、キャッシュ無効化ビットCR0.CDです。 CR0.CDが0にクリアされるとキャッシングが有効になり、CR0.CDが1に設定されるとキャッシングが無効になります。キャッシングが無効になると、メインメモリの読み取りと書き込みが行われます。
キャッシュが有効なデータ(または命令)を保持している間、ソフトウェアはキャッシュを無効にすることができます。 CR0.CD = 1のときに、読み取りまたは書き込みがL1データキャッシュまたはL2キャッシュにヒットすると、プロセッサは次のことを行います。
- キャッシュラインが変更または所有されている場合、キャッシュラインを書き戻します。
- キャッシュラインを無効にします。
- キャッシュ不可のメインメモリアクセスを実行して、データの読み取りまたは書き込みを行います。
CR0.CD = 1のときに命令フェッチがL1命令キャッシュにヒットすると、一部のプロセッサモデルはメインメモリにアクセスするのではなく、キャッシュされた命令を読み取る場合があります。 CR0.CD = 1の場合、L2およびL3キャッシュの正確な動作はモデルに依存し、メモリアクセスの種類によって異なる場合があります。
CR0.CD = 1の場合、プロセッサはキャッシュプローブにも応答します。プローブがキャッシュにヒットすると、プロセッサはステップ1を実行します。ステップ2(キャッシュラインの無効化)は、メモリの書き込みまたは排他的な読み取りの代わりにプローブが実行された場合にのみ実行されます。
Writethrough Disable。 CR0レジスタのビット29は、ライトスルー無効化ビットCR0.NWです。初期のx86プロセッサでは、CR0.NWはキャッシュのライトスルー動作を制御するために使用され、CR0.NWとCR0.CDの組み合わせがキャッシュの動作モードを決定します。
[...]
AMD64アーキテクチャーの実装では、CR0.CDによって確立されたキャッシュ動作モードを修飾するためにCR0.NWは使用されません。
これは次のコードに変換されます(Intelのものと非常に似ています)。
;Step 1 - Disable the caches
mov eax, cr0
or eax, 1<<30
mov cr0, eax
;For some models we need to invalidated the L1I
wbinvd
;Step 2 - Disable speculative accesses
xor eax, eax
xor edx, edx
mov ecx, MTRRdefType ;MSR number is 2FFH
wrmsr
キャッシュは、次の場所でも選択的に無効にできます。
IA32_PAT
キャッシングタイプを使用し、ビットPAT、PCD、PWTを3ビットインデックスとして使用すると、6つのキャッシングタイプ(UC-、UC、WC、WT、WP、WB)の1つを選択できます。これらのオプションのうち、ページ属性のみをユーザーモードプログラムに公開できます(例 this を参照)。