コラム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における実装を概観しました。その他の機能についてはまたの機会に解説します。