コラム4

KVMの実装の特徴

KVMは、先に述べたような困難に対処する為に、次のようなものを導入しています。

 

  • shadow page
    struct kvm_mmu_pageで記述されます。
  • shadow hash table: (gfn, role) -> shadow page
    gfnまたは(gfn, role)のペアをkeyとして対応するshadow pageを検索します。hash値はgfnをベースに計算されます。(roleについては後述)これによりshadowしているページに変更があった際に変更しなければならないshadow pageを高速に検索します。
  • rmap: reverse mapping
    gfn -> parent spte
    gfnで示されるpageをmapしている全てのshadow page entryを覚えておきます。1 shadow page entryだけの場合は最適化されており、メモリを使わなくていいようになっています。2 shadow page entry以上の場合は、struct kvm_rmap_descを使用してlinked listを作成します。
    あるページをshadowし始める場合、ページをread onlyでwrite protectする必要があります。それを効率的に行う為に使用されます。
  • parent pte
    shadow page -> parent spte
    struct kvm_mmu_pageで示されるshadow pageをmapしている全てのshadow page entryを得ます。shadow pageをwrite protectしたりzapする際に使用されます。
    これもrmapの場合と同様に1 parent shadow page entryの場合は最適化されており、メモリを使わないようになっています。2 shadow page entry以上の場合はlinked listを使用します。

上記のhash table, reverse mapping, parent_pteの関係を【 図4 hash tables 】に示します。

 

 
  • role
    図5 roleroleとはshadow pageがpage tableの中でどういった役割を果たしているかを示すもので、struct kvm_mmu_page_roleで記述されます。KVMではあるgfnに対して複数のshadowを作成ことがあります。正確にはroleが違うものに対して違ったshadowを作成します。

 

 
  • guest physical address => host physical address変換
    struct vmaが実際の変換テーブルとなっています。struct pageを得る為にget_user_page()が使用されます。
  • lru list
    shadow pageを使い回すためにlru listにつなぎます。
    struct kvm_arch::active_mmu_page及びstruct kvm_mmu_page::linkを使います。

shadow pagingについて解説を行ったあとに、KVMにおける実装を概観しました。その他の機能についてはまたの機会に解説します。