非常に簡単な質問があります。QEMU は TLB をエミュレートしますか? ゲスト Linux システムが「invlpg」命令をそのまま TLB エントリの無効化のために実行するとどうなるか。QEMUには、ゲスト仮想アドレスをホスト仮想アドレスに変換するために使用されるsoftmmuリンクがありますが、QEMUは実際のTLBをエミュレートし、「invlpg」命令の影響は何ですか。それとも、QEMU は単にこの命令を無視するのでしょうか?
2 に答える
答えは「はい」と「いいえ」の間のどこかにあります。QEMU は、実際のゲスト CPU の TLB (ゲストの仮想アドレスからゲストの物理アドレスへのルックアップを高速化するハードウェアの一部) をエミュレートしようとしません。ただし、TLB と呼ばれる独自のかなり類似したデータ構造を実装しています。これにより、ゲスト仮想アドレスから RAM のホスト仮想アドレスへの直接のルックアップ、またはゲスト仮想アドレスからエミュレートされたデバイスの読み取り/書き込み関数へのルックアップが高速化されます。
CPU TLB と QEMU の TLB には類似点があるため、QEMU TLB の無効化を実行するトリガーとして、ゲスト命令を使用して TLB を無効化または操作することができます (これは helper_invlpg() の tlb_flush_page() 呼び出しが行っていることです)。 ; したがって、これらの手順は単純なノーオペレーションではありません。また、ゲストがキャッシュと TLB 情報を照会する cpuid 命令を使用している場合、ゲストに嘘をつき、TLB のサイズについてもっともらしいことを伝えます。ただし、実際にはゲスト TLB をモデル化していないため、ゲスト TLB のサイズに関するパフォーマンスの変化は見られず、ゲスト TLB のヒットとミスに関する情報をログに記録することはできず、TLB ロックダウンは実装されていません。それを持つCPUアーキテクチャで。
最後に、モニターの「info tlb」コマンドは、TLB 状態とは関係のないゲストのページ テーブル設定に関する情報を実際に表示しているため、かなり誤った名前になっています。
QEMU は TLB をエミュレートしますか?
はい。
QEMU モニター コンソールは、次のinfo tlb
コマンドを提供します。
TLB (Translation Lookaside Buffer) をリストします。つまり、物理メモリと仮想メモリの間のマッピングです。
CPU エミュレーションのドキュメントには、次のセクションがあります。
ページ キャッシュは、QEMU ソースでは「TLB」と呼ばれます。
ソースコードにtarget-i386/cpu.c
は、TLB に関連する次の定義が含まれています。
/* TLB definitions: */
#define L1_DTLB_2M_ASSOC 1
#define L1_DTLB_2M_ENTRIES 255
#define L1_DTLB_4K_ASSOC 1
#define L1_DTLB_4K_ENTRIES 255
#define L1_ITLB_2M_ASSOC 1
#define L1_ITLB_2M_ENTRIES 255
#define L1_ITLB_4K_ASSOC 1
#define L1_ITLB_4K_ENTRIES 255
#define L2_DTLB_2M_ASSOC 0 /* disabled */
#define L2_DTLB_2M_ENTRIES 0 /* disabled */
#define L2_DTLB_4K_ASSOC 4
#define L2_DTLB_4K_ENTRIES 512
#define L2_ITLB_2M_ASSOC 0 /* disabled */
#define L2_ITLB_2M_ENTRIES 0 /* disabled */
#define L2_ITLB_4K_ASSOC 4
#define L2_ITLB_4K_ENTRIES 512
では、命令target-i386/translate.c
を処理する次のコードが表示されます。INVLPG
case 7:
if (mod != 3) { /* invlpg */
if (s->cpl != 0) {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else {
gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base);
gen_lea_modrm(env, s, modrm);
gen_helper_invlpg(cpu_env, cpu_A0);
gen_jmp_im(s->pc - s->cs_base);
gen_eob(s);
}
}
gen_helper_invlpg
に実装されていtarget-i386/misc_helper.c
ます:
void helper_invlpg(CPUX86State *env, target_ulong addr)
{
X86CPU *cpu = x86_env_get_cpu(env);
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
tlb_flush_page(CPU(cpu), addr);
}
tlb_flush_page
で実装されている を呼び出す場所cputlb.c
。
はい、INVLPG
命令がアドレスのTLBをフラッシュすることがわかります。