ドメインの切り替え【後編】仮想マシンモニタ Xen 3.0解読室(2/2 ページ)

» 2007年07月11日 00時42分 公開
[高橋浩和(VA Linux Systems Japan),ITmedia]
前のページへ 1|2       

__context_switch関数

新旧ドメインのコンテキストを入れ替える部分

 さて、保留していた__context_switch関数です。この関数は、新旧ドメインのコンテキストの入れ替えを行います(リスト2)

編集部注:リストには多くの注釈線が含まれているため、画像として用意しました。上記アイコンをクリックいただくことでご覧いただけます

 current変数は、現在走行中のドメインの仮想CPUを指すという話をしました。その一方で、遅延切り替えを行っているとき、1つ前に動作していたドメインの仮想CPUのコンテキストがそのままになっています。つまり、1つ前に動作していた仮想CPUも覚えておく必要があります。x86用のXenでは、これをpercpu_ctxt[]という配列に記録するようになっています。実際のコンテキスト切り替えが必要になった場合、この配列を参照することで、どの仮想CPUとの間でコンテキストの切り替えを行えば良いかが分かります。

 percpu_ctxt[]の更新は、__context_switch関数が呼ばれたときのみ行われます(B18)。つまり、アイドルドメインへの切り替え時(A5)は、context_

switch関数が__context_switch関数を呼び出さないため、currentはアイドルドメインの仮想CPUを指す一方で、percpu_ctxt[]はその1つ前に動作していたドメインの仮想CPUを指したままになります。

 さて、__context_switch関数のコードを見ていくことにしましょう。__context_switch関数は、percpu_ctxt[]が指すコンテキスト(B1)とcurrentが指すコンテキスト(B2)の入れ替えを行います。

 古いコンテキストpが、アイドルドメインの仮想CPUを指している場合は、コンテキストの待避を省略します(B3)。逆にこれから動作するコンテキストnが、アイドルドメインの仮想CPUを指している場合は、コンテキストの復帰を省略します(B7)

 古いコンテキストpの待避処理では、まずハイパーバイザースタック上に待避されているコンテキストを、仮想CPU pの中に移します(B4)。次に浮動小数点レジスタの待避を行い、浮動小数点レジスタ演算レジスタの利用を禁止します(B5)。さらに、セグメントレジスタの待避を行います。

 これから動作するコンテキストnの復帰処理では、まず仮想CPU nからハイパーバイザースタック上にコンテキストを移動します。デバッグレジスタの設定が必要であれば(B9)、ここで設定します。

 少し面白いのは、準仮想化ドメイン時の、0x80番のソフト割り込みベクターの設定と、リング1のスタック設定です。準仮想化ドメインがシステムコールを発行したとき、Xenはこれをトラップしても何もせず、ドメインにその割り込みを伝えるだけです。そのためXenを経由せずにシステムコールを発行できるようIDTを書き換えてしまいます(B10)。int 0x80命令を実行すると、リング1で動作するドメインに直接飛び込みます*

 リングレベル1のスタックを設定(B11)しているのは、準仮想化ドメインをリングレベル1で強制的に動作させるためです。リングレベル1のスタックがカーネルスタックとして機能するようにしています。

 write_ptbase関数は、仮想空間を次に動作するドメインのものに切り替えます(B14)、ドメインの仮想空間管理については、「メモリ管理」の回で詳しく説明したいと思います)。切り替え前後の仮想CPUのIDが異なる場合は、GDT(Global Descriptor Table)の切り替えも行います(B15)。同じIDを持つ仮想CPUはGDTを共有しますが、通常同じ実CPUに割り当てられる仮想CPUのIDは同じになるため、ほとんどの場合この処理は省略されます。

 また、ドメインが利用している実CPUの情報も更新し(B12、B16)、仮想CPUが割り当てられている実CPUの情報も更新します(B13、B17)

浮動小数点演算レジスタの切り替え遅延

 先ほど、小数点演算レジスタの切り替えは遅延して行うと説明しました。これをもう少し詳しく見てみましょう。__context_switch関数の中では、unlazy_fpu関数を呼び出していました(B5)。この関数は、ドメインが浮動小数点演算を行っている場合(D1、図1の状態2)のみ、浮動小数点演算レジスタの値を仮想CPUに待避し、さらに浮動小数点演算レジスタを操作できないようアクセスを禁止します(D2、図1の状態3)

図1 図1 浮動小数点演算レジスタの状態遷移

 コンテキスト切り替えによって実行を再開したドメインは、浮動小数点レジスタへのアクセスが禁止された状態になることが分かると思います。このまま浮動小数点レジスタにアクセスせずに、再度別のドメインに切り替わる場合、__context_switch関数から呼び出されるunlazy_fpu関数は何も行いません。

 実行を再開したドメイン(図1の状態3)が浮動小数点演算を行った場合はどうなるのでしょうか? 浮動小数点演算レジスタへのアクセスは禁止されているため、実CPUは例外を発生させます(例外ハンドラとしては、math_state_restore関数が実行されます)。math_state_restore関数はsetup_fpu関数を呼び出し、浮動小数点演算レジスタを利用できるようにします。

浮動小数点演算レジスタの切り替え遅延部分

 setup_fpu関数(リスト3)は、図1の状態3にあるドメインに対してrestore_fpu関数を呼び出し、仮想CPUから実CPUにレジスタ値を復帰させます(D5、図1の状態2)。例外ハンドラから復帰すると、ドメインは浮動小数点演算を行える状態になっています。

編集部注:リストには多くの注釈線が含まれているため、画像として用意しました。上記アイコンをクリックいただくことでご覧いただけます

 一方、生成されたばかりのドメイン(図1の状態1)は、まだ一度も浮動小数点演算レジスタを利用していません。この場合も同じ仕組みを利用して、浮動小数点演算レジスタを初期化します。ドメインがはじめて浮動小数点演算レジスタにアクセスすると、例外が発生しますが、このドメインにとってはじめての浮動小数点演算レジスタアクセスである場合、setup_fpu関数はinit_fpu関数を呼び出し、浮動小数点演算レジスタを初期化します。

最後に

 2回にわたってドメインの切り替えを中心に見てきました。「なんだ、やっていることはLinuxカーネルと何も変わんないじゃん、期待して損した」と思われたあなた、正解です。一見、まったく異なることを行っているように見えていても、やろうとしていることはLinuxカーネルでもXenでも大きな違いはありません。今後の連載でも、「基本はLinuxカーネルと大差ないんだ」と気楽に考えていてください。

このページで出てきた専門用語

リング1で動作するドメインに直接飛び込みます

ドメイン内で動作するゲストがOSでLinuxで、旧形式のシステムコールを発行した場合のみ高速化される。


関連キーワード

カーネル | Linux | オープンソース | 仮想化 | Xen


本記事は、オープンソースマガジン2006年5月号「仮想マシンモニタ Xen 3.0解読室」を再構成したものです。


前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