以下の記事ではQEMU上でのBitVisorの実行に成功していましたが、SMPは使用していませんでした。果たしてどうなるでしょうか。
QEMU上でBitVisorは動作するか? リベンジ編
https://qiita.com/hdk_2/items/dab49edf80975f4cc7d0
面倒なのでKVMありの場合だけ紹介します。
- Debian GNU/Linux 9
- Linux 4.9.0-8-amd64
- QEMU 2.8.1(Debian 1:2.8+dfsg-6+deb9u5)
- AMD Ryzen 7 2700
起動パラメーター
qemu-system-x86_64 -bios OVMF.fd -cpu host -enable-kvm -m 2048 -snapshot -cdrom ../data/iso/ubuntu-18.04-desktop-amd64.iso -hda fat:bitvisor/_ -M q35 -vga qxl -smp 2
結果
2個目のプロセッサを開始したログも出ていますし、一見大丈夫そうに見えますね? 実はこれ、ダメなんです...
このように、taskset 1ならdbgshが動くのに、taskset 2だと動きません。
Intel環境の場合は?
Intel環境では、2個目のプロセッサを開始したところで、VM entry failed. panicが発生するそうです。その理由は、BitVisorがVMCSのguest activity stateにwait-for-SIPIをセットしたためみたいです。実は、IA32_VMX_MISC MSRに、guest activity stateにactive以外のステートをセットできるかどうかを示す情報があるのですが、BitVisorはこれをチェックしないで使用してしまっています。QEMU KVMはwait-for-SIPI未対応と返しているみたいです。
なお、問題はそれだけではないようです。
何が起きているのか?
推測ですが、どうやら、QEMUかKVMのいずれかあるいは両方のINIT信号の処理には問題があるようです。BitVisorでは以下の機能を使用していますが、いずれもQEMU KVM上では正しく動作しません。
- AMDの場合: VM_CR MSRのR_INITビットをセットすることにより、INIT信号は#SX例外に変換される
- Intelの場合: INIT信号は、VMX root operationであればブロックされ、VMX non-root operationであればVM exitになる
BitVisorのSMP対応はこの機能をあてにしていて、AMD環境では常にlocal APICのIPI送信をフックしていますが、それで見ているのはUEFI環境での最初のINIT信号送信と、startup IPI送信だけです。しかも、裏から見ているだけで、実際にINIT信号もstartup IPIも送信されます。AMD環境ではwait-for-SIPIを受け取る特別な機能はないので、INIT信号を受けたらwait-for-SIPI待ちのポーリング処理に移る仕掛けになっています。
それで、QEMU KVM上ではどうやら、INIT信号を受けたプロセッサは、本当にリセットしてwait-for-SIPIステートに移ってしまうようです。それで2個目のプロセッサではBitVisorがいなくなってしまい、QEMU KVM上で直接動作していたのでdbgshが動作しないのです。Intelの場合も同じような問題を抱えているっぽいです。
Intelでwait-for-SIPIステートが使えないプロセッサに対応できていないのはBitVisorの問題ですが、INIT信号を正しく扱えないのはQEMUあるいはKVMのバグということになりそうです。