BitVisorにはthreadとprocessがあります.この二つについて簡単に説明します.なお一部の用語はIntel VT-xのものを利用しています.ご了承ください.AMDの場合でも内容は同様です.
一般に,プロセスもスレッドもCPUが実行するプログラムの単位で,その二つの違いはプロセスが独立したメモリ空間を持つのに対して,スレッドは同じグループのスレッド内でメモリ空間が共有されるという点です(スタックは除く).
さて,BitVisorのthreadやprocessも上記の性質を持ちますが,それに加えて以下のような特徴があります.
thread
Linuxでは一番最初にinitプロセスが動作しますが,BitVisorでは最初にmain threadが起動します.そして,VMX root modeのring0で動作するものは全てthreadになります.
threadの作成
threadは thread_new()
で作成することができます.ソース中で thread_new()
を呼んでる箇所をみればthreadがどんなものか分かると思います.
threadのスケジューリング
メインスレッドで実行されるメインループのvt_mainloop()
関数を見ると,ループの最初に schedule()
が呼ばれていることが分かります.
static void
vt_mainloop (void)
{
enum vmmerr err;
ulong cr0, acr;
u64 efer;
bool nmi;
for (;;) {
schedule ();
vt_vmptrld (current->u.vt.vi.vmcs_region_phys);
panic_test ();
[...]
基本的には schedule()
は一つずつ作成したスレッドにスイッチして処理を進めます.逆に言えば,BitVisorのスレッドが動作するタイミングは(当たり前といえば当たり前ですが)VMEXITが発生し,VMX root modeに制御が移ったタイミングになります.またBitVisorはタイマ割り込みによるスケジュールは利用していないので,各スレッドは自分の責任で schedule()
を呼ぶ必要があります.さもなければそのスレッドで処理が止まってしまいます.
process
さて,BitVisorではprocessはVMX root modeのring3,いわゆる保護ドメインで動作します.プロセスのソースは process/
以下にあります.プロセスを新規に追加するには,ここにソースを書いて,Makefileに追加することになります.
processの起動
processは process_new()
関数で準備をおこなったあとBitVisorのメッセージパッシングの仕組みを利用して起動します. 詳しくは core/process.c をみてください.processにコンテキストスイッチするときにsysenterでring3 (保護ドメイン)へ移行します.
メッセージパッシングの仕組みについては,また別途改めて機会があれば別の記事にまとめようと思います.
processのスケジューリング
process自体にスケジューリングという概念はありません.プロセスがシステムコールを呼んだり,あるいはメッセージハンドラが終了すればsysexitでring0のスレッドに戻ります.そしてそこのスレッドで schedule()
されることになります.
参考文献
process (保護ドメイン) に関しては以下にも説明があります.ここでは触れていないメッセージパッシングについても書かれています..
- deep_tkkn, BitVisor の保護ドメインとのI/F のお話 - Qiita, BitVisor Advent Calendar 2016