1248484Sneel#!/bin/sh 2248484Sneel# 3248484Sneel# Copyright (c) 2013 NetApp, Inc. 4248484Sneel# All rights reserved. 5248484Sneel# 6248484Sneel# Redistribution and use in source and binary forms, with or without 7248484Sneel# modification, are permitted provided that the following conditions 8248484Sneel# are met: 9248484Sneel# 1. Redistributions of source code must retain the above copyright 10248484Sneel# notice, this list of conditions and the following disclaimer. 11248484Sneel# 2. Redistributions in binary form must reproduce the above copyright 12248484Sneel# notice, this list of conditions and the following disclaimer in the 13248484Sneel# documentation and/or other materials provided with the distribution. 14248484Sneel# 15248484Sneel# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16248484Sneel# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17248484Sneel# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18248484Sneel# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19248484Sneel# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20248484Sneel# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21248484Sneel# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22248484Sneel# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23248484Sneel# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24248484Sneel# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25248484Sneel# SUCH DAMAGE. 26248484Sneel# 27248484Sneel# $FreeBSD: releng/11.0/share/examples/bhyve/vmrun.sh 289001 2015-10-08 02:28:22Z marcel $ 28248484Sneel# 29248484Sneel 30248484SneelLOADER=/usr/sbin/bhyveload 31248484SneelBHYVECTL=/usr/sbin/bhyvectl 32248484SneelFBSDRUN=/usr/sbin/bhyve 33248484Sneel 34256176SneelDEFAULT_MEMSIZE=512M 35248484SneelDEFAULT_CPUS=2 36248484SneelDEFAULT_TAPDEV=tap0 37264837SjhbDEFAULT_CONSOLE=stdio 38248484Sneel 39248484SneelDEFAULT_VIRTIO_DISK="./diskdev" 40248484SneelDEFAULT_ISOFILE="./release.iso" 41248484Sneel 42277309Sneelerrmsg() { 43277309Sneel echo "*** $1" 44277309Sneel} 45277309Sneel 46248484Sneelusage() { 47277309Sneel local msg=$1 48277309Sneel 49264837Sjhb echo "Usage: vmrun.sh [-ahi] [-c <CPUs>] [-C <console>] [-d <disk file>]" 50264837Sjhb echo " [-e <name=value>] [-g <gdbport> ] [-H <directory>]" 51289001Smarcel echo " [-I <location of installation iso>] [-l <loader>]" 52289001Smarcel echo " [-m <memsize>] [-t <tapdev>] <vmname>" 53264837Sjhb echo "" 54248484Sneel echo " -h: display this help message" 55264837Sjhb echo " -a: force memory mapped local APIC access" 56248484Sneel echo " -c: number of virtual cpus (default is ${DEFAULT_CPUS})" 57264837Sjhb echo " -C: console device (default is ${DEFAULT_CONSOLE})" 58248484Sneel echo " -d: virtio diskdev file (default is ${DEFAULT_VIRTIO_DISK})" 59256657Sneel echo " -e: set FreeBSD loader environment variable" 60248840Sneel echo " -g: listen for connection from kgdb at <gdbport>" 61264837Sjhb echo " -H: host filesystem to export to the loader" 62248484Sneel echo " -i: force boot of the Installation CDROM image" 63248484Sneel echo " -I: Installation CDROM image location (default is ${DEFAULT_ISOFILE})" 64289001Smarcel echo " -l: the OS loader to use (default is /boot/userboot.so)" 65256176Sneel echo " -m: memory size (default is ${DEFAULT_MEMSIZE})" 66279925Sglebius echo " -p: pass-through a host PCI device at bus/slot/func (e.g. 10/0/0)" 67248484Sneel echo " -t: tap device for virtio-net (default is $DEFAULT_TAPDEV)" 68248484Sneel echo "" 69277309Sneel [ -n "$msg" ] && errmsg "$msg" 70248484Sneel exit 1 71248484Sneel} 72248484Sneel 73248484Sneelif [ `id -u` -ne 0 ]; then 74277309Sneel errmsg "This script must be executed with superuser privileges" 75277309Sneel exit 1 76248484Sneelfi 77248484Sneel 78248484Sneelkldstat -n vmm > /dev/null 2>&1 79248484Sneelif [ $? -ne 0 ]; then 80277309Sneel errmsg "vmm.ko is not loaded" 81248484Sneel exit 1 82248484Sneelfi 83248484Sneel 84248484Sneelforce_install=0 85248484Sneelisofile=${DEFAULT_ISOFILE} 86248484Sneelmemsize=${DEFAULT_MEMSIZE} 87264837Sjhbconsole=${DEFAULT_CONSOLE} 88248484Sneelcpus=${DEFAULT_CPUS} 89267559Salfredtap_total=0 90267559Salfreddisk_total=0 91248840Sneelgdbport=0 92264837Sjhbloader_opt="" 93284539Sneelbhyverun_opt="-H -A -P" 94279925Sglebiuspass_total=0 95248484Sneel 96289001Smarcelwhile getopts ac:C:d:e:g:hH:iI:l:m:p:t: c ; do 97248484Sneel case $c in 98248484Sneel a) 99284539Sneel bhyverun_opt="${bhyverun_opt} -a" 100248484Sneel ;; 101264837Sjhb c) 102264837Sjhb cpus=${OPTARG} 103264837Sjhb ;; 104264837Sjhb C) 105264837Sjhb console=${OPTARG} 106264837Sjhb ;; 107248484Sneel d) 108284023Savg disk_dev=${OPTARG%%,*} 109284023Savg disk_opts=${OPTARG#${disk_dev}} 110284023Savg eval "disk_dev${disk_total}=\"${disk_dev}\"" 111284023Savg eval "disk_opts${disk_total}=\"${disk_opts}\"" 112267559Salfred disk_total=$(($disk_total + 1)) 113248484Sneel ;; 114256657Sneel e) 115264837Sjhb loader_opt="${loader_opt} -e ${OPTARG}" 116256657Sneel ;; 117264837Sjhb g) 118264837Sjhb gdbport=${OPTARG} 119248840Sneel ;; 120264837Sjhb H) 121264837Sjhb host_base=`realpath ${OPTARG}` 122264837Sjhb ;; 123248484Sneel i) 124248484Sneel force_install=1 125248484Sneel ;; 126248484Sneel I) 127248484Sneel isofile=${OPTARG} 128248484Sneel ;; 129289001Smarcel l) 130289001Smarcel loader_opt="${loader_opt} -l ${OPTARG}" 131289001Smarcel ;; 132248484Sneel m) 133248484Sneel memsize=${OPTARG} 134248484Sneel ;; 135279925Sglebius p) 136279925Sglebius eval "pass_dev${pass_total}=\"${OPTARG}\"" 137279925Sglebius pass_total=$(($pass_total + 1)) 138279925Sglebius ;; 139248484Sneel t) 140267559Salfred eval "tap_dev${tap_total}=\"${OPTARG}\"" 141267559Salfred tap_total=$(($tap_total + 1)) 142248484Sneel ;; 143264837Sjhb *) 144248484Sneel usage 145248484Sneel ;; 146248484Sneel esac 147248484Sneeldone 148248484Sneel 149267559Salfredif [ $tap_total -eq 0 ] ; then 150267559Salfred tap_total=1 151267559Salfred tap_dev0="${DEFAULT_TAPDEV}" 152267559Salfredfi 153267559Salfredif [ $disk_total -eq 0 ] ; then 154267559Salfred disk_total=1 155267559Salfred disk_dev0="${DEFAULT_VIRTIO_DISK}" 156267559Salfred 157267559Salfredfi 158267559Salfred 159248484Sneelshift $((${OPTIND} - 1)) 160248484Sneel 161248484Sneelif [ $# -ne 1 ]; then 162277309Sneel usage "virtual machine name not specified" 163248484Sneelfi 164248484Sneel 165248484Sneelvmname="$1" 166264837Sjhbif [ -n "${host_base}" ]; then 167264837Sjhb loader_opt="${loader_opt} -h ${host_base}" 168264837Sjhbfi 169248484Sneel 170284539Sneel# If PCI passthru devices are configured then guest memory must be wired 171284539Sneelif [ ${pass_total} -gt 0 ]; then 172284539Sneel loader_opt="${loader_opt} -S" 173284539Sneel bhyverun_opt="${bhyverun_opt} -S" 174284539Sneelfi 175284539Sneel 176267559Salfredmake_and_check_diskdev() 177267559Salfred{ 178267559Salfred local virtio_diskdev="$1" 179267559Salfred # Create the virtio diskdev file if needed 180273102Sneel if [ ! -e ${virtio_diskdev} ]; then 181267559Salfred echo "virtio disk device file \"${virtio_diskdev}\" does not exist." 182267559Salfred echo "Creating it ..." 183267559Salfred truncate -s 8G ${virtio_diskdev} > /dev/null 184267559Salfred fi 185248484Sneel 186267559Salfred if [ ! -r ${virtio_diskdev} ]; then 187267559Salfred echo "virtio disk device file \"${virtio_diskdev}\" is not readable" 188267559Salfred exit 1 189267559Salfred fi 190248484Sneel 191267559Salfred if [ ! -w ${virtio_diskdev} ]; then 192267559Salfred echo "virtio disk device file \"${virtio_diskdev}\" is not writable" 193267559Salfred exit 1 194267559Salfred fi 195267559Salfred} 196248484Sneel 197248484Sneelecho "Launching virtual machine \"$vmname\" ..." 198248484Sneel 199284024Savgfirst_diskdev="$disk_dev0" 200267559Salfred 201270513Srodrigc${BHYVECTL} --vm=${vmname} --destroy > /dev/null 2>&1 202270513Srodrigc 203248484Sneelwhile [ 1 ]; do 204248484Sneel 205284024Savg file -s ${first_diskdev} | grep "boot sector" > /dev/null 206248484Sneel rc=$? 207248484Sneel if [ $rc -ne 0 ]; then 208284024Savg file -s ${first_diskdev} | grep ": Unix Fast File sys" > /dev/null 209248484Sneel rc=$? 210248484Sneel fi 211248484Sneel if [ $rc -ne 0 ]; then 212248484Sneel need_install=1 213248484Sneel else 214248484Sneel need_install=0 215248484Sneel fi 216248484Sneel 217248484Sneel if [ $force_install -eq 1 -o $need_install -eq 1 ]; then 218248484Sneel if [ ! -r ${isofile} ]; then 219248484Sneel echo -n "Installation CDROM image \"${isofile}\" " 220248484Sneel echo "is not readable" 221248484Sneel exit 1 222248484Sneel fi 223284024Savg BOOTDISKS="-d ${isofile}" 224284024Savg installer_opt="-s 31:0,ahci-cd,${isofile}" 225248484Sneel else 226284024Savg BOOTDISKS="" 227284024Savg i=0 228284024Savg while [ $i -lt $disk_total ] ; do 229284024Savg eval "disk=\$disk_dev${i}" 230284024Savg if [ -r ${disk} ] ; then 231284024Savg BOOTDISKS="$BOOTDISKS -d ${disk} " 232284024Savg fi 233284024Savg i=$(($i + 1)) 234284024Savg done 235248484Sneel installer_opt="" 236248484Sneel fi 237248484Sneel 238284024Savg ${LOADER} -c ${console} -m ${memsize} ${BOOTDISKS} ${loader_opt} \ 239264837Sjhb ${vmname} 240271496Srodrigc bhyve_exit=$? 241271496Srodrigc if [ $bhyve_exit -ne 0 ]; then 242248484Sneel break 243248484Sneel fi 244248484Sneel 245267559Salfred # 246267559Salfred # Build up args for additional tap and disk devices now. 247267559Salfred # 248267559Salfred nextslot=2 # slot 0 is hostbridge, slot 1 is lpc 249267559Salfred devargs="" # accumulate disk/tap args here 250267559Salfred i=0 251267559Salfred while [ $i -lt $tap_total ] ; do 252267559Salfred eval "tapname=\$tap_dev${i}" 253267559Salfred devargs="$devargs -s $nextslot:0,virtio-net,${tapname} " 254267559Salfred nextslot=$(($nextslot + 1)) 255267559Salfred i=$(($i + 1)) 256267559Salfred done 257267559Salfred 258267559Salfred i=0 259267559Salfred while [ $i -lt $disk_total ] ; do 260267559Salfred eval "disk=\$disk_dev${i}" 261284023Savg eval "opts=\$disk_opts${i}" 262267559Salfred make_and_check_diskdev "${disk}" 263284023Savg devargs="$devargs -s $nextslot:0,virtio-blk,${disk}${opts} " 264267559Salfred nextslot=$(($nextslot + 1)) 265267559Salfred i=$(($i + 1)) 266267559Salfred done 267267559Salfred 268279925Sglebius i=0 269279925Sglebius while [ $i -lt $pass_total ] ; do 270279925Sglebius eval "pass=\$pass_dev${i}" 271279925Sglebius devargs="$devargs -s $nextslot:0,passthru,${pass} " 272279925Sglebius nextslot=$(($nextslot + 1)) 273279925Sglebius i=$(($i + 1)) 274279925Sglebius done 275279925Sglebius 276284539Sneel ${FBSDRUN} -c ${cpus} -m ${memsize} ${bhyverun_opt} \ 277248840Sneel -g ${gdbport} \ 278248484Sneel -s 0:0,hostbridge \ 279257293Sneel -s 1:0,lpc \ 280267559Salfred ${devargs} \ 281264837Sjhb -l com1,${console} \ 282248484Sneel ${installer_opt} \ 283248484Sneel ${vmname} 284270512Srodrigc 285271496Srodrigc bhyve_exit=$? 286270512Srodrigc # bhyve returns the following status codes: 287270512Srodrigc # 0 - VM has been reset 288270512Srodrigc # 1 - VM has been powered off 289270512Srodrigc # 2 - VM has been halted 290270512Srodrigc # 3 - VM generated a triple fault 291270512Srodrigc # all other non-zero status codes are errors 292270512Srodrigc # 293271496Srodrigc if [ $bhyve_exit -ne 0 ]; then 294248484Sneel break 295248484Sneel fi 296248484Sneeldone 297248484Sneel 298271496Srodrigc 299271496Srodrigccase $bhyve_exit in 300271496Srodrigc 0|1|2) 301271496Srodrigc # Cleanup /dev/vmm entry when bhyve did not exit 302271496Srodrigc # due to an error. 303271496Srodrigc ${BHYVECTL} --vm=${vmname} --destroy > /dev/null 2>&1 304271496Srodrigc ;; 305271496Srodrigcesac 306271496Srodrigc 307271496Srodrigcexit $bhyve_exit 308