bhyve

Table of Contents

truncate

前回目をつけておいたFreeBSD/amd64で、bhyveをやってみたい。これって、不自 由なqemuと看破したんだけど、何よりも有り難いと思うのは、qemuをパッケー ジから入れなくても済むことだ。どうせqemuを入れても使う石は、amd64か i386しかないからね(それ以外は、遅くて使用に耐えない、我ながら気が短か くなったものだ。歳のせいだな。)

専用に20GのDiskを増設したよ。で、ゲストOS用に、専用の仮想Diskを作成す る必要が有る。作成コマンドには、truncateってのを使うそうだ。ちと実験す る。

sakae@f64:/tmp $ truncate -s 4G mydisk
sakae@f64:/tmp $ ls -lh mydisk
-rw-r--r--  1 sakae wheel  4.0G Jun 29 15:49 mydisk
sakae@f64:/tmp $ df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/da0s1a     22G    4.1G     16G    20%    /
devfs          1.0K      0B    1.0K     0%    /dev
tmpfs          384M    4.0K    384M     0%    /tmp
/dev/da1        19G    1.7G     16G    10%    /opt
sakae@f64:/tmp $ ls -s mydisk
0 mydisk

注目は、/tmpの下に4Gのファイルを作成出来てしまった事。張子の虎を作成するコマンドなのだな。

OpenBSD on bhyve

一番ターゲットにしたいのは、OpenBSDだ。何と言っても直接VMWareで扱おと すると、問題を起こしていたからね。たとえFreeBSDの中からでも、動けばオ ンノジだ。

起動は面倒だけど、2段階の手順を踏むそうだ。最初は、どこかで見た事があ るようなコマンドを叩いて、miniroot相当をロードするらしい。

# cat dev.map
(hd0) /opt/OB75/disk.img
(cd0) /opt/OB75/install75.iso
# cat grub
grub-bhyve -m dev.map -r cd0 -M 384M ob75

デバイスのマッピング・ファイルを用意して、それを引数にgrub-bhyveを起動 するとな。で、起動に成功したら、マニュアルで、bsd.rdとcom0を認識さるっ ぽい。

# ./grub
Could not create VM ob75
Error in initializing VM

出鼻を挫かれた。幸先悪いぞ。これって、ひょっとしてリナの血が混ッている からでは、なかろうか? ちょいと中身を暴いてやる。今回は、得意のソース 読めは、繰り出しません。まあ、パッケージのソースを展開するのが、面倒な だけです(何せリナっぽいですから)。ktraceの姉妹品である、trussを使って、 システムコールをトレースしてみました。

# truss ./grub
  :
read(10,"\ngrub-bhyve -m dev.map -r cd0 -"...,1024) = 43 (0x2b)
fstatat(AT_FDCWD,"/usr/local/sbin/grub-bhyve",{ mode=-r-xr-xr-x ,inode=1289646,size=1058768,blksize=32768 },0x0) = 0 (0x0)
vfork()                                          = 1326 (0x52e)
Could not create VM ob75
Error in initializing VM

なんか、フォークした後に問題が発生してるみたいですな。焦らずに、純正品 だけで、勝負してみますかね。急いては事を仕損じるですから。

FreeBSD on bhyve

そんな訳で、リナの影が全く無いやつです。まずはインストールって事で、-i でCDからのブート指定、-l で、その実体を指定。

# cat INS.sh
/usr/share/examples/bhyve/vmrun.sh \
        -c 1 \
        -m 384M \
        -t tap0 \
        -d /opt/FB141/disk.img \
        -i \
        -I /opt/FB141/FreeBSD-14.1-RELEASE-amd64-disc1.iso \
        freebsd-14.1
# ./INS.sh
Launching virtual machine "freebsd-14.1" ...
bhyveload: vm_create: Device not configured

何かOpenBSDの時と、様相は一緒だなあ。ならば、trussしましょ。

# truss ./INS.sh
   :
read(10,"/usr/share/examples/bhyve/vmrun."...,1024) = 216 (0xd8)
vfork()                                          = 1361 (0x551)
Launching virtual machine "freebsd-14.1" ...
bhyveload: vm_create: Device not configured

/usr/share/examples/bhyve/vmrun.sh

shell scriptは接着剤なんで、部品を確認。冒頭に部品が列挙されてた。

LOADER=/usr/sbin/bhyveload
BHYVECTL=/usr/sbin/bhyvectl
FBSDRUN=/usr/sbin/bhyve

