• en 
  • | it
  • FreeBSD as a Host with bhyve

    1. Prepare the Host

    1.1. 1. Check processor support for bhyve module

    Check if the 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.

    root@freebsd:~ # dmesg | egrep 'EPT|UG' --color
      VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
      VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
      VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
      VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
      VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
      VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
      VT-x: PAT,HLT,MTF,PAUSE,EPT,UG,VPID
    root@freebsd:~ #
    

    1.2. 2. Load the module

    added following lines to /boot/loader.conf on FreeBSD host

    # needed for virtualization support
    vmm_load="YES"
    

    to load the kernel module without rebooting issue the following command

    root@freebsd:~ # kldload vmm
    

    1.3. 3. Create bhyve directory structure

    For ZFS

    zfs create zroot/bhyve
    

    2. Configure bhyve Networking

    2.1. NAT (Option 1)

    Create single bridge and add a separate tap device for each Guest VMs:

    root@freebsd:~ # ifconfig bridge create name brnat up
    brnat
    root@freebsd:~ # ifconfig tap create up
    tap0
    root@freebsd:~ # ifconfig brnat addm tap0
    
    root@freebsd:~ # ifconfig brnat inet 10.0.0.1/24
    

    added to /etc/pf.conf

    virt_net="10.0.0.0/24"
    set skip on brnat
    nat on $ext_if from $virt_net to any -> ($ext_if)
    

    Enable ip forwarding

    root@freebsd:~ # sysctl net.inet.ip.forwarding
    net.inet.ip.forwarding: 1
    root@freebsd:~ #
    

    Assign ip to bridge

    root@freebsd:~ # ifconfig brnat inet 10.0.0.1/24
    

    An IP can then be assigned to the Guest VM from the 10.0.0.0/24 network and the default gw set to 10.0.0.1.

    2.2. Passthrough (Option 2)

    FreeBSD Wiki - bhyve PCI Passthrough

    root@freebsd:/zroot/bhyve # pciconf -lv vmx1
    vmx1@pci0:19:0:0:       class=0x020000 rev=0x01 hdr=0x00 vendor=0x15ad device=0x07b0 subvendor=0x15ad subdevice=0x07b0
        vendor     = 'VMware'
        device     = 'VMXNET3 Ethernet Controller'
        class      = network
        subclass   = ethernet
    root@freebsd:/zroot/bhyve #
    

    add following to /boot/loader.conf and reboot

    pptdevs="19/0/0"
    

    add to bhyve config

    bhyve -A -H -P \
    -s 0:0,hostbridge \
    -s 1:0,lpc \
    -s 6,passthru,19/0/0 \
    -s 3:0,virtio-blk,./linux.img \
    -l com1,stdio \
    -c 4 \
    -m 2048M linux
    

    3. Create Guest VMs

    3.1. Create ZFS volume or disk image

    Create a ZFS volume

    # zfs create -V16G -o volmode=dev zroot/linuxdisk0
    

    or a disk image with truncate

    root@freebsd:~ # truncate -s 16G linux.img
    

    3.1.1. For UEFI based VMs (Option 1)

    Install sysutils/bhyve-firmware

    Create a per-guest-copy of the variables template file:

    # cp /usr/local/share/uefi-firmware/BHYVE_UEFI_VARS.fd /path/to/vm-image/BHYVE_UEFI_VARS.fd
    

    Create a bhyve boot script:

    cat start-linux.sh
    bhyve -AHP \
          -s 0:0,hostbridge \
          -s 1:0,lpc \
          -s 2:0,virtio-net,tap1 \
          -s 3:0,virtio-blk,/dev/zvol/zroot/rheldisc0 \
          -s 4:0,ahci-cd,./rhel-8.10-x86_64-dvd.iso \
          -c 4 \
          -m 2048M \
          -u \
          -s 29,fbuf,password="PASSWORDHERE",tcp=0.0.0.0:5900 \
          -s 30,xhci,tablet \
          -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd,./BHYVE_UEFI_VARS.fd \
          rhel
    

    Start the VM.

    # ./start-linux.sh
    

    Stop the VM when needed:

    # cat ./destroy.sh
    bhyvectl --destroy --vm=debian1
    

    3.1.2. Booting with GRUB (Option 2)

    Install sysutils/grub2-bhyve port.

    Create a device.map that grub will use to map the virtual devices to the files on the host system:

    root@freebsd:/zroot/bhyve # cat device.map
    (hd0) ./linux.img
    (cd0) ./ubuntu-22.04.4-live-server-amd64.iso
    root@freebsd:/zroot/bhyve #
    
    1. Use sysutils/grub2-bhyve to load the Linux® kernel from the ISO image:
    root@freebsd:/zroot/bhyve # grub-bhyve -m device.map -r cd0 -M 1024M linux
    
    1. Now that the Linux® kernel is loaded, the guest can be started:
    root@freebsd:/zroot/bhyve # bhyve -A -H -P \
        -s 0:0,hostbridge \
        -s 1:0,lpc \
        -s 2:0,virtio-net,tap0 \
        -s 3:0,virtio-blk,./linux.img \
        -s 4:0,ahci-cd,./ubuntu-22.04.4-live-server-amd64.iso \
        -l com1,stdio \
        -c 4 \
        -m 1024M linux
    
    1. The system will boot and start the installer. After installing a system in the virtual machine, reboot the virtual machine. This will cause bhyve to exit. The instance of the virtual machine needs to be destroyed before it can be started again:
    root@freebsd:~ # bhyvectl --destroy --vm=linux
    

    4 (a). Now the guest can be started directly from the virtual disk. Load the kernel:

    grub> ls
    (hd0) (hd0,gpt3) (hd0,gpt2) (hd0,gpt1) (cd0) (cd0,gpt3) (cd0,gpt2) (cd0,gpt1) (host) (lvm/ubuntu--vg-ubuntu--lv)
    grub> ls (hd0,gpt2)/
    lost+found/ grub/ config-5.15.0-94-generic initrd.img.old vmlinuz.old System.map-5.15.0-94-generic vmlinuz-5.15.0-94-generic initrd.img
    vmlinuz initrd.img-5.15.0-94-generic
    grub> linux (hd0,gpt2)/vmlinuz-5.15.0-94-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv
    grub> initrd (hd0,gpt2)/initrd.img-5.15.0-94-generic
    grub> boot
    

    4 (b). Boot the new system

    root@freebsd:/zroot/bhyve # cat boot.sh
    bhyve -A -H -P \
        -s 0:0,hostbridge \
        -s 1:0,lpc \
        -s 2:0,virtio-net,tap0 \
        -s 3:0,virtio-blk,./linux.img \
        -l com1,stdio \
        -c 4 \
        -m 1024M \
        -u \
        linux
    root@freebsd:/zroot/bhyve #
    

    When finished reboot and destroy:

    guestvm# reboot
    bhyvehost# bhyvectl --destroy --vm=debian
    
    1. Create a start script which automatically loads the kernel (4 a.) and boots the VM (4 b.):
    #!/bin/sh
    
    grub-bhyve -m device.map -r hd0,gpt2 -M 2048M linux < linux-grub.cfg > /dev/null
    
    bhyve -A -H -P \
        -s 0:0,hostbridge \
        -s 1:0,lpc \
        -s 2:0,virtio-net,tap0 \
        -s 3:0,virtio-blk,./linux.img \
        -l com1,stdio \
        -c 8 \
        -m 2048M \
        -u \
        linux
    

    device.map

    (hd0) ./linux.img
    (cd0) ./ubuntu-22.04.4-live-server-amd64.iso
    

    linux-grub.cfg

    linux (hd0,gpt2)/vmlinuz-5.15.0-122-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv
    initrd (hd0,gpt2)/initrd.img-5.15.0-122-generic
    boot
    

    4. Start VMs when FreeBSD Host boots

    crontab

    root@freebsd:~ # crontab -l
    @reboot /zroot/bhyve/linux-nat.sh
    @reboot cd /zroot/bhyve/ubuntu; /usr/local/bin/tmux new-session -d -s "ubuntu" /zroot/bhyve/ubuntu/linux-start.sh
    root@freebsd:~ #
    

    /zroot/bhyve/linux-nat.sh

    root@freebsd:~ # cat /zroot/bhyve/linux-nat.sh
    #!/bin/sh
    
    ifconfig bridge create name brnat up
    ifconfig tap create up
    ifconfig tap create up
    ifconfig brnat addm tap0
    ifconfig brnat addm tap1
    ifconfig brnat inet 10.0.0.1/24
    root@freebsd:~ #
    

    Author: https://vieron.info

    Created: 2025-06-04 Wed 15:21