2021/2/24 WSL2 サポート 4f6b785
WSL2(Windows Subsystem for Linux 2)のUbuntu 20.04で gokvm を実行すると、 IOポート 0x64 への出力が無限に繰り返され、Initプロセスの起動まで到達しなかった。 どうやら PS/2 キーボード周りの挙動が原因のようだ。
kvmtool では in (0x61) に対して 0x20 を返している 1 のでそれを踏襲する形で対応した。
IOポート 0x61は NMI (Non-Maskable Interrupt)のステータスとコントロールレジスタとして使われているようだ 2。
このステータスレジスタの内容を調べると、bit 5はmirrors timer 2 output condition
を意味するが、
これ以上は解釈できず。
理解できていない部分はあるが、結果として WSL2 での ゲストVMの起動もできるようになった。
0061 r KB controller port B control register (ISA, EISA) system control port for compatibility with 8255 bit 7 parity check occurred bit 6 channel check occurred bit 5 mirrors timer 2 output condition bit 4 toggles with each refresh request bit 3 channel check status bit 2 parity check status bit 1 speaker data status bit 0 timer 2 gate to speaker status
2021/2/27 Fedora標準のカーネルでゲストを起動 a86d86b
gokvm 内でビルドしたカーネルだけでなく、広く使われているカーネルにも対応したい。 単純に起動してみると以下のようにカーネルパニックとなった。 KVM API の KVM_SET_MEMORY_REGION には1GBメモリを渡しているので、 下の出力を見ると明らかにそのサイズが小さいように思う。
[ 0.000000] BIOS-provided physical RAM map:
[ 0.000000] BIOS-88: [mem 0x0000000000000000-0x000000000009efff] usable
[ 0.000000] BIOS-88: [mem 0x0000000000100000-0x00000000002fa7ff] usable
[ 0.020431] Kernel panic - not syncing: initrd too large to handle,
disabling initrd (33769847 needed, 22421504 available)
どうやら e820 エントリの指定が不正で、メモリが枯渇しているのかもしれない。 ちなみに、e820はメモリマップを管理するテーブルで、メモリ開始位置・メモリ終了位置・フラグの組みをエントリとして持つ。
struct e820_entry { u64 addr; u64 size; enum e820_type type; } __attribute__((packed)); struct e820_table { __u32 nr_entries; struct e820_entry entries[E820_MAX_ENTRIES]; };
2021/2/28 e820のセットアップ 6712e09
e820 をどうやって設定すれば良いのか。 ブート時の挙動だろうということでx86のBoot周りのドキュメントを見直し、 Zero Page 3と呼ばれる領域の中にe820_entriesとe820_tableを見つけた。 Zero Pageに記載されたオフセットは、前回の記事で触れた Boot Protocol Real-Mode Kernel Header 4 と同じように解釈できる。 そこで、リファクタリングを施しe820 entry も自由に操作できる構造にした。 実際に登録すべきエントリの内容についてはkvmtool 5 を参考にした。 最終的に、Fedora標準のカーネルを使ってゲストを起動できるようになった。
これから
ディスクやNICのデバイスエミュレーションに手を出そうかと模索中。 NICであれば e1000(Intel Intel 8254x)とvirtio-net だとどちらが簡単だろうか。 ナイーブな実装で良いので動くところまで持っていきたい。 いずれにしてもPCIデバイスのConfiguration Spaceの初期化周りのエミュレーションは必要になるだろう。