上のエラーから、bhyveloadの vm_create でエラーしてると想像できるので、 該当部分を参照してみる。

bhyveload.c

vmname = argv[0];

need_reinit = 0;
error = vm_create(vmname);
if (error) {
        if (errno != EEXIST)
                err(1, "vm_create");
        need_reinit = 1;
}

指示した名前で、仮想マシンを作成しろ、だな。これが失敗してるって事は、 根本がそもそも動作していない。

念の為bhyveload(8)に出てたサンプルを実行。

# bhyveload -m 384M -d ./FreeBSD-14.1-RELEASE-amd64-disc1.iso test-vm
bhyveload: vm_create: Device not configured

同じエラーですな。絞りこめてきました。

次なるは、 vm_create を調査する事だな。 何処に定義されてるの? /usr/src/usr.sbin/bhyve*/* をgrepするも、みんな 平然と使っているだけですよ。こういう時は、Makefileを見て、変?なライブ ラリィーを抱えこんでいないか調査。あるいは、

# ldd /usr/sbin/bhyveload
/usr/sbin/bhyveload:
        libvmmapi.so.6 => /usr/lib/libvmmapi.so.6 (0x382fc37ae000)
        libc.so.7 => /lib/libc.so.7 (0x382fc47ea000)
        libutil.so.9 => /lib/libutil.so.9 (0x382fc5479000)
        [vdso] (0x382fc2b21000)

こんな方法でもいいかな。

vm_create

sakae@f64:/usr/src/lib/libvmmapi $ grep vm_create *
vmmapi.c:vm_create(const char *name)
vmmapi.c:vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len)
vmmapi.h:void   *vm_create_devmem(struct vmctx *ctx, int segid, const char *name,
vmmapi.h:int    vm_create(const char *name);
#define CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
#define DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))

vm_create(const char *name)
{
        /* Try to load vmm(4) module before creating a guest. */
        if (modfind("vmm") < 0)
                kldload("vmm");
        return (CREATE(name));
}

さて、この先、どうしよう? 無駄にこんなの確認したり。。。

sakae@f64:/usr/src/lib/libvmmapi $ sysctl hw.vmm
 :
hw.vmm.create: beavis
hw.vmm.destroy: beavis
hw.vmm.maxcpu: 2
hw.vmm.trap_wbinvd: 0
hw.vmm.trace_guest_exceptions: 0
hw.vmm.ipinum: 252
hw.vmm.halt_detection: 1

そして、思い出したように。。。

# truss bhyveload -m 384M -d ./FreeBSD-14.1-RELEASE-amd64-disc1.iso test-vm
  :
modfind("vmm")                                   ERR#2 'No such file or directory'
kldload("vmm")                                   ERR#17 'File exists'
__sysctlbyname("hw.vmm.create",13,0x0,0x0,0x35bc252734d4,7) ERR#6 'Device not configured'

for debug

母艦でのdebug環境を用意しておくか。CDイメージが有るので、そこから取り 出せばいいか。えと、どうやるんだっけ? ググる代わりにman mdconfigした ら、こんな技を紹介してくれたよ。これで、リナに馬鹿にされないな。

# mount -t cd9660 /dev/`mdconfig -f FreeBSD-14.1-RELEASE-amd64-disc1.iso` /mnt
# cd /
# tar jxf /mnt/usr/freebsd-dist/kernel-dbg.txz

base-dbg.txzはCDに未収録だったのでネットから取ってきて入れた。

kern_sysctl.c

カーネルサイドを閲覧。

sys___sysctlbyname(struct thread *td, struct __sysctlbyname_args *uap)
{
        size_t rv;
        int error;

        error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,
            uap->oldlenp, uap->new, uap->newlen, &rv, 0, 0);
        if (error != 0)
                return (error);
        if (uap->oldlenp != NULL)
                error = copyout(&rv, uap->oldlenp, sizeof(rv));

        return (error);
}

それから、エラーの名前をsys/*.h から、探し出しておく。

errno.h:#define ENXIO           6               /* Device not configured */

で、カーネル内部の動きを確認したいんだけど、それにはゲストOSとして FreeBSDが必要だ。qemuを入れるのも癪だな。

test

んで、思いついたのは、32BitのFreeBSDに、その環境が有るじゃん。供試品が 必要だな。/usr/sbin中で、sysctlbynameを使っているアプリは無いかな。 実害の無さそうなのがヒットしたんで、取りあえず確認。

