7

Linuxカーネルでは、copy_page_range(mm / memory.c)に似たコードを記述したため、COW最適化を使用してあるプロセスから別のプロセスにメモリをコピーします。宛先アドレスと送信元アドレスはによってオフセットすることができPAGE_SIZE、COWは引き続き機能します。ただし、ユーザープログラムで、同じ送信元アドレスから別の宛先アドレスにコピーすると、TLBが適切にフラッシュされていないように見えることに気付きました。高レベルでは、ユーザーレベルのコードは次のことを行います(一度に1ページ、0x1000バイトをマシンにコピーします)。

SRC = 0x20000000

  1. SRCに書き込みます(関連するページを呼び出しますpage1)。
  2. 宛先プロセスでSRCを0x30000000にコピーするSyscall。これで、srcプロセスアドレス0x20000000と宛先プロセスアドレス0x30000000が同じページを指します(page1)。
  3. SRCとは異なるものを記述します(これにより、COWを処理するためのページフォールトがトリガーされます)。送信元アドレスがを指していると仮定しpage2ます。
  4. 宛先プロセスでSRCを0x30001000にコピーするシステムコール。

この時点で、2つの別々のページが存在する必要があります。SRC0x20000000 page2 DST 0x30000000 page1 DST 0x30001000page2

手順3で、src 0x20000000に別の何かを書き込んでも、ページフォールトは生成されないことがわかりました。検査すると、実際のページマッピングは次のようになります。SRC0x20000000 page1 DST 0x30000000 page1 DST 0x30001000page1

私のコードではflush_tlb_page、送信元アドレスを呼び出して渡すと、ユーザーコードは適切なページマッピングで期待どおりに機能します。したがって、TLBを正しく維持していないと確信しています。ではcopy_page_range、カーネルはmmu_notifier_invalidate_range_start/endページテーブルを変更する前後に呼び出します。私はまったく同じことをしていて、実際に正しいstruct_mmとアドレスをに渡していることを再確認しましたmmu_notifier_invalidate_range_start/end。この関数はtlbのフラッシュを処理しませんか?

さて、文字通りこれを入力し終えたとき、私はチェックして、dup_mmapの主要な呼び出し元(kernel / fork.c)が。を呼び出すことに気づきました。カーネルコードの前後に呼び出す必要があると思います。これは正しいです?正確には何をしますか?copy_page_rangedup_mmapflush_tlb_mmflush_cache_rangeflush_tlb_rangemmu_notifier_invalidate_range_start/end

4

1 に答える 1

9

はい、ページテーブルを変更する何かをしている場合は、必要に応じてTLBが無効になっていることを確認する必要があります。

mmu_notifier_invalidate_range_start/endMMU通知フックを呼び出しているだけです。これらのフックは、TLBの無効化が発生したときに他のカーネルコードに通知できるようにするためにのみ存在します。MMU通知機能を設定する場所は次のとおりです。

  • KVM(ハードウェア支援仮想化)は、それらを使用してページのスワップアウトを処理します。仮想化されたゲストMMUをホストと同期させるには、ホストTLBの無効化について知る必要があります。
  • GRU(巨大なSGIシステムの特殊なハードウェア用のドライバー)は、MMU通知機能を使用して、GRUハードウェアのマッピングテーブルをCPUMMUと同期させます。

ただし、MMU通知フックを呼び出しているほとんどすべての場所で、カーネルがまだTLBシュートダウン関数を呼び出していない場合は、TLBシュートダウン関数も呼び出す必要があります。

于 2011-12-05T07:14:04.710 に答える