ドメインのスケジューリング【後編】仮想マシンモニタ Xen 3.0解読室(2/3 ページ)

» 2007年07月26日 08時52分 公開
[高橋浩和(VA Linux Systems Japan),ITmedia]

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

 浮動小数点演算レジスタの切り替えは複雑なので、少し詳しく見ておくことにしましょう。浮動小数点演算レジスタの切り替えでは、ネイティブのLinuxカーネルと同様、遅延切り替えで切り替えコストを抑えています。どちらも、浮動小数点演算レジスタのアクセスを一時的に禁止することで、 浮動小数点演算を行おうとしたときに生成されるDevice Not Available例外を捕捉し、そのタイミングでコンテキスト切り替えを完了させます(図2)

図2 図2 プロセス切り替え

 Xenのレベルでも、浮動小数点演算レジスタの切り替えを遅延する仕組みが実装されているため、動作は少々複雑です。Device Not Available例外をドメインの浮動小数点演算用コンテキストの切り替えと、プロセスの浮動小数点演算用コンテキスト切り替えの両方に使う必要があります。これを両立させるための仕掛けを、少しのぞいてみましょう(図3)

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

 Xenは実CPUの浮動小数点演算レジスタへのアクセスを制御します。一方、ゲストOSのLinuxは、仮想CPUの浮動小数点レジスタへのアクセスを制御します。どちらかが禁止されていれば、実CPUの浮動小数点演算用レジスタへのアクセスは禁止しておく必要があります。実際に浮動小数点演算レジスタへアクセスがあったときに、間違いなくそれを捕捉し、対応する処理(ドメイン、またはプロセスの浮動小数点演算用コンテキスト切り替え)を行う必要があるためです。

 Linuxカーネル内でプロセスが切り替わるとき、Linuxカーネルは、プロセスの浮動小数点レジスタ値を待避した後、Xenに対し浮動小数点レジスタへのアクセス禁止を依頼します(リスト2の太字部分)。Xenは、仮想CPUにアクセス禁止フラグを立てる(リスト3のB1)と同時に、実CPUが浮動小数点レジスタへアクセスするのも禁止(リスト3のB2)します(仮想CPU状態3から、仮想CPU状態4へ遷移)。


struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
                                :
                                :
    mcl->op = __HYPERVISOR_fpu_taskswitch;
                                :
                                :

リスト2 Linuxコード

long do_fpu_taskswitch(int set)
{
    struct vcpu *v = current;

    if ( set )     {         v->arch.guest_context.ctrlreg[0] |= X86_CR0_TS;    ←B1         stts();    ←B2     }     else     {         v->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;         if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )             clts();     }
    return 0; }
リスト3 Xenのfpu_taskswitchハイパーバイザーコールのサービス関数
リスト4

 例えば、ドメインが切り替わる前に、このプロセスが再度スケジューリングされ、浮動小数点演算を行ったとしましょう。実CPUはそれを検知し、Device Not Available例外を発生させます。この例外は、Xenが受け取ります。実CPUの浮動小数点レジスタはアクセス許可の状態(実CPU状態1)であるため、特に何もしません(リスト4のC2)

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

 しかし、実CPU上で動作している仮想CPUにはアクセス禁止フラグが立っているため(リスト4のC3)、Xenは仮想CPUに対して仮想例外を発生させます(リスト4のC4)。仮想例外を受け取ったLinuxは、プロセスの浮動小数点演算レジスタ値を元に戻します(リスト5の太字部分。仮想CPU状態4から、仮想CPU状態3へ遷移)


asmlinkage void math_state_restore(struct pt_regs regs)
{
    struct thread_info *thread = current_thread_info();
    struct task_struct *tsk = thread->task;

    /* NB. 'clts' is done for us by Xen during virtual trap. */     if (!tsk_used_math(tsk))         init_fpu(tsk);     restore_fpu(tsk);     thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ }
リスト5 LinuxのDevice Not Available例外ハンドラ

 また、カレントプロセスが浮動小数点演算を行っているとき(仮想CPU状態3)にドメイン切り替えが発生した場合も考えてみましょう。再度このドメインが動作を始めたとき、仮想CPUとしてはアクセス可能(仮想CPU状態5)ですが、実CPUとしてはアクセス不可(実CPU状態2)という状態になります。カレントプロセスが浮動小数点演算を行うと例外が発生し、その例外ハンドラ内で浮動小数点演算レジスタの値を復帰させる(リスト4のC2)ことになります(仮想CPU状態3)。

 Linuxの動作しているドメインがスケジューリングから外されたときに、カレントプロセスが浮動小数点演算を行っていなかった場合(仮想CPU状態4)はどうでしょうか? 再度このドメインが動作を始めたとき、仮想CPUとしてはアクセス不可(仮想CPU状態6)、かつ実CPUとしてもアクセス不可(実CPU状態2)という状態になります。

 この状態でカレントプロセスが浮動小数点演算を行うと例外が発生します。その例外はXenが捕捉し、ドメインとしての浮動小数点演算レジスタ値の復帰処理(リスト4のC2)を行います(仮想CPU状態4)。さらに、この実CPU上で動作している仮想CPUにはアクセス禁止フラグが立っている(リスト4のC3)ため、Xenはこの仮想CPUに対して仮想例外を発生させます(リスト4のC4)

 仮想例外を受け取ったLinuxは、プロセスの浮動小数点演算レジスタの値を元に戻します(リスト5のD1。仮想CPU状態4から、仮想CPU状態3へ遷移)

関連キーワード

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


Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