sakae@f64:~ $ gdb -q pstat
Reading symbols from pstat...
Reading symbols from /usr/lib/debug//usr/sbin/pstat.debug...
(gdb) b sysctlbyname
Breakpoint 1 at 0x3a80
(gdb) r -hT
Starting program: /usr/sbin/pstat -hT

Breakpoint 1, sysctlbyname (name=0x10222fb "kern.maxfiles",
    oldp=0x7fffffffe8f8, oldlenp=0x7fffffffe8d0, newp=0x0, newlen=0)
    at /usr/src/lib/libc/gen/sysctlbyname.c:43
43              if (__predict_true(strncmp(name, "user.", 5) != 0)) {

on OpenBSD

sysctl(3)

[ENXIO]            If the mib is a sparsely populated array, this error
                   may be returned instead.

mibが疎な配列の場合、代わりにこのエラーが返されることがある。と、deepL は、翻訳してくれたぞ。ちょいと頭の中が混乱してるわい。

on FreeBSD/i386

(gdb) info breakpoints
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x010383fc in sys___sysctl
                                           at /usr/src/sys/kern/kern_sysctl.c:2325
2       breakpoint     keep y   0x0103888c in sys___sysctlbyname
                                           at /usr/src/sys/kern/kern_sysctl.c:2397

これではブレークしないなあ? truss pstat -hT では、ちゃんと

__sysctl("sysctl.name2oid vm.swap_info",2,0xffbfe18c,0xffbfe104,0x400c63,12) = 0 (0x0)
__sysctl("vm.swap_info.0",3,0xffbfe114,0xffbfe10c,0x0,0) = 0 (0x0)
__sysctlbyname("kern.devname",12,0x20621795,0xffbfe0cc,0xffbfe0d0,8) = 0 (0x0)
__sysctl("vm.swap_info.1",3,0xffbfe114,0xffbfe10c,0x0,0) ERR#2 'No such file or directory'

出てくるんだけどな。これ以上の深入りは止めておこう。

other way

そもそもカーネル側を調べたいってのは、エラーの現場を現行犯逮捕したいか ら。多分ハードの要件が有るはずなんで、原点に返ってハンドブックを確認。

The easiest way to tell if an Intel or AMD processor supports bhyve is to run dmesg or look in /var/run/dmesg.boot for the POPCNT processor feature flag on the Features2 line for AMD® processors or EPT and UG on the VT-x line for Intel® processors.

vmm.koって事で、その在処を探すと、/sys/amd64/vmm/

sakae@f64:/sys/amd64/vmm/intel $ grep ENXIO *
vmx.c:          return (ENXIO);
vmx.c:          return (ENXIO);
vtd.c:          return (ENXIO);
vtd.c:          return (ENXIO);

OSからしたら、ドライバーの扱いなのか。vmx.c

/* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */
if (!(cpu_feature2 & CPUID2_VMX)) {
        printf("vmx_modinit: processor does not support VMX "
            "operation\n");
        return (ENXIO);
}

/*
 * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits
 * are set (bits 0 and 2 respectively).
 */
feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 1 &&
    (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) {
        printf("vmx_modinit: VMX operation disabled by BIOS\n");
        return (ENXIO);

dmesgを精査したら、残念なCPUってのが判明しちゃったぞ。

f64 kernel log messages:
+avail memory = 998932480 (952 MB)
+vmx_modinit: processor does not support VMX operation
+module_register_init: MOD_LOAD (vmm, 0xffffffff8213cf90, 0) error 6

research

既に大勢は判明しちゃったけど、後追いしてみる。

FreeBSD 14.0 RELEASE + bhyve で各種 OS を使用する

FreeBSD bhyve hypervisor to run OpenBSD virtual machines

bhyve FAQ

vm-bhyve

こちらが、判定基準。

Intel CPU

$ egrep '(EPT|UG|VT-x)' /var/run/dmesg.boot
  VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID

AMD CPU

$ grep 'POPCNT' /var/run/dmesg.boot   
Features2=0x7ed8320b<SSE3,PCLMULQDQ,MON,SSSE3,FMA,CX16,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,AVX,F16C,RDRAND>

My CPU

CPU: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz (2400.00-MHz K8-class CPU)
  Origin="GenuineIntel"  Id=0x406e3  Family=0x6  Model=0x4e  Stepping=3
  Features=0xf83fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2,SS>
  Features2=0xfffa3203<SSE3,PCLMULQDQ,SSSE3,FMA,CX16,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,TSCDLT,AESNI,XSAVE,OSXSAVE,AVX,F16C,RDRAND,HV>
  AMD Features=0x2c100800<SYSCALL,NX,Page1GB,RDTSCP,LM>
  AMD Features2=0x121<LAHF,ABM,Prefetch>
  Structured Extended Features=0x9c27ab<FSGSBASE,TSCADJ,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,NFPUSG,RDSEED,ADX,SMAP,CLFLUSHOPT>
  Structured Extended Features3=0xbc000400<MD_CLEAR,IBPB,STIBP,L1DFL,ARCH_CAP,SSBD>
  XSAVE Features=0xf<XSAVEOPT,XSAVEC,XINUSE,XSAVES>
  IA32_ARCH_CAPS=0x4<RSBA>
  TSC: P-state invariant
Hypervisor: Origin = "VMwareVMware"

こりゃ、駄目だわさ。VMWarePlayerのプロセッサー設定項目に、Intel VT-x/EPT の仮想化ってのが有る。けど、Playerでは有効化しても、無視され る。残念であります。

ChatGPT

そして、恒例のやつ。

Q: FreeBSD/amd64について質問します。manに例として掲載されてたコマンドを 実行すると、エラーになります。考えられる原因と対処方法を詳しく提示して ください。

# bhyveload -m 384M -d ./FreeBSD-14.1-RELEASE-amd64-disc1.iso test-vm
bhyveload: vm_create: Device not configured

A: `bhyveload`コマンドを実行するときに発生するエラー「bhyveload: vm_create : Device not configured」には、いくつかの原因が考えられます。以下に考えられる原因と対処方法を示します。

### 考えられる原因と対処方法

  1. VMサポートが有効になっていない
    • FreeBSDのbhyveは、カーネルモジュールがロードされている必要があります。`vmm`カーネルモジュールがロードされているか確認してください。
    • 確認方法:

      kldstat | grep vmm

    • 結果が空の場合は、モジュールをロードする必要があります。

      kldload vmm

    • 永続的に有効にするには、`/boot/loader.conf`に以下の行を追加します。

      vmm_load ="YES"

  1. 適切な権限がない
    • `bhyve`はルート権限で実行する必要があります。`root`ユーザーで実行していることを確認してください。
    • 確認方法:

      whoami

    • `root`でない場合は、`sudo`を使ってコマンドを実行します。

      sudo bhyveload -m 384M -d ./FreeBSD-14.1-RELEASE-amd64-disc1.iso test-vm

  1. /dev/vmmが存在しない
    • `/dev/vmm`デバイスが存在するか確認してください。
    • 確認方法:

      ls /dev/vmm

    • 存在しない場合は、`vmm`カーネルモジュールが正しくロードされていない可能性があります。再度、モジュールのロードを試みてください。

      kldload vmm

  1. VMの設定が正しくない
    • VMの名前に問題があるか、既に存在するVMと名前が重複していないか確認してください。
    • VMの状態を確認するには、`bhyvectl`コマンドを使います。

      bhyvectl –vm=test-vm –destroy

    • 既存のVMを破棄してから、再度`bhyveload`を実行します。
  2. bhyveの設定ファイルが不完全
    • 設定ファイルやパーミッションに問題がある場合、`bhyveload`が正しく動作しないことがあります。
    • `/var/log/messages`などのログファイルを確認し、追加のエラーメッセージや警告がないか確認してください。

### 追加の対処方法

上記の基本的なトラブルシューティングを行った後でも問題が解決しない場合は、以下の追加対策を試みることができます。

  1. FreeBSDのバージョンを確認
    • 使用しているFreeBSDのバージョンが最新であり、すべてのパッケージがアップデートされていることを確認します。
freebsd-version
freebsd-update fetch
freebsd-update install
  1. ISOファイルの確認
    • ISOファイルが正しくダウンロードされており、破損していないことを確認します。

      sha256 FreeBSD-14.1-RELEASE-amd64-disc1.iso

    • 公式サイトで提供されているチェックサムと一致するか確認してください。

以上の対処方法を試してもエラーが解決しない場合は、より具体的なシステム のログや設定ファイルの内容を確認する必要があります。また、FreeBSDの公 式ドキュメントやフォーラムを参照することも役立ちます。


This year's Index

Home