ハイパーバイザを自作して仮想化技術やセキュリティについて学ぶゼミ 応募課題
はじめに
問題は4つあります。回答する際は以下のことに気をつけてください。
- 回答は詳細に書いてもらうことを期待しますが、できるだけ簡潔に書いてください
- 回答について整理して結果以外の余計な部分を削除する必要はありません。どのように思考して調査しどういう結論に至ったのかの経緯を見ています
- 分からない場合でも「分かりませんでした」とだけ記述するのではなく、何を調べたか、何が理解できなかったかを可能な限り記述してください
- 過程を記載するのは歓迎しますが、同じことを複数回記述するようなことは避けてください
- 各問題はそれぞれ2048文字以下(ソースコード、URLリンクを除く)を心がけてください。それ以上の場合は評価しません
- 評価は加点方式です。不正確なことを書いて減点することはありません
- あなたの考えを述べてもらうため、途中で誤りがあっても減点はしません
- どのように考え、手を動かしたかを評価します
- ただし、闇雲に考察や引用を行っても記述量が多いという点では評価しません
- 調べたことは出典を示してください
- URL、検索キーワードなどを明記してください
- 自分の知識を元にした場合は可能であればその知識を得た背景・理由を記述してください。加点します
- 生成系AIの使用した場合は明記してください。どこまでが出力か、どこからが考察かを明記してください
- 詳細は後述します
- ソースコードは構文が正しい状態にして提出してください
- 構文が正しいとは、適切な関数が実装されていればコンパイルは通る状態です
clang-format
などの整形ツールでsyntax errorが出ない状態にしてください
- 正常に動作しなかった場合も提出可能です
- 書きかけのコードで構文が正しい状態に出来ない場合は、コメントアウトしてどのような挙動を期待して記述しようとしたかをコメントで追記してください
- ソースコードは別ファイルとして提出する、もしくは同一ファイル内で改行で区切ったり、Markdownのコードブロックとして記述してください
- 構文が正しいとは、適切な関数が実装されていればコンパイルは通る状態です
生成系AIの使用について
生成系AIの使用は許可します。ただし使用した際はそのことを明記してください。
生成系AIには、単純に文章を生成するものと生成する際に使用した文章の出典を付記するものがあります。 適宜、出典を確認しその情報の真偽を確認してください。
低レイヤの情報は、残念ながらあまり文章化されておらず情報源が乏しいもの、誤った知識で書かれたもの、別の環境の情報で役に立たないものなどが多く存在します。 このため生成系AIの出力する情報については必ずしも正確とは言えません。また一般的には正解だったとしても対象とした条件下では動作しない場合があります。
また、各種生成系AIにおいても学習セットや手法によっては真逆の回答が得られる場合があります。複数の生成系AIを比較するのも手でしょう。
例として、「i386のCPUを搭載したVirtualBoxでIntel 64用OSは動作しますか?」と入力した際の、GPT-3.5とGPT-4の結果を示します。
GPT-3.5
はい、i386のCPUを搭載したVirtualBox上でIntel 64用のオペレーティングシステムは動作します。 VirtualBoxは、ホストマシンのアーキテクチャとは異なるアーキテクチャの仮想マシンを実行することができます。 i386のCPUを搭載したVirtualBox上で64ビットのオペレーティングシステムを実行する場合、仮想マシンの設定でIntel 64(AMD64)を有効にする必要があります。 ただし、仮想マシンのパフォーマンスは、ホストマシンの性能に依存するため、注意が必要です。
GPT-4
「i386」のCPUを搭載したVirtualBoxで「Intel 64」用のOSを動作させることは基本的に不可能です。 なぜなら、i386は32ビットアーキテクチャを示し、Intel 64は64ビットアーキテクチャを示すためです。 64ビットOSは、64ビットアーキテクチャ上でしか動作しないため、32ビットアーキテクチャの上では動作しません。
ただし、一部の64ビットOSには32ビットモードがあり、その場合は動作する可能性もありますが、性能面で大幅な制限があることを理解しておいてください。 また、すべての64ビットOSが32ビットモードをサポートしているわけではありません。
以上の情報は2021年9月までのもので、それ以降の情報については保証できません。 もし最新の情報が必要なら、公式のVirtualBoxのウェブサイトや関連のフォーラムをご覧になることをお勧めします。具体的なOSや設定についてもっと詳しく知りたい場合は、お知らせください。
生成系AIの出力した情報を元に自分で検討・検証し、その結果を踏まえてさらなる調査や実験を行うことを期待します。
問題.1
本ゼミで取り組んでみたいことを、講義概要を読んだ上で回答してください。 あなたの知識や経験、及びそれらから得た学びなどを記述すると良いでしょう。 もしこの分野について初心者であるという場合は、なぜあなたがハイパーバイザに興味を持ったかを記述してください。
また、取り組む上で必要となる知識やそれを得るための手法、前提となるコンピュータの機能などを調査し記述してください。
問題.2
ハイパーバイザによる仮想化とエミュレータによるエミュレーションの違いについて述べてください。 ポイントとして以下の点を調べて挙げてください。
- ハイパーバイザよる仮想化のメリット、デメリット(制限)
- エミュレータによるエミュレーションのメリット、デメリット
- ハイパーバイザで仮想マシンを実行する際は、エミュレーションは必要か、不要か
- ヒント: 講義概要では"QEMU-KVM"と書きましたが、"QEMU"と"KVM"の役割について調べてみてください
- ハイパーバイザによる仮想化では、異なるCPUアーキテクチャ命令の実行は可能か
問題.3
Booting AArch64 Linux を読んでAArch64用のLinuxをブートする際にブートローダがすべきことを述べてください。
またハイパーバイザで必要となるブートローダの処理について、特にメモリ配置に注意して、以下のC言語のテンプレートを元に記述してください。
実装条件は以下のとおりです。
- POSIX準拠の関数が使用可能
- インラインアセンブリ使用可能
- 特権命令が必要なレジスタの操作も可能
- 指定された情報だけで処理できない場合は、必要な情報を取得・設定する関数を宣言し、その詳細を
launch_vm
の例に従って記載し使用 - MMUの設定(仮想アドレスと物理アドレスの対応付け)処理は不要
launch_vm
内でmem_start
とmem_size
を元にマッピング処理を行うものとする
- (U)EFIは不使用
- プロセッサは1つのみ
この問題では、仕様を自分なりに調べて理解しコード設計に落とし込めるかどうかを見ています。 指定したドキュメントには今回の処理に必要ない規定や説明があります。この中から必要な情報を探し出してコードに書き出してください。
すべての処理を完璧に記載する必要はありません。システムプログラムを書く際は、まず最低限動くようにする事を目標にすることが多いです。 このため、実装の優先度を把握し、必要な部分を実装するテクニックが必要です。 「本来はこのような処理が必要だが、今回はこうなっているであろうと仮定して記述した」というのがあればそれがわかるようにコメントで記載してください。
まずは、メモリに正しく"Image"と"DTB"が正しく配置され、entry_pointに適切にジャンプできることを目指してください。 その上で、追加の"Initramfs"のロードと、そのアドレスの通知、周辺デバイスの初期化などをわかる範囲で記述してください。
わからない部分があった場合は、その事を明記して自分の思う実装を記述してください。 間違った処理となっていても減点はしません。その処理がどのくらいの優先度で必要かを把握できていれば加点します。
何をしたら良いか分からない方へのヒント
この問題はLinuxという「ソフトウェア」を如何にメモリ上にロードして実行開始場所を特定するかが理解できるかを見ています。
ソフトウェアは通常メモリにロードされ、CPUのインストラクションポインタをロードしたソフトウェアのエントリポイントに設定することで実行されます。 これは、OSであるLinuxでも変わりません。
仮想マシンでゲストOSを起動する際はデバイスの設定などが必要ですが、今回は難しいことを抜きにしてソフトウェアを読み込む作業に集中してください。
指定したドキュメントには、"must be placed"というワードが複数出てきます。"placed"はすなわちメモリに配置される、ロードされるという意味です。 各プログラムやファイルを読み込む際には読み込む場所(アドレス)に制約があります。一番良く出てくるのがアライメントです。 アライメントについて知らない場合はまずこれについて調べて記述してみてください。その後アドレスの計算を行ってみてください。
今回メモリはmem
で確保してあります。仮想マシンで使用するメモリの0番地がmem
の指す先だと考えると仮想マシン上でのx番地はmem + x
ということになります。
これらを元にプログラムを書くと、実は数回、fread(mem + offset, 1, read_size, fp)
を実行し読み込んだ値をif文で少し検証し、値を取り出してlaunch_vm
に渡すだけで最低限の実装は完了します。
書いた後に、「こんな少ない行数でいいんだろうか...」と不安になるくらいかもしれません。
しかし実際のところ、これにデバイスの設定などを追加するだけでLinuxは動作してしまいます。
実装が出来たら、どうしてそのような実装にしたかをドキュメントを元に記述してみてください。
ここまで出来て余裕があったら、ドキュメントに書いてあるデバイスの設定などにトライしてみてください。
おすすめは、"initramfs"のロードです。これは単純にfread
するだけでは不十分です。
何が必要かを考え、適宜関数宣言を追加してください。
テンプレート
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define MEM_SIZE (512 * 1024 * 1024)
#define MEM_ALIGN 1 /* 調整してください */
/*
処理内容: VMを指定された条件で実行を開始します。
引数:
- mem_start: 仮想環境と共有するメモリ領域の開始アドレス
- mem_size: 仮想環境と共有するメモリのサイズ
- 仮想環境は mem_start ~ (mem_start + mem_size)
の間のメモリにアクセス可能です。
- entry_point: 仮想環境で実行を始めるアドレス
- x0: 実行を開始する際のx0 registerの値
- x1: 実行を開始する際のx1 registerの値
- x2: 実行を開始する際のx2 registerの値
- x3: 実行を開始する際のx3 registerの値
結果:
成功した場合は、VMに制御が移り、この関数は戻ってきません。失敗した場合はエラーコードが返却されます。
*/
int launch_vm(uintptr_t mem_start, size_t mem_size, uintptr_t entry_point,
uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3);
/*
main関数内では表現できない処理がある場合は、上の"launch_vm"のように処理内容と引数、結果を明記して関数宣言の形で記載してください。
*/
int main(void) {
void *mem =
aligned_alloc(MEM_ALIGN, MEM_SIZE); /* VMに割り当てるメモリです */
FILE *image = fopen("./Image", "rb"); /* Linux Kernel Image */
FILE *initrd =
fopen("./initramfs", "rb"); /* Initramfs 使用しなくても構いません */
FILE *dtb = fopen("./dtb", "rb"); /* The device tree blob (dtb) */
int err = 0;
/* ここから処理を記述してください */
err = launch_vm(mem_start /*変更してください*/, mem_size /*変更してください*/,
entry_point /*変更してください*/, x0 /*変更してください*/,
x1 /*変更してください*/, x2 /*変更してください*/,
x3 /*変更してください*/);
return err;
}
問題.4
これまでにあなたが行ってきたプログラミングに関することについて記述してください。 自作ハイパーバイザや、自作OS、その他システムプログラミング、それ以外のプログラミングについても可能な限り記述してください。 リポジトリへのリンクや、活動記録サイトへのリンク、プログラミングでのこだわりなども歓迎します。 また、この応募課題を解くにあたって、苦労した点や分からなかった点があれば記載してください。
アンケート(任意)
選考を通過し、本ゼミに参加できるようになった場合に、どのくらい事前学習に時間が割けるかと自身の知識や環境について差し支えない範囲で教えてください。 この項目は選考には影響しません。選考が完了し事前学習に向けて資料や環境作成を行う際に、どのような事を重視すべきかやスケジュールを決定する際に参考とします。 基本的にはLinux環境(VM含む)でRustを使用しようと思いますが、「どうしてもLinux環境が用意できない」「Rustは何度も挫折しており到底理解が出来ない」などあれば記載してください。