エンジニアなら知っておきたい仮想マシンのしくみ

第4回 x86プロセッサにおけるプロセッサ仮想化

この記事を読むのに必要な時間:およそ 3 分

これまで,x86システム仮想マシンの概要,およびその実例としてDebian GNU/Linux 6.0を利用した仮想マシンの実行方法について紹介してきました。今回からは,より具体的にCPU,メモリ,I/Oデバイスの仮想化がどうやって実現されているかを解説したいと思います。

今回は,仮想マシンを実装するための古典的手法およびそれを従来のx86プロセッサに適用する際の問題点,そして仮想マシンソフトウェアがどのようにそれらの障壁を乗り越えてきたかについて解説します。

システム仮想マシンに求められる条件

これまで,システム仮想マシンはどのようなものかについて説明してきましたが,仮想化仮想化の生みの親とも言えるGoldbergらは,1974年に書いた論文にて,仮想マシンソフトウェアとはどのようなものであるべきかについて,コンピュータアーキテクチャの観点から論じています。

彼らは,その仮想マシンソフトウェアを「仮想マシンモニタ」と呼びました。そして,仮想マシンモニタがどのような物であるべきか,次のように説明しています。

プログラムを実行した結果,物理マシンと等しい結果が得られること
あるプログラムを仮想マシン上で実行したとき,それは物理マシンで動かしたと同じ動作をしなければなりません。これにより,仮想マシンは,物理マシンのために作成されたプログラムがそのまま実行できるものであることを求めています。
仮想マシン上の命令の実行効率が高いこと
仮想マシン上でソフトウェアが実行される場合も,プログラムが実プロセッサにより直接実行されなければならなりません。これは,仮想マシンを利用した場合に著しい性能劣化が生じてはいけない,という点からの要求です。
リソースコントロールが可能であること
仮想マシンモニタが全てのハードウェア資源を掌握し,仮想マシンに必要な分量のリソースだけを割り当てできなくてはいけません。また,割り当てたリソースを仮想マシンモニタが回収できなくてはいけません。

仮想マシンのしくみ:trap-and-emulateによる仮想マシンの実現

このような仮想マシンを実現するために,40年近く前から用いられてきたのがtrap-and-emulate,すなわち,⁠仮想マシン内で何か都合が悪い事が起きた時だけ仮想マシンモニタが介入し,エミュレートする方式」です。

当時から,多くのプロセッサにメモリやハードウェアリソースの保護機能が実装されています。保護機能を利用して,ユーザモードのプログラムがシステム全体にとって都合が悪い(かもしれない)処理をしようとした時に,プロセッサがオペレーティングシステムに制御を移し,オペレーティングシステムがその状況にどう対応するか(プログラムを強制終了させるか,など)を決定できるようになっています。このような保護機能をオペレーティングシステムにも適用し,仮想マシンモニタでオペレーティングシステムを制御することでtrap-end-emulateを実現してきました。

ゲストのオペレーティングシステムを特権がない状態で実行すると,権限が不要な処理はそのまま実行できますが,システムの状態に変更を加えたり,プロセッサに接続されたデバイスへの入出力をしたりしようとしたときにトラップが発生します。トラップが発生すると仮想マシンモニタに制御が移りますので,仮想マシンモニタはプロセッサが生成したトラップの情報やトラップが発生した場所から,トラップの原因を推測します。そして,まるで原因となった命令が「成功した」かのような状況を造りだしてから,再度ゲストのオペレーティングシステムの実行を開始します。このため,ゲストのオペレーティングシステムはそのコンピュータが物理マシンなのか仮想マシンなのかを意識することなく動作します。

図1 trap-and-emulate方式におけるプロセッサの動作

図1 trap-and-emulate方式におけるプロセッサの動作

trap-and-emulate方式による仮想マシンの実装は,仮想マシンの考え方が生まれた頃から使われている古典的な方法です。それならば,同じ方法を使えばx86プロセッサのシステムも仮想化が可能ではないか――,しかし,x86プロセッサの場合はそれが簡単に実現できない罠がありました。

x86プロセッサとプロテクトモード

第1回で若干触れましたが,x86プロセッサには,元祖8086と互換性があるリアルモードと,その後に追加された高度な機能が利用できるプロテクトモードなど複数のモードが存在します。x86プロセッサの仮想化について具体的な話を進めていく前に,リアルモードとプロテクトモードについて簡単に紹介しましょう。

リアルモード

現在使われているほとんどのx86システムは,起動直後はプロセッサはリアルモードで立ち上がり,ハードディスクからブートローダと呼ばれる小さなプログラムがロードされます。リアルモードとは8086との互換性を持つモードであり,以下のような特徴を持ちます。

  • 16ビット単位の演算操作(メモリアクセス,汎用レジスタ幅)
  • セグメント方式のメモリ管理
  • メモリ,ハードウェアアクセスの保護機能は利用できない

プロテクトモード

最近のオペレーティングシステムは,32ビットもしくは64ビットで動作し,高度なメモリ/ハードウェアアクセスの保護機能を提供していますが,リアルモードでそのような機能は実現できません。オペレーティングシステムは,システムブート後にCPUの動作モードをプロテクトモードに切り替え,プロセッサの保護機能を有効化することで,さまざまな機能を実現しています。プロテクトモードには下記のような特徴を持ちます。

  • 32ビット,64ビット単位の演算操作(メモリアクセス,汎用レジスタ幅)
  • ページ単位のメモリ管理
  • リングプロテクションによるソフトウェア間の権限切り替え
  • メモリアクセス,およびI/Oのアクセスの保護機能

著者プロフィール

長谷川猛(はせがわたけし)

(株)SRAで7年間のシステム構築&提案を経験したのち,Fusion-ioのセールスエンジニアを経て,フリーランスエンジニアとして活動中。『LDAP Super Expert』(技術評論社)に寄稿したほか,『Xen 徹底入門』(翔泳社)および『萌え萌えうにっくす!UNIX ネットワーク管理ガイド』(毎日コミュニケーションズ)の共著者のひとりである。

スノーボード,ごまラーメン,飼い犬のミニチュアシュナウザー「ラピス君」が大好き。

コメント

コメントの記入