vkernel発掘体験記

vkernelを使ってみたい

実際に私のDragonflyBSDのバージョンでvkernelを使ってみたかったので,やってみた.

まず,DragonflyBSDのマニュアルを参考にして実行を試みました.

vknetd
vkernel

が,-bash: vkernel: コマンドが見つかりません というエラーが.
流石にvkernelってコマンドはないのかぁ.

vkernelを利用できるようにする道のりは長そうです.

vkernelを起動する

とりあえず,手当たり次第にvkernelとつくものがないか調べてみた

$ find / -name "vkernel"
/usr/obj/usr/src/sys/VKERNEL64/usr/src/sys/dev/virtual/vkernel
/usr/src/test/vkernel
/usr/src/sys/dev/virtual/vkernel
/usr/src/etc/rc.d/vkernel
/build/usr.obj/usr/src/sys/VKERNEL64/usr/src/sys/dev/virtual/vkernel
/etc/rc.d/vkernel

(。´・ω・)ん? なんか”いかにも”なファイルがあったような..

/etc/rc.d/vkernel ←!!?!?!?!!?!?!!?

当たり前かもしれないけど,ちゃんと起動スクリプトにvkernelの準備がありました.
デフォルトの起動はどうなっているか見ると,まぁNOになっています.

$ emacs /etc/defaults/rc.conf
...
vkernel_enable="NO"  # Set to YES to enable starting of vkernels
...

つまり実行するものがあれば,vkernelがすぐ使えるということですね.
その肝心の中身がないのだけれど..

起動スクリプトから機能を見てみる

$ cat /etc/rc.d/vkernel

簡単にまとめると,
①vkernelバイナリを要求
②メモリサイズを設定
③ルートイメージ設定
④daemon経由で起動する

特に①のvkernelバイナリがあれば使えるということです.
開発者としては,/bootにバイナリがあることを想定しているようです.

#vkernel_bin="/boot/kernel.VKERNEL64"

じゃあ,実際にカーネルをビルドして置いておこう

バイナリがない

cd /usr/src
sudo make buildkernel KERNCONF=VKERNEL64

結果
ちゃんとOSとソースのバージョンは揃えようね!(一敗)

-------------------------------------------------------------
>>> Kernel build for VKERNEL64 completed 
-------------------------------------------------------------

$ ls /boot | grep "kernel.VKERNEL64"
$

うーーん,結果のバイナリはkernel.VKERNEL64って名前じゃないのか..?

とりあえず,手当たり次第にVKERNEL64とつくファイルを探してみた

$ find / -name "VKERNEL64"
/usr/obj/usr/src/sys/VKERNEL64
/usr/src/sys/config/VKERNEL64
/build/usr.obj/usr/src/sys/VKERNEL64

直接kernel.VKERNEL64はなかったが,/usr/obj/usr/src/sys/VKERNEL64が怪しいらしい.

この中にはビルド結果のファイルが置かれています.
そして中に.doneというファイルがあり,それがビルド完了を示すファイルです.

ビルドも確実に成功している,後はこの中にバイナリもあるはず..
サイズでソートして大きいものがバイナリのはず..

$ ls -lhS /usr/obj/usr/src/sys/VKERNEL64 | head -10
total 255746
-rwxr-xr-x  1 root  wheel    44M kernel.debug
-rwxr-xr-x  1 root  wheel   5.5M kernel.stripped
...

上位2つのこのファイルが候補だが,名前的にkernel.debugではないでしょう.

vkernelバイナリを使って実行する

とりあえずそのままkernel.strippedを実行してみた

$ /usr/obj/usr/src/sys/VKERNEL64/kernel.stripped
kernel.stripped: vm.vkernel_enable is 0, must be set to 1 to execute a vkernel!

vm.vkernel_enableの値を1にすれば実行できる!!

$ sudo sysctl vm.vkernel_enable=1
vm.vkernel_enable: 0 -> 1

勝ったな👍

$ /usr/obj/usr/src/sys/VKERNEL64/kernel.stripped
Usage: /usr/obj/usr/src/sys/VKERNEL64/kernel.stripped [-hsUvdt] [-c file] [-e name=value:name=value:...]
        [-i file] [-I interface[:address1[:address2][/netmask]]] [-l cpulock]
        [-m size] [-n numcpus[:lbits[:cbits]]]
        [-p file] [-r file]

あとは,kernel.strippedを/boot/kernel.VKERNEL64として置いて,vkernel_enableをONにするだけ!

$ sudo service vkernel start
Starting virtual kernels: destroy_machine.

起動したぁああああああ‼️‼️‼️
が,ここで問題が発生.プロセスがない.

$ ps aux | grep kernel.VKERNEL64
$

ログを見ると,こんな表示が.

Using memory file: /var/vkernel/memimg.000000 kernel.VKERNEL64: Unable to mmap() kernel virtual memory!: Operation not supported

これについて格闘していたら,とんでもない事実にたどり着きました.

vkernelはサポートが削除されていた

ソースコードを調べると,vkernelはMAP_VPAGETABLEという特殊なmmapフラグを使用していました.
しかし,sys/mman.hには,

/*
* NOTE! MAP_VPAGETABLE is no longer supported and will generate a mmap()
* error.
*/

さらにvm_mmap.cでは

/*
* Virtual page table support has been removed and now always
* returns EOPNOTSUPP.
*/
if (flags & MAP_VPAGETABLE)
    return (EOPNOTSUPP);

つまり,実行すると意図的にエラーになるようにされていたのです.

2021年のコミット

2021年1月7日のMatthew Dillon 氏のコミット
kernel - Remove MAP_VPAGETABLEには,

This will break vkernel support for now

と書かれていました.
さらに,

We will need actual hardware mmu virtualization to get the vkernel working again.

とも書かれており,ソフトウェアページテーブルを利用していた従来のvkernelは,VMシステムの変更と両立できなくなったため,一旦停止されたようです.

なので,それ以降のDragonflyBSDの6.0 系以降では vkernel が動作しなくなっています.

まとめ

最新バージョンでは変態的特徴のあるvkernelが使えないのは残念でした.この上でDragonflyBSDのシステムで遊んでみたかったので.
for nowという書き方なので,いつか復活することを望んで待ちます🤓

\ Get the latest news /

Leave a Reply

Your email address will not be published. Required fields are marked *