diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 983fea2cb8c2..00b8b8c57ee1 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -1,478 +1,473 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
 # $FreeBSD$
 #
 
 # common files stuff between i386 and amd64
 include 	"conf/files.x86"
 
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
 # dependency lines other than the first are silently ignored.
 #
 #
 cloudabi32_vdso.o		optional	compat_cloudabi32	\
 	dependency	"$S/contrib/cloudabi/cloudabi_vdso_i686_on_64bit.S" \
 	compile-with	"${CC} -x assembler-with-cpp -m32 -shared -nostdinc -nostdlib -Wl,-T$S/compat/cloudabi/cloudabi_vdso.lds $S/contrib/cloudabi/cloudabi_vdso_i686_on_64bit.S -o ${.TARGET}" \
 	no-obj no-implicit-rule						\
 	clean		"cloudabi32_vdso.o"
 #
 cloudabi32_vdso_blob.o		optional	compat_cloudabi32	\
 	dependency 	"cloudabi32_vdso.o"				\
 	compile-with	"${OBJCOPY} --input-target binary --output-target elf64-x86-64-freebsd --binary-architecture i386 cloudabi32_vdso.o ${.TARGET}" \
 	no-implicit-rule						\
 	clean		"cloudabi32_vdso_blob.o"
 #
 cloudabi64_vdso.o		optional	compat_cloudabi64	\
 	dependency	"$S/contrib/cloudabi/cloudabi_vdso_x86_64.S"	\
 	compile-with	"${CC} -x assembler-with-cpp -shared -nostdinc -nostdlib -Wl,-T$S/compat/cloudabi/cloudabi_vdso.lds $S/contrib/cloudabi/cloudabi_vdso_x86_64.S -o ${.TARGET}" \
 	no-obj no-implicit-rule						\
 	clean		"cloudabi64_vdso.o"
 #
 cloudabi64_vdso_blob.o		optional	compat_cloudabi64	\
 	dependency 	"cloudabi64_vdso.o"				\
 	compile-with	"${OBJCOPY} --input-target binary --output-target elf64-x86-64-freebsd --binary-architecture i386 cloudabi64_vdso.o ${.TARGET}" \
 	no-implicit-rule						\
 	clean		"cloudabi64_vdso_blob.o"
 #
 linux32_genassym.o		optional	compat_linux32		\
 	dependency 	"$S/amd64/linux32/linux32_genassym.c offset.inc"		\
 	compile-with	"${CC} ${CFLAGS:N-flto:N-fno-common} -fcommon -c ${.IMPSRC}" \
 	no-obj no-implicit-rule						\
 	clean		"linux32_genassym.o"
 #
 linux32_assym.h			optional	compat_linux32		\
 	dependency 	"$S/kern/genassym.sh linux32_genassym.o"	\
 	compile-with	"sh $S/kern/genassym.sh linux32_genassym.o > ${.TARGET}" \
 	no-obj no-implicit-rule before-depend				\
 	clean		"linux32_assym.h"
 #
 linux32_locore.o	optional	compat_linux32		\
 	dependency 	"linux32_assym.h $S/amd64/linux32/linux32_locore.asm"	\
 	compile-with	"${CC} -x assembler-with-cpp -DLOCORE -m32 -shared -s -pipe -I. -I$S ${WERROR} -Wall -fPIC -fno-common -nostdinc -nostdlib -Wl,-T$S/amd64/linux32/linux32_vdso.lds.s -Wl,-soname=linux32_vdso.so,--eh-frame-hdr,-warn-common ${.IMPSRC} -o ${.TARGET}" \
 	no-obj no-implicit-rule						\
 	clean		"linux32_locore.o"
 #
 linux32_vdso.so		optional	compat_linux32			\
 	dependency 	"linux32_locore.o"				\
 	compile-with	"${OBJCOPY} --input-target binary --output-target elf64-x86-64-freebsd --binary-architecture i386 linux32_locore.o ${.TARGET}" \
 	no-implicit-rule						\
 	clean		"linux32_vdso.so"
 #
 ia32_genassym.o			standard				\
 	dependency 	"$S/compat/ia32/ia32_genassym.c offset.inc"		\
 	compile-with	"${CC} ${CFLAGS:N-flto:N-fno-common} -fcommon -c ${.IMPSRC}" \
 	no-obj no-implicit-rule						\
 	clean		"ia32_genassym.o"
 #
 ia32_assym.h			standard				\
 	dependency 	"$S/kern/genassym.sh ia32_genassym.o"		\
 	compile-with	"env NM='${NM}' NMFLAGS='${NMFLAGS}' sh $S/kern/genassym.sh ia32_genassym.o > ${.TARGET}" \
 	no-obj no-implicit-rule before-depend				\
 	clean		"ia32_assym.h"
 #
 amd64/acpica/acpi_machdep.c	optional	acpi
 acpi_wakecode.o			optional	acpi			\
 	dependency	"$S/amd64/acpica/acpi_wakecode.S assym.inc"	\
 	compile-with	"${NORMAL_S}"					\
 	no-obj no-implicit-rule before-depend				\
 	clean		"acpi_wakecode.o"
 acpi_wakecode.bin		optional	acpi			\
 	dependency	"acpi_wakecode.o"				\
 	compile-with	"${OBJCOPY} -S -O binary acpi_wakecode.o ${.TARGET}" \
 	no-obj no-implicit-rule	before-depend				\
 	clean		"acpi_wakecode.bin"
 acpi_wakecode.h			optional	acpi			\
 	dependency	"acpi_wakecode.bin"				\
 	compile-with	"file2c -sx 'static char wakecode[] = {' '};' < acpi_wakecode.bin > ${.TARGET}" \
 	no-obj no-implicit-rule	before-depend				\
 	clean		"acpi_wakecode.h"
 acpi_wakedata.h			optional	acpi			\
 	dependency	"acpi_wakecode.o"				\
 	compile-with	'${NM} -n --defined-only acpi_wakecode.o | while read offset dummy what; do echo "#define	$${what}	0x$${offset}"; done > ${.TARGET}' \
 	no-obj no-implicit-rule	before-depend				\
 	clean		"acpi_wakedata.h"
 #
 #amd64/amd64/apic_vector.S	standard
 amd64/amd64/bios.c		standard
 amd64/amd64/bpf_jit_machdep.c	optional	bpf_jitter
 amd64/amd64/copyout.c		standard
 amd64/amd64/cpu_switch.S	standard
 amd64/amd64/db_disasm.c		optional	ddb
 amd64/amd64/db_interface.c	optional	ddb
 amd64/amd64/db_trace.c		optional	ddb
 amd64/amd64/efirt_machdep.c	optional	efirt
 amd64/amd64/efirt_support.S	optional	efirt
 amd64/amd64/elf_machdep.c	standard
 amd64/amd64/exception.S		standard
 amd64/amd64/fpu.c		standard
 amd64/amd64/gdb_machdep.c	optional	gdb
 amd64/amd64/in_cksum.c		optional	inet | inet6
 amd64/amd64/initcpu.c		standard
 amd64/amd64/io.c		optional	io
 amd64/amd64/locore.S		standard	no-obj
 amd64/amd64/xen-locore.S	optional	xenhvm \
 	compile-with "${NORMAL_S} -g0" \
 	no-ctfconvert
 amd64/amd64/machdep.c		standard
 amd64/amd64/mem.c		optional	mem
 amd64/amd64/minidump_machdep.c	standard
 amd64/amd64/mp_machdep.c	optional	smp
 amd64/amd64/mpboot.S		optional	smp
 amd64/amd64/pmap.c		standard
 amd64/amd64/prof_machdep.c	optional	profiling-routine
 amd64/amd64/ptrace_machdep.c	standard
 amd64/amd64/sigtramp.S		standard
 amd64/amd64/support.S		standard
 amd64/amd64/sys_machdep.c	standard
 amd64/amd64/trap.c		standard
 amd64/amd64/uio_machdep.c	standard
 amd64/amd64/uma_machdep.c	standard
 amd64/amd64/vm_machdep.c	standard
 amd64/cloudabi32/cloudabi32_sysvec.c		optional compat_cloudabi32
 amd64/cloudabi64/cloudabi64_sysvec.c		optional compat_cloudabi64
 amd64/pci/pci_cfgreg.c		optional	pci
 cddl/dev/dtrace/amd64/dtrace_asm.S			optional dtrace compile-with "${DTRACE_S}"
 cddl/dev/dtrace/amd64/dtrace_subr.c			optional dtrace compile-with "${DTRACE_C}"
 crypto/aesni/aeskeys_amd64.S	optional aesni
 crypto/des/des_enc.c		optional	netsmb
 crypto/openssl/amd64/sha1-x86_64.S	optional ossl
 crypto/openssl/amd64/sha256-x86_64.S	optional ossl
 crypto/openssl/amd64/sha512-x86_64.S	optional ossl
 dev/acpi_support/acpi_wmi_if.m	standard
 dev/agp/agp_amd64.c		optional	agp
 dev/agp/agp_i810.c		optional	agp
 dev/agp/agp_via.c		optional	agp
 dev/amdgpio/amdgpio.c		optional	amdgpio
 dev/axgbe/if_axgbe_pci.c	optional	axp
 dev/axgbe/xgbe-desc.c		optional	axp
 dev/axgbe/xgbe-dev.c		optional	axp
 dev/axgbe/xgbe-drv.c		optional	axp
 dev/axgbe/xgbe-mdio.c		optional	axp
 dev/axgbe/xgbe-sysctl.c		optional	axp
 dev/axgbe/xgbe-txrx.c		optional	axp
 dev/axgbe/xgbe_osdep.c		optional	axp
 dev/axgbe/xgbe-i2c.c		optional	axp
 dev/axgbe/xgbe-phy-v2.c		optional	axp
 dev/hyperv/vmbus/amd64/hyperv_machdep.c			optional	hyperv
 dev/hyperv/vmbus/amd64/vmbus_vector.S			optional	hyperv
 dev/ice/if_ice_iflib.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_lib.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_osdep.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_resmgr.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_strings.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_iflib_recovery_txrx.c	optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_iflib_txrx.c	optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_common.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_controlq.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_dcb.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_flex_pipe.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_flow.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_nvm.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_sched.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_sriov.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 dev/ice/ice_switch.c		optional	ice pci \
 	compile-with "${NORMAL_C} -I$S/dev/ice"
 ice_ddp.c			optional ice_ddp	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk ice_ddp.fw:ice_ddp:0x01031000 -mice_ddp -c${.TARGET}"	\
 	no-implicit-rule before-depend local		\
 	clean		"ice_ddp.c"
 ice_ddp.fwo			optional ice_ddp	\
 	dependency	"ice_ddp.fw"			\
 	compile-with	"${NORMAL_FWO}"			\
 	no-implicit-rule				\
 	clean		"ice_ddp.fwo"
 ice_ddp.fw			optional ice_ddp	\
 	dependency	"$S/contrib/dev/ice/ice-1.3.16.0.pkg" \
 	compile-with	"${CP} $S/contrib/dev/ice/ice-1.3.16.0.pkg ice_ddp.fw" \
 	no-obj no-implicit-rule				\
 	clean		"ice_ddp.fw"
 dev/ioat/ioat.c			optional	ioat pci
 dev/ioat/ioat_test.c		optional	ioat pci
 dev/ixl/if_ixl.c		optional	ixl pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_pf_main.c		optional	ixl pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_pf_iflib.c		optional	ixl pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_pf_qmgr.c		optional	ixl pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_pf_iov.c		optional	ixl pci  pci_iov \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_pf_i2c.c		optional	ixl pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/if_iavf.c		optional	iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/iavf_vc.c			optional	iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/ixl_txrx.c		optional	ixl pci | iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/i40e_osdep.c		optional	ixl pci | iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/i40e_lan_hmc.c		optional	ixl pci | iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/i40e_hmc.c		optional	ixl pci | iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/i40e_common.c		optional	ixl pci | iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/i40e_nvm.c		optional	ixl pci | iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/i40e_adminq.c		optional	ixl pci | iavf pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/ixl/i40e_dcb.c		optional	ixl pci \
 	compile-with "${NORMAL_C} -I$S/dev/ixl"
 dev/nctgpio/nctgpio.c		optional	nctgpio
 dev/nfe/if_nfe.c		optional	nfe pci
 dev/ntb/if_ntb/if_ntb.c		optional	if_ntb
 dev/ntb/ntb_transport.c		optional	ntb_transport | if_ntb
 dev/ntb/ntb.c			optional	ntb | ntb_transport | if_ntb | ntb_hw_amd | ntb_hw_intel | ntb_hw_plx | ntb_hw
 dev/ntb/ntb_if.m		optional	ntb | ntb_transport | if_ntb | ntb_hw_amd | ntb_hw_intel | ntb_hw_plx | ntb_hw
 dev/ntb/ntb_hw/ntb_hw_amd.c	optional	ntb_hw_amd | ntb_hw
 dev/ntb/ntb_hw/ntb_hw_intel.c	optional	ntb_hw_intel | ntb_hw
 dev/ntb/ntb_hw/ntb_hw_plx.c	optional	ntb_hw_plx | ntb_hw
 dev/ntb/test/ntb_tool.c		optional	ntb_tool
 dev/nvram/nvram.c		optional	nvram isa
 dev/random/ivy.c		optional	rdrand_rng !random_loadable
 dev/random/nehemiah.c		optional	padlock_rng !random_loadable
 dev/qlxge/qls_dbg.c		optional	qlxge pci
 dev/qlxge/qls_dump.c		optional	qlxge pci
 dev/qlxge/qls_hw.c		optional	qlxge pci
 dev/qlxge/qls_ioctl.c		optional	qlxge pci
 dev/qlxge/qls_isr.c		optional	qlxge pci
 dev/qlxge/qls_os.c		optional	qlxge pci
 dev/qlxgb/qla_dbg.c		optional	qlxgb pci
 dev/qlxgb/qla_hw.c		optional	qlxgb pci
 dev/qlxgb/qla_ioctl.c		optional	qlxgb pci
 dev/qlxgb/qla_isr.c		optional	qlxgb pci
 dev/qlxgb/qla_misc.c		optional	qlxgb pci
 dev/qlxgb/qla_os.c		optional	qlxgb pci
 dev/qlxgbe/ql_dbg.c		optional	qlxgbe pci
 dev/qlxgbe/ql_hw.c		optional	qlxgbe pci
 dev/qlxgbe/ql_ioctl.c		optional	qlxgbe pci
 dev/qlxgbe/ql_isr.c		optional	qlxgbe pci
 dev/qlxgbe/ql_misc.c		optional	qlxgbe pci
 dev/qlxgbe/ql_os.c		optional	qlxgbe pci
 dev/qlxgbe/ql_reset.c		optional	qlxgbe pci
 dev/qlxgbe/ql_fw.c		optional	qlxgbe pci
 dev/qlxgbe/ql_boot.c		optional	qlxgbe pci
 dev/qlxgbe/ql_minidump.c	optional	qlxgbe pci
 dev/qlnx/qlnxe/ecore_cxt.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_dbg_fw_funcs.c optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_dcbx.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_dev.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_hw.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_init_fw_funcs.c optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_init_ops.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_int.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_l2.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_mcp.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_sp_commands.c optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/ecore_spq.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/qlnx_ioctl.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/qlnx/qlnxe/qlnx_os.c	optional	qlnxe pci \
 	compile-with "${LINUXKPI_C}"
 dev/sfxge/common/ef10_ev.c	optional	sfxge pci
 dev/sfxge/common/ef10_filter.c	optional	sfxge pci
 dev/sfxge/common/ef10_image.c	optional	sfxge pci
 dev/sfxge/common/ef10_intr.c	optional	sfxge pci
 dev/sfxge/common/ef10_mac.c	optional	sfxge pci
 dev/sfxge/common/ef10_mcdi.c	optional	sfxge pci
 dev/sfxge/common/ef10_nic.c	optional	sfxge pci
 dev/sfxge/common/ef10_nvram.c	optional	sfxge pci
 dev/sfxge/common/ef10_phy.c	optional	sfxge pci
 dev/sfxge/common/ef10_rx.c	optional	sfxge pci
 dev/sfxge/common/ef10_tx.c	optional	sfxge pci
 dev/sfxge/common/ef10_vpd.c	optional	sfxge pci
 dev/sfxge/common/efx_bootcfg.c	optional	sfxge pci
 dev/sfxge/common/efx_crc32.c	optional	sfxge pci
 dev/sfxge/common/efx_ev.c	optional	sfxge pci
 dev/sfxge/common/efx_filter.c	optional	sfxge pci
 dev/sfxge/common/efx_hash.c	optional	sfxge pci
 dev/sfxge/common/efx_intr.c	optional	sfxge pci
 dev/sfxge/common/efx_lic.c	optional	sfxge pci
 dev/sfxge/common/efx_mac.c	optional	sfxge pci
 dev/sfxge/common/efx_mcdi.c	optional	sfxge pci
 dev/sfxge/common/efx_mon.c	optional	sfxge pci
 dev/sfxge/common/efx_nic.c	optional	sfxge pci
 dev/sfxge/common/efx_nvram.c	optional	sfxge pci
 dev/sfxge/common/efx_phy.c	optional	sfxge pci
 dev/sfxge/common/efx_port.c	optional	sfxge pci
 dev/sfxge/common/efx_rx.c	optional	sfxge pci
 dev/sfxge/common/efx_sram.c	optional	sfxge pci
 dev/sfxge/common/efx_tunnel.c	optional	sfxge pci
 dev/sfxge/common/efx_tx.c	optional	sfxge pci
 dev/sfxge/common/efx_vpd.c	optional	sfxge pci
 dev/sfxge/common/hunt_nic.c	optional	sfxge pci
 dev/sfxge/common/mcdi_mon.c	optional	sfxge pci
 dev/sfxge/common/medford_nic.c	optional	sfxge pci
 dev/sfxge/common/medford2_nic.c	optional	sfxge pci
 dev/sfxge/common/siena_mac.c	optional	sfxge pci
 dev/sfxge/common/siena_mcdi.c	optional	sfxge pci
 dev/sfxge/common/siena_nic.c	optional	sfxge pci
 dev/sfxge/common/siena_nvram.c	optional	sfxge pci
 dev/sfxge/common/siena_phy.c	optional	sfxge pci
 dev/sfxge/common/siena_sram.c	optional	sfxge pci
 dev/sfxge/common/siena_vpd.c	optional	sfxge pci
 dev/sfxge/sfxge.c		optional	sfxge pci
 dev/sfxge/sfxge_dma.c		optional	sfxge pci
 dev/sfxge/sfxge_ev.c		optional	sfxge pci
 dev/sfxge/sfxge_intr.c		optional	sfxge pci
 dev/sfxge/sfxge_mcdi.c		optional	sfxge pci
 dev/sfxge/sfxge_nvram.c		optional	sfxge pci
 dev/sfxge/sfxge_port.c		optional	sfxge pci
 dev/sfxge/sfxge_rx.c		optional	sfxge pci
 dev/sfxge/sfxge_tx.c		optional	sfxge pci
 dev/smartpqi/smartpqi_cam.c     optional 	smartpqi
 dev/smartpqi/smartpqi_cmd.c     optional 	smartpqi
 dev/smartpqi/smartpqi_discovery.c	optional	smartpqi
 dev/smartpqi/smartpqi_event.c   optional 	smartpqi
 dev/smartpqi/smartpqi_helper.c  optional 	smartpqi
 dev/smartpqi/smartpqi_init.c    optional 	smartpqi
 dev/smartpqi/smartpqi_intr.c    optional 	smartpqi
 dev/smartpqi/smartpqi_ioctl.c   optional 	smartpqi
 dev/smartpqi/smartpqi_main.c    optional 	smartpqi
 dev/smartpqi/smartpqi_mem.c     optional 	smartpqi
 dev/smartpqi/smartpqi_misc.c    optional 	smartpqi
 dev/smartpqi/smartpqi_queue.c   optional 	smartpqi
 dev/smartpqi/smartpqi_request.c optional 	smartpqi
 dev/smartpqi/smartpqi_response.c	optional 	smartpqi
 dev/smartpqi/smartpqi_sis.c     optional 	smartpqi
 dev/smartpqi/smartpqi_tag.c     optional 	smartpqi
 dev/speaker/spkr.c		optional	speaker
 dev/sume/if_sume.c		optional	sume
 dev/superio/superio.c		optional	superio isa
 dev/syscons/apm/apm_saver.c	optional	apm_saver apm
 dev/syscons/scvesactl.c		optional	sc vga vesa
 dev/syscons/scvgarndr.c		optional	sc vga
 dev/tpm/tpm.c			optional	tpm
 dev/tpm/tpm20.c		optional	tpm
 dev/tpm/tpm_crb.c		optional	tpm acpi
 dev/tpm/tpm_tis.c		optional	tpm acpi
 dev/tpm/tpm_acpi.c		optional	tpm acpi
 dev/tpm/tpm_isa.c		optional	tpm isa
 dev/uart/uart_cpu_x86.c		optional	uart
 dev/viawd/viawd.c		optional	viawd
 dev/vmd/vmd.c			optional	vmd
 dev/vmd/vmd_bus.c		optional	vmd_bus
 dev/wbwd/wbwd.c			optional	wbwd
 dev/xen/pci/xen_acpi_pci.c	optional	xenhvm
 dev/xen/pci/xen_pci.c		optional	xenhvm
 isa/syscons_isa.c		optional	sc
 isa/vga_isa.c			optional	vga
 kern/imgact_aout.c		optional compat_aout
 kern/link_elf_obj.c		standard
 #
 # IA32 binary support
 #
 #amd64/ia32/ia32_exception.S	optional	compat_freebsd32
 amd64/ia32/ia32_reg.c		optional	compat_freebsd32
 amd64/ia32/ia32_signal.c	optional	compat_freebsd32
 amd64/ia32/ia32_sigtramp.S	optional	compat_freebsd32
 amd64/ia32/ia32_syscall.c	optional	compat_freebsd32
 amd64/ia32/ia32_misc.c		optional	compat_freebsd32
 compat/ia32/ia32_sysvec.c	optional	compat_freebsd32
 compat/linprocfs/linprocfs.c	optional	linprocfs
 compat/linsysfs/linsysfs.c	optional	linsysfs
 #
 # Linux/i386 binary support
 #
 amd64/linux32/linux32_dummy_machdep.c	optional	compat_linux32
 amd64/linux32/linux32_machdep.c	optional	compat_linux32
 amd64/linux32/linux32_support.s	optional	compat_linux32		\
 	dependency 	"linux32_assym.h"
 amd64/linux32/linux32_sysent.c	optional	compat_linux32
 amd64/linux32/linux32_sysvec.c	optional	compat_linux32
 compat/linux/linux_dummy.c	optional	compat_linux32
 compat/linux/linux_emul.c	optional	compat_linux32
 compat/linux/linux_errno.c	optional	compat_linux32
 compat/linux/linux_file.c	optional	compat_linux32
 compat/linux/linux_fork.c	optional	compat_linux32
 compat/linux/linux_futex.c	optional	compat_linux32
 compat/linux/linux_getcwd.c	optional	compat_linux32
 compat/linux/linux_ioctl.c	optional	compat_linux32
 compat/linux/linux_ipc.c	optional	compat_linux32
 compat/linux/linux_mib.c	optional	compat_linux32
 compat/linux/linux_misc.c	optional	compat_linux32
 compat/linux/linux_mmap.c	optional	compat_linux32
 compat/linux/linux_signal.c	optional	compat_linux32
 compat/linux/linux_socket.c	optional	compat_linux32
 compat/linux/linux_stats.c	optional	compat_linux32
 compat/linux/linux_sysctl.c	optional	compat_linux32
 compat/linux/linux_time.c	optional	compat_linux32
 compat/linux/linux_timer.c	optional	compat_linux32
 compat/linux/linux_uid16.c	optional	compat_linux32
 compat/linux/linux_util.c	optional	compat_linux32
 compat/linux/linux_vdso.c	optional	compat_linux32
 compat/linux/linux_common.c	optional	compat_linux32
 compat/linux/linux_event.c	optional	compat_linux32
 compat/linux/linux.c		optional	compat_linux32
 x86/linux/linux_dummy_x86.c	optional	compat_linux32
 dev/amr/amr_linux.c		optional	compat_linux32 amr
 dev/mfi/mfi_linux.c		optional	compat_linux32 mfi
 compat/ndis/winx64_wrap.S	optional	ndisapi pci
 #
 # x86 real mode BIOS emulator, required by dpms/pci/vesa
 #
 compat/x86bios/x86bios.c	optional x86bios | dpms | pci | vesa
 contrib/x86emu/x86emu.c		optional x86bios | dpms | pci | vesa
-#
-# bvm console
-#
-dev/bvm/bvm_console.c		optional	bvmconsole
-dev/bvm/bvm_dbg.c		optional	bvmdebug
 # Common files where we currently configure the system differently, but perhaps shouldn't
 # config(8) doesn't have a way to force standard options, so we've been inconsistent
 # about marking non-optional things 'standard'.
 x86/acpica/madt.c		optional	acpi
 x86/isa/atpic.c			optional	atpic isa
 x86/isa/elcr.c			optional	atpic isa | mptable
 x86/isa/isa.c			standard
 x86/isa/isa_dma.c		standard
 x86/pci/pci_early_quirks.c	optional	pci
 x86/x86/io_apic.c		standard
 x86/x86/local_apic.c		standard
 x86/x86/mptable.c		optional	mptable
 x86/x86/mptable_pci.c		optional	mptable pci
 x86/x86/msi.c			optional	pci
 x86/xen/pv.c			optional	xenhvm
 x86/xen/pvcpu_enum.c		optional	xenhvm
 x86/xen/xen_pci_bus.c		optional	xenhvm
 
 contrib/openzfs/module/zcommon/zfs_fletcher_avx512.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_fletcher_intel.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_fletcher_sse.c		optional zfs compile-with "${ZFS_C}"
 
 contrib/openzfs/module/zfs/vdev_raidz_math_avx2.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_raidz_math_avx512bw.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_raidz_math_avx512f.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_raidz_math_sse2.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_raidz_math_ssse3.c		optional zfs compile-with "${ZFS_C}"
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index bae1a8cde184..96d2413b532d 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,248 +1,243 @@
 # This file tells config what files go into building a kernel,
 # files marked standard are always included.
 #
 # $FreeBSD$
 #
 
 # common files stuff between i386 and amd64
 include 	"conf/files.x86"
 
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
 # dependency lines other than the first are silently ignored.
 #
 cloudabi32_vdso.o		optional	compat_cloudabi32	\
 	dependency	"$S/contrib/cloudabi/cloudabi_vdso_i686.S" \
 	compile-with	"${CC} -x assembler-with-cpp -shared -nostdinc -nostdlib -Wl,-T$S/compat/cloudabi/cloudabi_vdso.lds $S/contrib/cloudabi/cloudabi_vdso_i686.S -o ${.TARGET}" \
 	no-obj no-implicit-rule						\
 	clean		"cloudabi32_vdso.o"
 #
 cloudabi32_vdso_blob.o		optional	compat_cloudabi32	\
 	dependency 	"cloudabi32_vdso.o"				\
 	compile-with	"${OBJCOPY} --input-target binary --output-target elf32-i386-freebsd --binary-architecture i386 cloudabi32_vdso.o ${.TARGET}" \
 	no-implicit-rule						\
 	clean		"cloudabi32_vdso_blob.o"
 #
 linux_genassym.o		optional	compat_linux		\
 	dependency 	"$S/i386/linux/linux_genassym.c offset.inc"		\
 	compile-with	"${CC} ${CFLAGS:N-flto:N-fno-common} -fcommon -c ${.IMPSRC}" \
 	no-obj no-implicit-rule						\
 	clean		"linux_genassym.o"
 #
 linux_assym.h			optional	compat_linux		\
 	dependency 	"$S/kern/genassym.sh linux_genassym.o"		\
 	compile-with	"sh $S/kern/genassym.sh linux_genassym.o > ${.TARGET}" \
 	no-obj no-implicit-rule before-depend				\
 	clean		"linux_assym.h"
 #
 linux_locore.o			optional	compat_linux		\
 	dependency 	"linux_assym.h $S/i386/linux/linux_locore.asm"	\
 	compile-with	"${CC} -x assembler-with-cpp -DLOCORE -shared -s -pipe -I. -I$S ${WERROR} -Wall -fPIC -fno-common -nostdinc -nostdlib -Wl,-T$S/i386/linux/linux_vdso.lds.s -Wl,-soname=linux_vdso.so,--eh-frame-hdr,-warn-common ${.IMPSRC} -o ${.TARGET}" \
 	no-obj no-implicit-rule						\
 	clean		"linux_locore.o"
 #
 linux_vdso.so			optional	compat_linux		\
 	dependency 	"linux_locore.o"				\
 	compile-with	"${OBJCOPY} --input-target binary --output-target elf32-i386-freebsd --binary-architecture i386 linux_locore.o ${.TARGET}" \
 	no-implicit-rule						\
 	clean		"linux_vdso.so"
 #
 cddl/contrib/opensolaris/common/atomic/i386/opensolaris_atomic.S	optional zfs | dtrace compile-with "${ZFS_S}"
 cddl/dev/dtrace/i386/dtrace_asm.S			optional dtrace compile-with "${DTRACE_S}"
 cddl/dev/dtrace/i386/dtrace_subr.c			optional dtrace compile-with "${DTRACE_C}"
 compat/linprocfs/linprocfs.c	optional linprocfs
 compat/linsysfs/linsysfs.c	optional linsysfs
 compat/linux/linux_dummy.c	optional compat_linux
 compat/linux/linux_event.c	optional compat_linux
 compat/linux/linux_emul.c	optional compat_linux
 compat/linux/linux_errno.c	optional compat_linux
 compat/linux/linux_file.c	optional compat_linux
 compat/linux/linux_fork.c	optional compat_linux
 compat/linux/linux_futex.c	optional compat_linux
 compat/linux/linux_getcwd.c	optional compat_linux
 compat/linux/linux_ioctl.c	optional compat_linux
 compat/linux/linux_ipc.c	optional compat_linux
 compat/linux/linux_mib.c	optional compat_linux
 compat/linux/linux_misc.c	optional compat_linux
 compat/linux/linux_mmap.c	optional compat_linux
 compat/linux/linux_signal.c	optional compat_linux
 compat/linux/linux_socket.c	optional compat_linux
 compat/linux/linux_stats.c	optional compat_linux
 compat/linux/linux_sysctl.c	optional compat_linux
 compat/linux/linux_time.c	optional compat_linux
 compat/linux/linux_timer.c	optional compat_linux
 compat/linux/linux_uid16.c	optional compat_linux
 compat/linux/linux_util.c	optional compat_linux
 compat/linux/linux_vdso.c	optional compat_linux
 compat/linux/linux.c		optional compat_linux
 compat/ndis/winx32_wrap.S	optional ndisapi pci
 crypto/aesni/aeskeys_i386.S	optional aesni
 crypto/des/arch/i386/des_enc.S	optional netsmb
 crypto/openssl/i386/sha1-586.S	optional ossl
 crypto/openssl/i386/sha256-586.S	optional ossl
 crypto/openssl/i386/sha512-586.S	optional ossl
 dev/agp/agp_ali.c		optional agp
 dev/agp/agp_amd.c		optional agp
 dev/agp/agp_amd64.c		optional agp
 dev/agp/agp_ati.c		optional agp
 dev/agp/agp_i810.c		optional agp
 dev/agp/agp_intel.c		optional agp
 dev/agp/agp_nvidia.c		optional agp
 dev/agp/agp_sis.c		optional agp
 dev/agp/agp_via.c		optional agp
 dev/ce/ceddk.c			optional ce
 dev/ce/if_ce.c			optional ce
 dev/ce/tau32-ddk.c		optional ce \
 	compile-with "${NORMAL_C} ${NO_WCONSTANT_CONVERSION} ${NO_WMISLEADING_INDENTATION}"
 dev/cp/cpddk.c			optional cp \
 	compile-with "${NORMAL_C} ${NO_WMISLEADING_INDENTATION}"
 dev/cp/if_cp.c			optional cp
 dev/glxiic/glxiic.c		optional glxiic
 dev/glxsb/glxsb.c		optional glxsb
 dev/glxsb/glxsb_hash.c		optional glxsb
 dev/hyperv/vmbus/i386/hyperv_machdep.c			optional	hyperv
 dev/hyperv/vmbus/i386/vmbus_vector.S			optional	hyperv
 dev/le/if_le_isa.c		optional le isa
 dev/nctgpio/nctgpio.c		optional nctgpio
 dev/nfe/if_nfe.c		optional nfe pci
 dev/ntb/if_ntb/if_ntb.c		optional if_ntb
 dev/ntb/ntb_transport.c		optional ntb_transport | if_ntb
 dev/ntb/ntb.c			optional ntb | ntb_transport | if_ntb | ntb_hw_amd | ntb_hw_intel | ntb_hw_plx | ntb_hw
 dev/ntb/ntb_if.m		optional ntb | ntb_transport | if_ntb | ntb_hw_amd | ntb_hw_intel | ntb_hw_plx | ntb_hw
 dev/ntb/ntb_hw/ntb_hw_amd.c	optional ntb_hw_amd | ntb_hw
 dev/ntb/ntb_hw/ntb_hw_intel.c	optional ntb_hw_intel | ntb_hw
 dev/ntb/ntb_hw/ntb_hw_plx.c	optional ntb_hw_plx | ntb_hw
 dev/ntb/test/ntb_tool.c		optional ntb_tool
 dev/nvram/nvram.c		optional	nvram isa
 dev/ofw/ofwpci.c		optional fdt pci
 dev/pcf/pcf_isa.c		optional pcf
 dev/random/ivy.c		optional rdrand_rng !random_loadable
 dev/random/nehemiah.c		optional padlock_rng !random_loadable
 dev/sbni/if_sbni.c		optional sbni
 dev/sbni/if_sbni_isa.c		optional sbni isa
 dev/sbni/if_sbni_pci.c		optional sbni pci
 dev/speaker/spkr.c		optional speaker
 dev/superio/superio.c		optional superio isa
 dev/syscons/scvesactl.c		optional sc vga vesa
 dev/syscons/scvgarndr.c		optional sc vga
 dev/tpm/tpm.c			optional tpm
 dev/tpm/tpm_acpi.c		optional tpm acpi
 dev/tpm/tpm_isa.c		optional tpm isa
 dev/uart/uart_cpu_x86.c		optional uart
 dev/viawd/viawd.c		optional viawd
 dev/acpi_support/acpi_wmi_if.m	standard
 dev/wbwd/wbwd.c			optional wbwd
 i386/acpica/acpi_machdep.c	optional acpi
 acpi_wakecode.o			optional acpi				\
 	dependency	"$S/i386/acpica/acpi_wakecode.S assym.inc"	\
 	compile-with	"${NORMAL_S}"					\
 	no-obj no-implicit-rule before-depend				\
 	clean		"acpi_wakecode.o"
 acpi_wakecode.bin		optional acpi				\
 	dependency	"acpi_wakecode.o"				\
 	compile-with	"${OBJCOPY} -S -O binary acpi_wakecode.o ${.TARGET}" \
 	no-obj no-implicit-rule	before-depend				\
 	clean		"acpi_wakecode.bin"
 acpi_wakecode.h			optional acpi				\
 	dependency	"acpi_wakecode.bin"				\
 	compile-with	"file2c -sx 'static char wakecode[] = {' '};' < acpi_wakecode.bin > ${.TARGET}" \
 	no-obj no-implicit-rule	before-depend				\
 	clean		"acpi_wakecode.h"
 acpi_wakedata.h			optional acpi				\
 	dependency	"acpi_wakecode.o"				\
 	compile-with	'${NM} -n --defined-only acpi_wakecode.o | while read offset dummy what; do echo "#define	$${what}	0x$${offset}"; done > ${.TARGET}' \
 	no-obj no-implicit-rule	before-depend				\
 	clean		"acpi_wakedata.h"
 #
 i386/bios/smapi.c		optional smapi
 i386/bios/smapi_bios.S		optional smapi
 i386/cloudabi32/cloudabi32_sysvec.c	optional compat_cloudabi32
 #i386/i386/apic_vector.s		optional apic
 i386/i386/bios.c		standard
 i386/i386/bioscall.s		standard
 i386/i386/bpf_jit_machdep.c	optional bpf_jitter
 i386/i386/copyout.c		standard
 i386/i386/db_disasm.c		optional ddb
 i386/i386/db_interface.c	optional ddb
 i386/i386/db_trace.c		optional ddb
 i386/i386/elan-mmcr.c		optional cpu_elan | cpu_soekris
 i386/i386/elf_machdep.c		standard
 i386/i386/exception.s		standard
 i386/i386/gdb_machdep.c		optional gdb
 i386/i386/geode.c		optional cpu_geode
 i386/i386/in_cksum.c		optional inet | inet6
 i386/i386/initcpu.c		standard
 i386/i386/io.c			optional io
 i386/i386/k6_mem.c		optional mem
 i386/i386/locore.s		standard	no-obj
 i386/i386/longrun.c		optional cpu_enable_longrun
 i386/i386/machdep.c		standard
 i386/i386/mem.c			optional mem
 i386/i386/minidump_machdep.c	standard
 i386/i386/minidump_machdep_pae.c	standard
 i386/i386/minidump_machdep_nopae.c	standard
 i386/i386/mp_clock.c		optional smp
 i386/i386/mp_machdep.c		optional smp
 i386/i386/mpboot.s		optional smp
 i386/i386/npx.c			standard
 i386/i386/perfmon.c		optional perfmon
 i386/i386/pmap_base.c		standard
 i386/i386/pmap_nopae.c		standard
 i386/i386/pmap_pae.c		standard
 i386/i386/prof_machdep.c	optional profiling-routine
 i386/i386/ptrace_machdep.c	standard
 i386/i386/sigtramp.s		standard
 i386/i386/support.s		standard
 i386/i386/swtch.s		standard
 i386/i386/sys_machdep.c		standard
 i386/i386/trap.c		standard
 i386/i386/uio_machdep.c		standard
 i386/i386/vm86.c		standard
 i386/i386/vm_machdep.c		standard
 i386/linux/imgact_linux.c	optional compat_linux
 i386/linux/linux_copyout.c	optional compat_linux
 i386/linux/linux_dummy_machdep.c	optional compat_linux
 i386/linux/linux_machdep.c	optional compat_linux
 i386/linux/linux_ptrace.c	optional compat_linux
 i386/linux/linux_sysent.c	optional compat_linux
 i386/linux/linux_sysvec.c	optional compat_linux
 i386/pci/pci_cfgreg.c		optional pci
 i386/pci/pci_pir.c		optional pci
 isa/syscons_isa.c		optional sc
 isa/vga_isa.c			optional vga
 kern/imgact_aout.c		optional compat_aout
 kern/subr_sfbuf.c		standard
 libkern/divdi3.c		standard
 libkern/ffsll.c			standard
 libkern/flsll.c			standard
 libkern/memcmp.c		standard
 libkern/memset.c		standard
 libkern/moddi3.c		standard
 libkern/qdivrem.c		standard
 libkern/ucmpdi2.c		standard
 libkern/udivdi3.c		standard
 libkern/umoddi3.c		standard
 #
 # x86 real mode BIOS support, required by dpms/pci/vesa
 #
 compat/x86bios/x86bios.c	optional x86bios | dpms | pci | vesa
-#
-# bvm console
-#
-dev/bvm/bvm_console.c		optional	bvmconsole
-dev/bvm/bvm_dbg.c		optional	bvmdebug
 # Common files where we currently configure the system differently, but perhaps shouldn't
 # config(8) doesn't have a way to force standard options, so we've been inconsistent
 # about marking non-optional things 'standard'.
 x86/acpica/madt.c		optional acpi apic
 x86/cpufreq/smist.c		optional cpufreq
 x86/isa/atpic.c			optional atpic
 x86/isa/elcr.c			optional atpic | apic
 x86/isa/isa.c			optional isa
 x86/isa/isa_dma.c		optional isa
 x86/linux/linux_dummy_x86.c	optional compat_linux
 x86/x86/io_apic.c		optional apic
 x86/x86/local_apic.c		optional apic
 x86/x86/mptable.c		optional apic
 x86/x86/mptable_pci.c		optional apic pci
 x86/x86/msi.c			optional apic pci
diff --git a/sys/dev/bvm/bvm_console.c b/sys/dev/bvm/bvm_console.c
deleted file mode 100644
index c73f462ed84f..000000000000
--- a/sys/dev/bvm/bvm_console.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2011 NetApp, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/types.h>
-#include <sys/cons.h>
-#include <sys/tty.h>
-#include <sys/reboot.h>
-#include <sys/bus.h>
-
-#include <sys/kdb.h>
-#include <ddb/ddb.h>
-
-#ifndef	BVMCONS_POLL_HZ
-#define	BVMCONS_POLL_HZ	4
-#endif
-#define BVMBURSTLEN	16	/* max number of bytes to write in one chunk */
-
-static tsw_open_t bvm_tty_open;
-static tsw_close_t bvm_tty_close;
-static tsw_outwakeup_t bvm_tty_outwakeup;
-
-static struct ttydevsw bvm_ttydevsw = {
-	.tsw_flags	= TF_NOPREFIX,
-	.tsw_open	= bvm_tty_open,
-	.tsw_close	= bvm_tty_close,
-	.tsw_outwakeup	= bvm_tty_outwakeup,
-};
-
-static int			polltime;
-static struct callout		bvm_timer;
-
-#if defined(KDB)
-static int			alt_break_state;
-#endif
-
-#define	BVM_CONS_PORT	0x220
-static int bvm_cons_port = BVM_CONS_PORT;
-
-#define BVM_CONS_SIG	('b' << 8 | 'v')
-
-static void	bvm_timeout(void *);
-
-static cn_probe_t	bvm_cnprobe;
-static cn_init_t	bvm_cninit;
-static cn_term_t	bvm_cnterm;
-static cn_getc_t	bvm_cngetc;
-static cn_putc_t	bvm_cnputc;
-static cn_grab_t 	bvm_cngrab;
-static cn_ungrab_t 	bvm_cnungrab;
-
-CONSOLE_DRIVER(bvm);
-
-static int
-bvm_rcons(u_char *ch)
-{
-	int c;
-
-	c = inl(bvm_cons_port);
-	if (c != -1) {
-		*ch = (u_char)c;
-		return (0);
-	} else
-		return (-1);
-}
-
-static void
-bvm_wcons(u_char ch)
-{
-
-	outl(bvm_cons_port, ch);
-}
-
-static void
-cn_drvinit(void *unused)
-{
-	struct tty *tp;
-    
-	gone_in(13, "bvmconsole");
-
-	if (bvm_consdev.cn_pri != CN_DEAD) {
-		tp = tty_alloc(&bvm_ttydevsw, NULL);
-		callout_init_mtx(&bvm_timer, tty_getlock(tp), 0);
-		tty_makedev(tp, NULL, "bvmcons");
-	}
-}
-
-static int
-bvm_tty_open(struct tty *tp)
-{
-	polltime = hz / BVMCONS_POLL_HZ;
-	if (polltime < 1)
-		polltime = 1;
-	callout_reset(&bvm_timer, polltime, bvm_timeout, tp);
-
-	return (0);
-}
-
-static void
-bvm_tty_close(struct tty *tp)
-{
-
-	tty_assert_locked(tp);
-	callout_stop(&bvm_timer);
-}
-
-static void
-bvm_tty_outwakeup(struct tty *tp)
-{
-	int len, written;
-	u_char buf[BVMBURSTLEN];
-
-	for (;;) {
-		len = ttydisc_getc(tp, buf, sizeof(buf));
-		if (len == 0)
-			break;
-
-		written = 0;
-		while (written < len)
-			bvm_wcons(buf[written++]);
-	}
-}
-
-static void
-bvm_timeout(void *v)
-{
-	struct	tty *tp;
-	int 	c;
-
-	tp = (struct tty *)v;
-
-	tty_assert_locked(tp);
-	while ((c = bvm_cngetc(NULL)) != -1)
-		ttydisc_rint(tp, c, 0);
-	ttydisc_rint_done(tp);
-
-	callout_reset(&bvm_timer, polltime, bvm_timeout, tp);
-}
-
-static void
-bvm_cnprobe(struct consdev *cp)
-{
-	int disabled, port;
-
-	disabled = 0;
-	cp->cn_pri = CN_DEAD;
-	strcpy(cp->cn_name, "bvmcons");
-
-	resource_int_value("bvmconsole", 0, "disabled", &disabled);
-	if (!disabled) {
-		if (resource_int_value("bvmconsole", 0, "port", &port) == 0)
-			bvm_cons_port = port;
-
-		if (inw(bvm_cons_port) == BVM_CONS_SIG)
-			cp->cn_pri = CN_REMOTE;
-	}
-}
-
-static void
-bvm_cninit(struct consdev *cp)
-{
-	int i;
-	const char *bootmsg = "Using bvm console.\n";
-
-	if (boothowto & RB_VERBOSE) {
-		for (i = 0; i < strlen(bootmsg); i++)
-			bvm_cnputc(cp, bootmsg[i]);
-	}
-}
-
-static void
-bvm_cnterm(struct consdev *cp)
-{
-
-}
-
-static int
-bvm_cngetc(struct consdev *cp)
-{
-	unsigned char ch;
-
-	if (bvm_rcons(&ch) == 0) {
-#if defined(KDB)
-		kdb_alt_break(ch, &alt_break_state);
-#endif
-		return (ch);
-	}
-
-	return (-1);
-}
-
-static void
-bvm_cnputc(struct consdev *cp, int c)
-{
-
-	bvm_wcons(c);
-}
-
-static void
-bvm_cngrab(struct consdev *cp)
-{
-}
-
-static void
-bvm_cnungrab(struct consdev *cp)
-{
-}
-
-SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL);
diff --git a/sys/dev/bvm/bvm_dbg.c b/sys/dev/bvm/bvm_dbg.c
deleted file mode 100644
index 9aff8c10c8fb..000000000000
--- a/sys/dev/bvm/bvm_dbg.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2011 NetApp, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/bus.h>
-
-#include <gdb/gdb.h>
-
-#include <machine/cpufunc.h>
-
-static gdb_probe_f bvm_dbg_probe;
-static gdb_init_f bvm_dbg_init;
-static gdb_term_f bvm_dbg_term;
-static gdb_getc_f bvm_dbg_getc;
-static gdb_putc_f bvm_dbg_putc;
-
-GDB_DBGPORT(bvm, bvm_dbg_probe, bvm_dbg_init, bvm_dbg_term,
-    bvm_dbg_getc, bvm_dbg_putc);
-
-#define	BVM_DBG_PORT	0x224
-static int bvm_dbg_port = BVM_DBG_PORT;
-
-#define BVM_DBG_SIG	('B' << 8 | 'V')
-
-static int
-bvm_dbg_probe(void)
-{
-	int disabled, port;
-
-	disabled = 0;
-	resource_int_value("bvmdbg", 0, "disabled", &disabled);
-
-	gone_in(13, "bvmdebug");
-
-	if (!disabled) {
-		if (resource_int_value("bvmdbg", 0, "port", &port) == 0)
-			bvm_dbg_port = port;
-
-		if (inw(bvm_dbg_port) == BVM_DBG_SIG) {
-			/*
-			 * Return a higher priority than 0 to override other
-			 * gdb dbgport providers that may be present (e.g. uart)
-			 */
-			return (1);
-		}
-	}
-
-	return (-1);
-}
-
-static void
-bvm_dbg_init(void)
-{
-}
-
-static void
-bvm_dbg_term(void)
-{
-}
-
-static void
-bvm_dbg_putc(int c)
-{
-
-	outl(bvm_dbg_port, c);
-}
-
-static int
-bvm_dbg_getc(void)
-{
-
-	return (inl(bvm_dbg_port));
-}
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
index b884930d5b03..0233690a5082 100644
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -1,127 +1,125 @@
 #
 # $FreeBSD$
 #
 
 .include <src.opts.mk>
 CFLAGS+=-I${.CURDIR}/../../contrib/lib9p
 CFLAGS+=-I${SRCTOP}/sys
 .PATH:  ${SRCTOP}/sys/cam/ctl
 
 PROG=	bhyve
 PACKAGE=	bhyve
 
 MAN=	bhyve.8
 
 BHYVE_SYSDIR?=${SRCTOP}
 
 SRCS=	\
 	atkbdc.c		\
 	acpi.c			\
 	audio.c			\
 	bhyvegc.c		\
 	bhyverun.c		\
 	block_if.c		\
 	bootrom.c		\
 	console.c		\
-	consport.c		\
 	ctl_util.c		\
 	ctl_scsi_all.c		\
-	dbgport.c		\
 	fwctl.c			\
 	gdb.c			\
 	hda_codec.c		\
 	inout.c			\
 	ioapic.c		\
 	kernemu_dev.c		\
 	mem.c			\
 	mevent.c		\
 	mptbl.c			\
 	net_backends.c		\
 	net_utils.c		\
 	pci_ahci.c		\
 	pci_e82545.c		\
 	pci_emul.c		\
 	pci_hda.c		\
 	pci_fbuf.c		\
 	pci_hostbridge.c	\
 	pci_irq.c		\
 	pci_lpc.c		\
 	pci_nvme.c		\
 	pci_passthru.c		\
 	pci_virtio_9p.c		\
 	pci_virtio_block.c	\
 	pci_virtio_console.c	\
 	pci_virtio_net.c	\
 	pci_virtio_rnd.c	\
 	pci_virtio_scsi.c	\
 	pci_uart.c		\
 	pci_xhci.c		\
 	pctestdev.c		\
 	pm.c			\
 	post.c			\
 	ps2kbd.c		\
 	ps2mouse.c		\
 	rfb.c			\
 	rtc.c			\
 	smbiostbl.c		\
 	sockstream.c		\
 	task_switch.c		\
 	uart_emul.c		\
 	usb_emul.c		\
 	usb_mouse.c		\
 	virtio.c		\
 	vga.c			\
 	vmgenc.c		\
 	xmsr.c			\
 	spinup_ap.c		\
 	iov.c
 
 .if ${MK_BHYVE_SNAPSHOT} != "no"
 SRCS+=	snapshot.c
 .endif
 
 CFLAGS.kernemu_dev.c+=	-I${SRCTOP}/sys/amd64
 
 .PATH:  ${BHYVE_SYSDIR}/sys/amd64/vmm
 SRCS+=	vmm_instruction_emul.c
 
 LIBADD=	vmmapi md pthread z util sbuf cam 9p casper cap_pwd cap_grp
 .if ${MK_BHYVE_SNAPSHOT} != "no"
 LIBADD+= ucl xo
 .endif
 
 .if ${MK_INET_SUPPORT} != "no"
 CFLAGS+=-DINET
 .endif
 .if ${MK_INET6_SUPPORT} != "no"
 CFLAGS+=-DINET6
 .endif
 .if ${MK_NETGRAPH_SUPPORT} != "no"
 CFLAGS+=-DNETGRAPH
 LIBADD+=    netgraph
 .endif
 .if ${MK_OPENSSL} == "no"
 CFLAGS+=-DNO_OPENSSL
 .else
 LIBADD+=	crypto
 .endif
 
 CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/e1000
 CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/mii
 CFLAGS+= -I${BHYVE_SYSDIR}/sys/dev/usb/controller
 .if ${MK_BHYVE_SNAPSHOT} != "no"
 CFLAGS+= -I${SRCTOP}/contrib/libucl/include
 
 # Temporary disable capsicum, until we integrate checkpoint code with it.
 CFLAGS+= -DWITHOUT_CAPSICUM
 
 CFLAGS+= -DBHYVE_SNAPSHOT
 .endif
 
 .ifdef GDB_LOG
 CFLAGS+=-DGDB_LOG
 .endif
 
 WARNS?=	2
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
index f93e73e2e1be..a3ea7be0b579 100644
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -1,748 +1,731 @@
 .\" Copyright (c) 2013 Peter Grehan
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
 .\" 1. Redistributions of source code must retain the above copyright
 .\"    notice, this list of conditions and the following disclaimer.
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
 .\"
 .\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 8, 2020
+.Dd December 23, 2020
 .Dt BHYVE 8
 .Os
 .Sh NAME
 .Nm bhyve
 .Nd "run a guest operating system inside a virtual machine"
 .Sh SYNOPSIS
 .Nm
-.Op Fl AabCDeHhPSuWwxY
+.Op Fl AaCDeHhPSuWwxY
 .Oo
 .Sm off
 .Fl c\~
 .Oo
 .Op Cm cpus=
 .Ar numcpus
 .Oc
 .Op Cm ,sockets= Ar n
 .Op Cm ,cores= Ar n
 .Op Cm ,threads= Ar n
 .Oc
 .Sm on
 .Op Fl G Ar port
-.Op Fl g Ar gdbport
 .Oo Fl l
 .Sm off
 .Cm help | Ar lpcdev Op Cm \&, Ar conf
 .Sm on
 .Oc
 .Oo Fl m
 .Sm off
 .Ar memsize
 .Oo
 .Cm K No | Cm k No | Cm M No | Cm m No | Cm G No | Cm g No | Cm T No | Cm t
 .Oc
 .Sm on
 .Oc
 .Op Fl p Ar vcpu Ns Cm \&: Ns Ar hostcpu
 .Op Fl r Ar file
 .Oo Fl s
 .Sm off
 .Cm help | Ar slot Cm \&, Ar emulation Op Cm \&, Ar conf
 .Sm on
 .Oc
 .Op Fl U Ar uuid
 .Ar vmname
 .Sh DESCRIPTION
 .Nm
 is a hypervisor that runs guest operating systems inside a
 virtual machine.
 .Pp
 Parameters such as the number of virtual CPUs, amount of guest memory, and
 I/O connectivity can be specified with command-line parameters.
 .Pp
 If not using a boot ROM, the guest operating system must be loaded with
 .Xr bhyveload 8
 or a similar boot loader before running
 .Nm ,
 otherwise, it is enough to run
 .Nm
 with a boot ROM of choice.
 .Pp
 .Nm
 runs until the guest operating system reboots or an unhandled hypervisor
 exit is detected.
 .Sh OPTIONS
 .Bl -tag -width 10n
 .It Fl a
 The guest's local APIC is configured in xAPIC mode.
 The xAPIC mode is the default setting so this option is redundant.
 It will be deprecated in a future version.
 .It Fl A
 Generate ACPI tables.
 Required for
 .Fx Ns /amd64
 guests.
-.It Fl b
-Enable a low-level console device supported by
-.Fx
-kernels compiled with
-.Cd "device bvmconsole" .
-This option is deprecated and will be removed in
-.Fx 13.0 .
 .It Fl c Op Ar setting ...
 Number of guest virtual CPUs
 and/or the CPU topology.
 The default value for each of
 .Ar numcpus ,
 .Ar sockets ,
 .Ar cores ,
 and
 .Ar threads
 is 1.
 The current maximum number of guest virtual CPUs is 16.
 If
 .Ar numcpus
 is not specified then it will be calculated from the other arguments.
 The topology must be consistent in that the
 .Ar numcpus
 must equal the product of
 .Ar sockets ,
 .Ar cores ,
 and
 .Ar threads .
 If a
 .Ar setting
 is specified more than once the last one has precedence.
 .It Fl C
 Include guest memory in core file.
 .It Fl D
 Destroy the VM on guest initiated power-off.
 .It Fl e
 Force
 .Nm
 to exit when a guest issues an access to an I/O port that is not emulated.
 This is intended for debug purposes.
-.It Fl g Ar gdbport
-For
-.Fx
-kernels compiled with
-.Cd "device bvmdebug" ,
-allow a remote kernel kgdb to be relayed to the guest kernel gdb stub
-via a local IPv4 address and this port.
-This option is deprecated and will be removed in
-.Fx 13.0 .
 .It Fl G Ar port
 Start a debug server that uses the GDB protocol to export guest state to a
 debugger.
 An IPv4 TCP socket will be bound to the supplied
 .Ar port
 to listen for debugger connections.
 Only a single debugger may be attached to the debug server at a time.
 If
 .Ar port
 begins with
 .Sq w ,
 .Nm
 will pause execution at the first instruction waiting for a debugger to attach.
 .It Fl h
 Print help message and exit.
 .It Fl H
 Yield the virtual CPU thread when a HLT instruction is detected.
 If this option is not specified, virtual CPUs will use 100% of a host CPU.
 .It Fl l Op Ar help|lpcdev Ns Op , Ns Ar conf
 Allow devices behind the LPC PCI-ISA bridge to be configured.
 The only supported devices are the TTY-class devices
 .Ar com1
 and
 .Ar com2 ,
 the boot ROM device
 .Ar bootrom ,
 and the debug/test device
 .Ar pc-testdev .
 .Pp
 .Ar help
 print a list of supported LPC devices.
 .It Fl m Ar memsize Ns Op Ar K|k|M|m|G|g|T|t
 Guest physical memory size in bytes.
 This must be the same size that was given to
 .Xr bhyveload 8 .
 .Pp
 The size argument may be suffixed with one of K, M, G or T (either upper
 or lower case) to indicate a multiple of kilobytes, megabytes, gigabytes,
 or terabytes.
 If no suffix is given, the value is assumed to be in megabytes.
 .Pp
 .Ar memsize
 defaults to 256M.
 .It Fl p Ar vcpu:hostcpu
 Pin guest's virtual CPU
 .Em vcpu
 to
 .Em hostcpu .
 .It Fl P
 Force the guest virtual CPU to exit when a PAUSE instruction is detected.
 .It Fl r Ar file
 Resume a guest from a snapshot.
 The guest memory contents are restored from
 .Ar file ,
 and the guest device and vCPU state are restored from the file
 .Dq Ar file Ns .kern .
 .Pp
 Note that the current snapshot file format requires that the configuration of
 devices in the new VM match the VM from which the snapshot was taken by specifying the
 same
 .Op Fl s
 and
 .Op Fl l
 options.
 The count of vCPUs and memory configuration are read from the snapshot.
 .It Fl s Op Ar help|slot,emulation Ns Op , Ns Ar conf
 Configure a virtual PCI slot and function.
 .Pp
 .Nm
 provides PCI bus emulation and virtual devices that can be attached to
 slots on the bus.
 There are 32 available slots, with the option of providing up to 8 functions
 per slot.
 .Bl -tag -width 10n
 .It Ar help
 print a list of supported PCI devices.
 .It Ar slot
 .Ar pcislot[:function]
 .Ar bus:pcislot:function
 .Pp
 The
 .Ar pcislot
 value is 0 to 31.
 The optional
 .Ar function
 value is 0 to 7.
 The optional
 .Ar bus
 value is 0 to 255.
 If not specified, the
 .Ar function
 value defaults to 0.
 If not specified, the
 .Ar bus
 value defaults to 0.
 .It Ar emulation
 .Bl -tag -width 10n
 .It Li hostbridge | Li amd_hostbridge
 .Pp
 Provide a simple host bridge.
 This is usually configured at slot 0, and is required by most guest
 operating systems.
 The
 .Li amd_hostbridge
 emulation is identical but uses a PCI vendor ID of
 .Li AMD .
 .It Li passthru
 PCI pass-through device.
 .It Li virtio-net
 Virtio network interface.
 .It Li virtio-blk
 Virtio block storage interface.
 .It Li virtio-scsi
 Virtio SCSI interface.
 .It Li virtio-9p
 Virtio 9p (VirtFS) interface.
 .It Li virtio-rnd
 Virtio RNG interface.
 .It Li virtio-console
 Virtio console interface, which exposes multiple ports
 to the guest in the form of simple char devices for simple IO
 between the guest and host userspaces.
 .It Li ahci
 AHCI controller attached to arbitrary devices.
 .It Li ahci-cd
 AHCI controller attached to an ATAPI CD/DVD.
 .It Li ahci-hd
 AHCI controller attached to a SATA hard-drive.
 .It Li e1000
 Intel e82545 network interface.
 .It Li uart
 PCI 16550 serial device.
 .It Li lpc
 LPC PCI-ISA bridge with COM1 and COM2 16550 serial ports, a boot ROM, and,
 optionally, the debug/test device.
 The LPC bridge emulation can only be configured on bus 0.
 .It Li fbuf
 Raw framebuffer device attached to VNC server.
 .It Li xhci
 eXtensible Host Controller Interface (xHCI) USB controller.
 .It Li nvme
 NVM Express (NVMe) controller.
 .It Li hda
 High Definition Audio Controller.
 .El
 .It Op Ar conf
 This optional parameter describes the backend for device emulations.
 If
 .Ar conf
 is not specified, the device emulation has no backend and can be
 considered unconnected.
 .Pp
 Network backends:
 .Bl -tag -width 10n
 .It Ar tapN Ns Oo , Ns Ar mac=xx:xx:xx:xx:xx:xx Oc Ns Oo , Ns Ar mtu=N Oc
 .It Ar vmnetN Ns Oo , Ns Ar mac=xx:xx:xx:xx:xx:xx Oc Ns Oo , Ns Ar mtu=N Oc
 .It Ar netgraph,path=ADDRESS,peerhook=HOOK Ns Oo , Ns Ar socket=NAME Oc Ns Oo , Ns Ar hook=HOOK Oc Ns Oo , Ns Ar mac=xx:xx:xx:xx:xx:xx Oc Ns Oo , Ns Ar mtu=N Oc
 .Pp
 If
 .Ar mac
 is not specified, the MAC address is derived from a fixed OUI and the
 remaining bytes from an MD5 hash of the slot and function numbers and
 the device name.
 .Pp
 The MAC address is an ASCII string in
 .Xr ethers 5
 format.
 .Pp
 With virtio-net devices, the
 .Ar mtu
 parameter can be specified to inform the guest about the largest MTU
 that should be allowed, expressed in bytes.
 .Pp
 With netgraph backend, the
 .Ar path
 and
 .Ar peerhook
 parameters must be specified to set the destination node and corresponding hook.
 The optional parameters
 .Ar socket
 and
 .Ar hook
 may be used to set the
 .Xr ng_socket 4
 node name and source hook.
 The
 .Ar ADDRESS ,
 .Ar HOOK
 and
 .Ar NAME
 must comply with
 .Xr netgraph 4
 addressing rules.
 .El
 .Pp
 Block storage devices:
 .Bl -tag -width 10n
 .It Pa /filename Ns Oo , Ns Ar block-device-options Oc
 .It Pa /dev/xxx Ns Oo , Ns Ar block-device-options Oc
 .El
 .Pp
 The
 .Ar block-device-options
 are:
 .Bl -tag -width 8n
 .It Li nocache
 Open the file with
 .Dv O_DIRECT .
 .It Li direct
 Open the file using
 .Dv O_SYNC .
 .It Li ro
 Force the file to be opened read-only.
 .It Li sectorsize= Ns Ar logical Ns Oo / Ns Ar physical Oc
 Specify the logical and physical sector sizes of the emulated disk.
 The physical sector size is optional and is equal to the logical sector size
 if not explicitly specified.
 .El
 .Pp
 SCSI devices:
 .Bl -tag -width 10n
 .It Pa /dev/cam/ctl Ns Oo Ar pp . Ns Ar vp Oc Ns Oo , Ns Ar scsi-device-options Oc
 .El
 .Pp
 The
 .Ar scsi-device-options
 are:
 .Bl -tag -width 10n
 .It Li iid= Ns Ar IID
 Initiator ID to use when sending requests to specified CTL port.
 The default value is 0.
 .El
 .Pp
 9P devices:
 .Bl -tag -width 10n
 .It Pa sharename=/path/to/share[,9p-device-options]
 .El
 .Pp
 The
 .Ar 9p-device-options
 are:
 .Bl -tag -width 10n
 .It Li ro
 Expose the share in read-only mode.
 .El
 .Pp
 TTY devices:
 .Bl -tag -width 10n
 .It Li stdio
 Connect the serial port to the standard input and output of
 the
 .Nm
 process.
 .It Pa /dev/xxx
 Use the host TTY device for serial port I/O.
 .El
 .Pp
 Boot ROM device:
 .Bl -tag -width 10n
 .It Pa romfile
 Map
 .Ar romfile
 in the guest address space reserved for boot firmware.
 .El
 .Pp
 Pass-through devices:
 .Bl -tag -width 10n
 .It Ns Ar slot Ns / Ns Ar bus Ns / Ns Ar function
 Connect to a PCI device on the host at the selector described by
 .Ar slot ,
 .Ar bus ,
 and
 .Ar function
 numbers.
 .El
 .Pp
 Guest memory must be wired using the
 .Fl S
 option when a pass-through device is configured.
 .Pp
 The host device must have been reserved at boot-time using the
 .Va pptdevs
 loader variable as described in
 .Xr vmm 4 .
 .Pp
 Virtio console devices:
 .Bl -tag -width 10n
 .It Li port1= Ns Pa /path/to/port1.sock Ns ,anotherport= Ns Pa ...
 A maximum of 16 ports per device can be created.
 Every port is named and corresponds to a Unix domain socket created by
 .Nm .
 .Nm
 accepts at most one connection per port at a time.
 .Pp
 Limitations:
 .Bl -bullet -offset 2n
 .It
 Due to lack of destructors in
 .Nm ,
 sockets on the filesystem must be cleaned up manually after
 .Nm
 exits.
 .It
 There is no way to use the "console port" feature, nor the console port
 resize at present.
 .It
 Emergency write is advertised, but no-op at present.
 .El
 .El
 .Pp
 Framebuffer devices:
 .Bl -tag -width 10n
 .It Xo
 .Oo rfb= Ns Oo Ar IP\&: Oc Ns Ar port Oc Ns Oo ,w= Ns Ar width Oc Ns Oo ,h= Ns
 .Ar height Oc Ns Oo ,vga= Ns Ar vgaconf Oc Ns Oo Ns ,wait Oc Ns Oo ,password= Ns
 .Ar password Oc
 .Xc
 .Bl -tag -width 8n
 .It Ar IPv4:port No or Ar [IPv6%zone]:port
 An
 .Ar IP
 address and a
 .Ar port
 VNC should listen on.
 The default is to listen on localhost IPv4 address and default VNC port 5900.
 An IPv6 address must be enclosed in square brackets and may contain an
 optional zone identifier.
 .It Ar width No and Ar height
 A display resolution, width and height, respectively.
 If not specified, a default resolution of 1024x768 pixels will be used.
 Minimal supported resolution is 640x480 pixels,
 and maximum is 1920x1200 pixels.
 .It Ar vgaconf
 Possible values for this option are
 .Dq io
 (default),
 .Dq on
 , and
 .Dq off .
 PCI graphics cards have a dual personality in that they are
 standard PCI devices with BAR addressing, but may also
 implicitly decode legacy VGA I/O space
 .Pq Ad 0x3c0-3df
 and memory space
 .Pq 64KB at Ad 0xA0000 .
 The default
 .Dq io
 option should be used for guests that attempt to issue BIOS calls which result
 in I/O port queries, and fail to boot if I/O decode is disabled.
 .Pp
 The
 .Dq on
 option should be used along with the CSM BIOS capability in UEFI
 to boot traditional BIOS guests that require the legacy VGA I/O and
 memory regions to be available.
 .Pp
 The
 .Dq off
 option should be used for the UEFI guests that assume that
 VGA adapter is present if they detect the I/O ports.
 An example of such a guest is
 .Ox
 in UEFI mode.
 .Pp
 Please refer to the
 .Nm
 .Fx
 wiki page
 .Pq Lk https://wiki.freebsd.org/bhyve
 for configuration notes of particular guests.
 .It wait
 Instruct
 .Nm
 to only boot upon the initiation of a VNC connection, simplifying the
 installation of operating systems that require immediate keyboard input.
 This can be removed for post-installation use.
 .It password
 This type of authentication is known to be cryptographically weak and is not
 intended for use on untrusted networks.
 Many implementations will want to use stronger security, such as running
 the session over an encrypted channel provided by IPsec or SSH.
 .El
 .El
 .Pp
 xHCI USB devices:
 .Bl -tag -width 10n
 .It Li tablet
 A USB tablet device which provides precise cursor synchronization
 when using VNC.
 .El
 .Pp
 NVMe devices:
 .Bl -tag -width 10n
 .It Li devpath
 Accepted device paths are:
 .Ar /dev/blockdev
 or
 .Ar /path/to/image
 or
 .Ar ram=size_in_MiB .
 .It Li maxq
 Max number of queues.
 .It Li qsz
 Max elements in each queue.
 .It Li ioslots
 Max number of concurrent I/O requests.
 .It Li sectsz
 Sector size (defaults to blockif sector size).
 .It Li ser
 Serial number with maximum 20 characters.
 .El
 .Pp
 AHCI devices:
 .Bl -tag -width 10n
 .It Li nmrr
 Nominal Media Rotation Rate, known as RPM. value 1 will indicate device as Solid State Disk. default value is 0, not report.
 .It Li ser
 Serial Number with maximum 20 characters.
 .It Li rev
 Revision Number with maximum 8 characters.
 .It Li model
 Model Number with maximum 40 characters.
 .El
 .Pp
 HD Audio devices:
 .Bl -tag -width 10n
 .It Li play
 Playback device, typically
 .Ar /dev/dsp0 .
 .It Li rec
 Recording device, typically
 .Ar /dev/dsp0 .
 .El
 .El
 .It Fl S
 Wire guest memory.
 .It Fl u
 RTC keeps UTC time.
 .It Fl U Ar uuid
 Set the universally unique identifier
 .Pq UUID
 in the guest's System Management BIOS System Information structure.
 By default a UUID is generated from the host's hostname and
 .Ar vmname .
 .It Fl w
 Ignore accesses to unimplemented Model Specific Registers (MSRs).
 This is intended for debug purposes.
 .It Fl W
 Force virtio PCI device emulations to use MSI interrupts instead of MSI-X
 interrupts.
 .It Fl x
 The guest's local APIC is configured in x2APIC mode.
 .It Fl Y
 Disable MPtable generation.
 .It Ar vmname
 Alphanumeric name of the guest.
 This should be the same as that created by
 .Xr bhyveload 8 .
 .El
 .Sh DEBUG SERVER
 The current debug server provides limited support for debuggers.
 .Ss Registers
 Each virtual CPU is exposed to the debugger as a thread.
 .Pp
 General purpose registers can be queried for each virtual CPU, but other
 registers such as floating-point and system registers cannot be queried.
 .Ss Memory
 Memory (including memory mapped I/O regions) can be read and written by the debugger.
 Memory operations use virtual addresses that are resolved to physical addresses
 via the current virtual CPU's active address translation.
 .Ss Control
 The running guest can be interrupted by the debugger at any time
 .Pq for example, by pressing Ctrl-C in the debugger .
 .Pp
 Single stepping is only supported on Intel CPUs supporting the MTRAP VM exit.
 .Pp
 Breakpoints are supported on Intel CPUs that support single stepping.
 Note that continuing from a breakpoint while interrupts are enabled in the
 guest may not work as expected due to timer interrupts firing while single
 stepping over the breakpoint.
 .Sh SIGNAL HANDLING
 .Nm
 deals with the following signals:
 .Pp
 .Bl -tag -width indent -compact
 .It SIGTERM
 Trigger ACPI poweroff for a VM
 .El
 .Sh EXIT STATUS
 Exit status indicates how the VM was terminated:
 .Pp
 .Bl -tag -width indent -compact
 .It 0
 rebooted
 .It 1
 powered off
 .It 2
 halted
 .It 3
 triple fault
 .It 4
 exited due to an error
 .El
 .Sh EXAMPLES
 If not using a boot ROM, the guest operating system must have been loaded with
 .Xr bhyveload 8
 or a similar boot loader before
 .Xr bhyve 4
 can be run.
 Otherwise, the boot loader is not needed.
 .Pp
 To run a virtual machine with 1GB of memory, two virtual CPUs, a virtio
 block device backed by the
 .Pa /my/image
 filesystem image, and a serial port for the console:
 .Bd -literal -offset indent
 bhyve -c 2 -s 0,hostbridge -s 1,lpc -s 2,virtio-blk,/my/image \\
   -l com1,stdio -A -H -P -m 1G vm1
 .Ed
 .Pp
 Run a 24GB single-CPU virtual machine with three network ports, one of which
 has a MAC address specified:
 .Bd -literal -offset indent
 bhyve -s 0,hostbridge -s 1,lpc -s 2:0,virtio-net,tap0 \\
   -s 2:1,virtio-net,tap1 \\
   -s 2:2,virtio-net,tap2,mac=00:be:fa:76:45:00 \\
   -s 3,virtio-blk,/my/image -l com1,stdio \\
   -A -H -P -m 24G bigvm
 .Ed
 .Pp
 Run an 8GB quad-CPU virtual machine with 8 AHCI SATA disks, an AHCI ATAPI
 CD-ROM, a single virtio network port, an AMD hostbridge, and the console
 port connected to an
 .Xr nmdm 4
 null-modem device.
 .Bd -literal -offset indent
 bhyve -c 4 \\
   -s 0,amd_hostbridge -s 1,lpc \\
   -s 1:0,ahci,hd:/images/disk.1,hd:/images/disk.2,\\
 hd:/images/disk.3,hd:/images/disk.4,\\
 hd:/images/disk.5,hd:/images/disk.6,\\
 hd:/images/disk.7,hd:/images/disk.8,\\
 cd:/images/install.iso \\
   -s 3,virtio-net,tap0 \\
   -l com1,/dev/nmdm0A \\
   -A -H -P -m 8G
 .Ed
 .Pp
 Run a UEFI virtual machine with a display resolution of 800 by 600 pixels
 that can be accessed via VNC at: 0.0.0.0:5900.
 .Bd -literal -offset indent
 bhyve -c 2 -m 4G -w -H \\
   -s 0,hostbridge \\
   -s 3,ahci-cd,/path/to/uefi-OS-install.iso \\
   -s 4,ahci-hd,disk.img \\
   -s 5,virtio-net,tap0 \\
   -s 29,fbuf,tcp=0.0.0.0:5900,w=800,h=600,wait \\
   -s 30,xhci,tablet \\
   -s 31,lpc -l com1,stdio \\
   -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \\
    uefivm
 .Ed
 .Pp
 Run a UEFI virtual machine with a VNC display that is bound to all IPv6
 addresses on port 5900.
 .Bd -literal -offset indent
 bhyve -c 2 -m 4G -w -H \\
   -s 0,hostbridge \\
   -s 4,ahci-hd,disk.img \\
   -s 5,virtio-net,tap0 \\
   -s 29,fbuf,tcp=[::]:5900,w=800,h=600 \\
   -s 30,xhci,tablet \\
   -s 31,lpc -l com1,stdio \\
   -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd \\
    uefivm
 .Ed
 .Sh SEE ALSO
 .Xr bhyve 4 ,
 .Xr netgraph 4 ,
 .Xr ng_socket 4 ,
 .Xr nmdm 4 ,
 .Xr vmm 4 ,
 .Xr ethers 5 ,
 .Xr bhyvectl 8 ,
 .Xr bhyveload 8
 .Pp
 .Rs
 .%A Intel
 .%B 64 and IA-32 Architectures Software Developer’s Manual
 .%V Volume 3
 .Re
 .Sh HISTORY
 .Nm
 first appeared in
 .Fx 10.0 .
 .Sh AUTHORS
 .An Neel Natu Aq Mt neel@freebsd.org
 .An Peter Grehan Aq Mt grehan@freebsd.org
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index bca5f44c2b40..aafab4af8d8c 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -1,1460 +1,1442 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2011 NetApp, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $FreeBSD$
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
 #ifndef WITHOUT_CAPSICUM
 #include <sys/capsicum.h>
 #endif
 #include <sys/mman.h>
 #ifdef BHYVE_SNAPSHOT
 #include <sys/socket.h>
 #include <sys/stat.h>
 #endif
 #include <sys/time.h>
 #ifdef BHYVE_SNAPSHOT
 #include <sys/un.h>
 #endif
 
 #include <amd64/vmm/intel/vmcs.h>
 
 #include <machine/atomic.h>
 #include <machine/segments.h>
 
 #ifndef WITHOUT_CAPSICUM
 #include <capsicum_helpers.h>
 #endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <err.h>
 #include <errno.h>
 #ifdef BHYVE_SNAPSHOT
 #include <fcntl.h>
 #endif
 #include <libgen.h>
 #include <unistd.h>
 #include <assert.h>
 #include <pthread.h>
 #include <pthread_np.h>
 #include <sysexits.h>
 #include <stdbool.h>
 #include <stdint.h>
 #ifdef BHYVE_SNAPSHOT
 #include <ucl.h>
 #include <unistd.h>
 
 #include <libxo/xo.h>
 #endif
 
 #include <machine/vmm.h>
 #ifndef WITHOUT_CAPSICUM
 #include <machine/vmm_dev.h>
 #endif
 #include <machine/vmm_instruction_emul.h>
 #include <vmmapi.h>
 
 #include "bhyverun.h"
 #include "acpi.h"
 #include "atkbdc.h"
 #include "bootrom.h"
 #include "inout.h"
-#include "dbgport.h"
 #include "debug.h"
 #include "fwctl.h"
 #include "gdb.h"
 #include "ioapic.h"
 #include "kernemu_dev.h"
 #include "mem.h"
 #include "mevent.h"
 #include "mptbl.h"
 #include "pci_emul.h"
 #include "pci_irq.h"
 #include "pci_lpc.h"
 #include "smbiostbl.h"
 #ifdef BHYVE_SNAPSHOT
 #include "snapshot.h"
 #endif
 #include "xmsr.h"
 #include "spinup_ap.h"
 #include "rtc.h"
 #include "vmgenc.h"
 
 #define GUEST_NIO_PORT		0x488	/* guest upcalls via i/o port */
 
 #define MB		(1024UL * 1024)
 #define GB		(1024UL * MB)
 
 static const char * const vmx_exit_reason_desc[] = {
 	[EXIT_REASON_EXCEPTION] = "Exception or non-maskable interrupt (NMI)",
 	[EXIT_REASON_EXT_INTR] = "External interrupt",
 	[EXIT_REASON_TRIPLE_FAULT] = "Triple fault",
 	[EXIT_REASON_INIT] = "INIT signal",
 	[EXIT_REASON_SIPI] = "Start-up IPI (SIPI)",
 	[EXIT_REASON_IO_SMI] = "I/O system-management interrupt (SMI)",
 	[EXIT_REASON_SMI] = "Other SMI",
 	[EXIT_REASON_INTR_WINDOW] = "Interrupt window",
 	[EXIT_REASON_NMI_WINDOW] = "NMI window",
 	[EXIT_REASON_TASK_SWITCH] = "Task switch",
 	[EXIT_REASON_CPUID] = "CPUID",
 	[EXIT_REASON_GETSEC] = "GETSEC",
 	[EXIT_REASON_HLT] = "HLT",
 	[EXIT_REASON_INVD] = "INVD",
 	[EXIT_REASON_INVLPG] = "INVLPG",
 	[EXIT_REASON_RDPMC] = "RDPMC",
 	[EXIT_REASON_RDTSC] = "RDTSC",
 	[EXIT_REASON_RSM] = "RSM",
 	[EXIT_REASON_VMCALL] = "VMCALL",
 	[EXIT_REASON_VMCLEAR] = "VMCLEAR",
 	[EXIT_REASON_VMLAUNCH] = "VMLAUNCH",
 	[EXIT_REASON_VMPTRLD] = "VMPTRLD",
 	[EXIT_REASON_VMPTRST] = "VMPTRST",
 	[EXIT_REASON_VMREAD] = "VMREAD",
 	[EXIT_REASON_VMRESUME] = "VMRESUME",
 	[EXIT_REASON_VMWRITE] = "VMWRITE",
 	[EXIT_REASON_VMXOFF] = "VMXOFF",
 	[EXIT_REASON_VMXON] = "VMXON",
 	[EXIT_REASON_CR_ACCESS] = "Control-register accesses",
 	[EXIT_REASON_DR_ACCESS] = "MOV DR",
 	[EXIT_REASON_INOUT] = "I/O instruction",
 	[EXIT_REASON_RDMSR] = "RDMSR",
 	[EXIT_REASON_WRMSR] = "WRMSR",
 	[EXIT_REASON_INVAL_VMCS] =
 	    "VM-entry failure due to invalid guest state",
 	[EXIT_REASON_INVAL_MSR] = "VM-entry failure due to MSR loading",
 	[EXIT_REASON_MWAIT] = "MWAIT",
 	[EXIT_REASON_MTF] = "Monitor trap flag",
 	[EXIT_REASON_MONITOR] = "MONITOR",
 	[EXIT_REASON_PAUSE] = "PAUSE",
 	[EXIT_REASON_MCE_DURING_ENTRY] =
 	    "VM-entry failure due to machine-check event",
 	[EXIT_REASON_TPR] = "TPR below threshold",
 	[EXIT_REASON_APIC_ACCESS] = "APIC access",
 	[EXIT_REASON_VIRTUALIZED_EOI] = "Virtualized EOI",
 	[EXIT_REASON_GDTR_IDTR] = "Access to GDTR or IDTR",
 	[EXIT_REASON_LDTR_TR] = "Access to LDTR or TR",
 	[EXIT_REASON_EPT_FAULT] = "EPT violation",
 	[EXIT_REASON_EPT_MISCONFIG] = "EPT misconfiguration",
 	[EXIT_REASON_INVEPT] = "INVEPT",
 	[EXIT_REASON_RDTSCP] = "RDTSCP",
 	[EXIT_REASON_VMX_PREEMPT] = "VMX-preemption timer expired",
 	[EXIT_REASON_INVVPID] = "INVVPID",
 	[EXIT_REASON_WBINVD] = "WBINVD",
 	[EXIT_REASON_XSETBV] = "XSETBV",
 	[EXIT_REASON_APIC_WRITE] = "APIC write",
 	[EXIT_REASON_RDRAND] = "RDRAND",
 	[EXIT_REASON_INVPCID] = "INVPCID",
 	[EXIT_REASON_VMFUNC] = "VMFUNC",
 	[EXIT_REASON_ENCLS] = "ENCLS",
 	[EXIT_REASON_RDSEED] = "RDSEED",
 	[EXIT_REASON_PM_LOG_FULL] = "Page-modification log full",
 	[EXIT_REASON_XSAVES] = "XSAVES",
 	[EXIT_REASON_XRSTORS] = "XRSTORS"
 };
 
 typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu);
 extern int vmexit_task_switch(struct vmctx *, struct vm_exit *, int *vcpu);
 
 const char *vmname;
 
 int guest_ncpus;
 uint16_t cores, maxcpus, sockets, threads;
 
 char *guest_uuid_str;
 
 int raw_stdio = 0;
 
 static int gdb_port = 0;
 static int guest_vmexit_on_hlt, guest_vmexit_on_pause;
 static int virtio_msix = 1;
 static int x2apic_mode = 0;	/* default is xAPIC */
 static int destroy_on_poweroff = 0;
 
 static int strictio;
 static int strictmsr = 1;
 
 static int acpi;
 
 static char *progname;
 static const int BSP = 0;
 
 static cpuset_t cpumask;
 
 static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip);
 
 static struct vm_exit vmexit[VM_MAXCPU];
 
 struct bhyvestats {
 	uint64_t	vmexit_bogus;
 	uint64_t	vmexit_reqidle;
 	uint64_t	vmexit_hlt;
 	uint64_t	vmexit_pause;
 	uint64_t	vmexit_mtrap;
 	uint64_t	vmexit_inst_emul;
 	uint64_t	cpu_switch_rotate;
 	uint64_t	cpu_switch_direct;
 } stats;
 
 struct mt_vmm_info {
 	pthread_t	mt_thr;
 	struct vmctx	*mt_ctx;
 	int		mt_vcpu;	
 } mt_vmm_info[VM_MAXCPU];
 
 static cpuset_t *vcpumap[VM_MAXCPU] = { NULL };
 
 static void
 usage(int code)
 {
 
         fprintf(stderr,
-		"Usage: %s [-abehuwxACDHPSWY]\n"
+		"Usage: %s [-aehuwxACDHPSWY]\n"
 		"       %*s [-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n]]\n"
-		"       %*s [-g <gdb port>] [-l <lpc>]\n"
+		"       %*s [-l <lpc>]\n"
 		"       %*s [-m mem] [-p vcpu:hostcpu] [-s <pci>] [-U uuid] <vm>\n"
 		"       -a: local apic is in xAPIC mode (deprecated)\n"
 		"       -A: create ACPI tables\n"
 		"       -c: number of cpus and/or topology specification\n"
 		"       -C: include guest memory in core file\n"
 		"       -D: destroy on power-off\n"
 		"       -e: exit on unhandled I/O access\n"
-		"       -g: gdb port\n"
 		"       -h: help\n"
 		"       -H: vmexit from the guest on hlt\n"
 		"       -l: LPC device configuration\n"
 		"       -m: memory size in MB\n"
 #ifdef BHYVE_SNAPSHOT
 		"       -r: path to checkpoint file\n"
 #endif
 		"       -p: pin 'vcpu' to 'hostcpu'\n"
 		"       -P: vmexit from the guest on pause\n"
 		"       -s: <slot,driver,configinfo> PCI slot config\n"
 		"       -S: guest memory cannot be swapped\n"
 		"       -u: RTC keeps UTC time\n"
 		"       -U: uuid\n"
 		"       -w: ignore unimplemented MSRs\n"
 		"       -W: force virtio to use single-vector MSI\n"
 		"       -x: local apic is in x2APIC mode\n"
 		"       -Y: disable MPtable generation\n",
 		progname, (int)strlen(progname), "", (int)strlen(progname), "",
 		(int)strlen(progname), "");
 
 	exit(code);
 }
 
 /*
  * XXX This parser is known to have the following issues:
  * 1.  It accepts null key=value tokens ",,".
  * 2.  It accepts whitespace after = and before value.
  * 3.  Values out of range of INT are silently wrapped.
  * 4.  It doesn't check non-final values.
  * 5.  The apparently bogus limits of UINT16_MAX are for future expansion.
  *
  * The acceptance of a null specification ('-c ""') is by design to match the
  * manual page syntax specification, this results in a topology of 1 vCPU.
  */
 static int
 topology_parse(const char *opt)
 {
 	uint64_t ncpus;
 	int c, chk, n, s, t, tmp;
 	char *cp, *str;
 	bool ns, scts;
 
 	c = 1, n = 1, s = 1, t = 1;
 	ns = false, scts = false;
 	str = strdup(opt);
 	if (str == NULL)
 		goto out;
 
 	while ((cp = strsep(&str, ",")) != NULL) {
 		if (sscanf(cp, "%i%n", &tmp, &chk) == 1) {
 			n = tmp;
 			ns = true;
 		} else if (sscanf(cp, "cpus=%i%n", &tmp, &chk) == 1) {
 			n = tmp;
 			ns = true;
 		} else if (sscanf(cp, "sockets=%i%n", &tmp, &chk) == 1) {
 			s = tmp;
 			scts = true;
 		} else if (sscanf(cp, "cores=%i%n", &tmp, &chk) == 1) {
 			c = tmp;
 			scts = true;
 		} else if (sscanf(cp, "threads=%i%n", &tmp, &chk) == 1) {
 			t = tmp;
 			scts = true;
 #ifdef notyet  /* Do not expose this until vmm.ko implements it */
 		} else if (sscanf(cp, "maxcpus=%i%n", &tmp, &chk) == 1) {
 			m = tmp;
 #endif
 		/* Skip the empty argument case from -c "" */
 		} else if (cp[0] == '\0')
 			continue;
 		else
 			goto out;
 		/* Any trailing garbage causes an error */
 		if (cp[chk] != '\0')
 			goto out;
 	}
 	free(str);
 	str = NULL;
 
 	/*
 	 * Range check 1 <= n <= UINT16_MAX all values
 	 */
 	if (n < 1 || s < 1 || c < 1 || t < 1 ||
 	    n > UINT16_MAX || s > UINT16_MAX || c > UINT16_MAX  ||
 	    t > UINT16_MAX)
 		return (-1);
 
 	/* If only the cpus was specified, use that as sockets */
 	if (!scts)
 		s = n;
 	/*
 	 * Compute sockets * cores * threads avoiding overflow
 	 * The range check above insures these are 16 bit values
 	 * If n was specified check it against computed ncpus
 	 */
 	ncpus = (uint64_t)s * c * t;
 	if (ncpus > UINT16_MAX || (ns && n != ncpus))
 		return (-1);
 
 	guest_ncpus = ncpus;
 	sockets = s;
 	cores = c;
 	threads = t;
 	return(0);
 
 out:
 	free(str);
 	return (-1);
 }
 
 static int
 pincpu_parse(const char *opt)
 {
 	int vcpu, pcpu;
 
 	if (sscanf(opt, "%d:%d", &vcpu, &pcpu) != 2) {
 		fprintf(stderr, "invalid format: %s\n", opt);
 		return (-1);
 	}
 
 	if (vcpu < 0 || vcpu >= VM_MAXCPU) {
 		fprintf(stderr, "vcpu '%d' outside valid range from 0 to %d\n",
 		    vcpu, VM_MAXCPU - 1);
 		return (-1);
 	}
 
 	if (pcpu < 0 || pcpu >= CPU_SETSIZE) {
 		fprintf(stderr, "hostcpu '%d' outside valid range from "
 		    "0 to %d\n", pcpu, CPU_SETSIZE - 1);
 		return (-1);
 	}
 
 	if (vcpumap[vcpu] == NULL) {
 		if ((vcpumap[vcpu] = malloc(sizeof(cpuset_t))) == NULL) {
 			perror("malloc");
 			return (-1);
 		}
 		CPU_ZERO(vcpumap[vcpu]);
 	}
 	CPU_SET(pcpu, vcpumap[vcpu]);
 	return (0);
 }
 
 void
 vm_inject_fault(void *arg, int vcpu, int vector, int errcode_valid,
     int errcode)
 {
 	struct vmctx *ctx;
 	int error, restart_instruction;
 
 	ctx = arg;
 	restart_instruction = 1;
 
 	error = vm_inject_exception(ctx, vcpu, vector, errcode_valid, errcode,
 	    restart_instruction);
 	assert(error == 0);
 }
 
 void *
 paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len)
 {
 
 	return (vm_map_gpa(ctx, gaddr, len));
 }
 
 #ifdef BHYVE_SNAPSHOT
 uintptr_t
 paddr_host2guest(struct vmctx *ctx, void *addr)
 {
 	return (vm_rev_map_gpa(ctx, addr));
 }
 #endif
 
 int
 fbsdrun_vmexit_on_pause(void)
 {
 
 	return (guest_vmexit_on_pause);
 }
 
 int
 fbsdrun_vmexit_on_hlt(void)
 {
 
 	return (guest_vmexit_on_hlt);
 }
 
 int
 fbsdrun_virtio_msix(void)
 {
 
 	return (virtio_msix);
 }
 
 static void *
 fbsdrun_start_thread(void *param)
 {
 	char tname[MAXCOMLEN + 1];
 	struct mt_vmm_info *mtp;
 	int vcpu;
 
 	mtp = param;
 	vcpu = mtp->mt_vcpu;
 
 	snprintf(tname, sizeof(tname), "vcpu %d", vcpu);
 	pthread_set_name_np(mtp->mt_thr, tname);
 
 #ifdef BHYVE_SNAPSHOT
 	checkpoint_cpu_add(vcpu);
 #endif
 	if (gdb_port != 0)
 		gdb_cpu_add(vcpu);
 
 	vm_loop(mtp->mt_ctx, vcpu, vmexit[vcpu].rip);
 
 	/* not reached */
 	exit(1);
 	return (NULL);
 }
 
 void
 fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip)
 {
 	int error;
 
 	assert(fromcpu == BSP);
 
 	/*
 	 * The 'newcpu' must be activated in the context of 'fromcpu'. If
 	 * vm_activate_cpu() is delayed until newcpu's pthread starts running
 	 * then vmm.ko is out-of-sync with bhyve and this can create a race
 	 * with vm_suspend().
 	 */
 	error = vm_activate_cpu(ctx, newcpu);
 	if (error != 0)
 		err(EX_OSERR, "could not activate CPU %d", newcpu);
 
 	CPU_SET_ATOMIC(newcpu, &cpumask);
 
 	/*
 	 * Set up the vmexit struct to allow execution to start
 	 * at the given RIP
 	 */
 	vmexit[newcpu].rip = rip;
 	vmexit[newcpu].inst_length = 0;
 
 	mt_vmm_info[newcpu].mt_ctx = ctx;
 	mt_vmm_info[newcpu].mt_vcpu = newcpu;
 
 	error = pthread_create(&mt_vmm_info[newcpu].mt_thr, NULL,
 	    fbsdrun_start_thread, &mt_vmm_info[newcpu]);
 	assert(error == 0);
 }
 
 static int
 fbsdrun_deletecpu(struct vmctx *ctx, int vcpu)
 {
 
 	if (!CPU_ISSET(vcpu, &cpumask)) {
 		fprintf(stderr, "Attempting to delete unknown cpu %d\n", vcpu);
 		exit(4);
 	}
 
 	CPU_CLR_ATOMIC(vcpu, &cpumask);
 	return (CPU_EMPTY(&cpumask));
 }
 
 static int
 vmexit_handle_notify(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu,
 		     uint32_t eax)
 {
 #if BHYVE_DEBUG
 	/*
 	 * put guest-driven debug here
 	 */
 #endif
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
 {
 	int error;
 	int bytes, port, in, out;
 	int vcpu;
 
 	vcpu = *pvcpu;
 
 	port = vme->u.inout.port;
 	bytes = vme->u.inout.bytes;
 	in = vme->u.inout.in;
 	out = !in;
 
         /* Extra-special case of host notifications */
         if (out && port == GUEST_NIO_PORT) {
                 error = vmexit_handle_notify(ctx, vme, pvcpu, vme->u.inout.eax);
 		return (error);
 	}
 
 	error = emulate_inout(ctx, vcpu, vme, strictio);
 	if (error) {
 		fprintf(stderr, "Unhandled %s%c 0x%04x at 0x%lx\n",
 		    in ? "in" : "out",
 		    bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'),
 		    port, vmexit->rip);
 		return (VMEXIT_ABORT);
 	} else {
 		return (VMEXIT_CONTINUE);
 	}
 }
 
 static int
 vmexit_rdmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
 {
 	uint64_t val;
 	uint32_t eax, edx;
 	int error;
 
 	val = 0;
 	error = emulate_rdmsr(ctx, *pvcpu, vme->u.msr.code, &val);
 	if (error != 0) {
 		fprintf(stderr, "rdmsr to register %#x on vcpu %d\n",
 		    vme->u.msr.code, *pvcpu);
 		if (strictmsr) {
 			vm_inject_gp(ctx, *pvcpu);
 			return (VMEXIT_CONTINUE);
 		}
 	}
 
 	eax = val;
 	error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RAX, eax);
 	assert(error == 0);
 
 	edx = val >> 32;
 	error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RDX, edx);
 	assert(error == 0);
 
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
 {
 	int error;
 
 	error = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code, vme->u.msr.wval);
 	if (error != 0) {
 		fprintf(stderr, "wrmsr to register %#x(%#lx) on vcpu %d\n",
 		    vme->u.msr.code, vme->u.msr.wval, *pvcpu);
 		if (strictmsr) {
 			vm_inject_gp(ctx, *pvcpu);
 			return (VMEXIT_CONTINUE);
 		}
 	}
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
 {
 
 	(void)spinup_ap(ctx, *pvcpu,
 		    vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip);
 
 	return (VMEXIT_CONTINUE);
 }
 
 #define	DEBUG_EPT_MISCONFIG
 #ifdef DEBUG_EPT_MISCONFIG
 #define	VMCS_GUEST_PHYSICAL_ADDRESS	0x00002400
 
 static uint64_t ept_misconfig_gpa, ept_misconfig_pte[4];
 static int ept_misconfig_ptenum;
 #endif
 
 static const char *
 vmexit_vmx_desc(uint32_t exit_reason)
 {
 
 	if (exit_reason >= nitems(vmx_exit_reason_desc) ||
 	    vmx_exit_reason_desc[exit_reason] == NULL)
 		return ("Unknown");
 	return (vmx_exit_reason_desc[exit_reason]);
 }
 
 static int
 vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	fprintf(stderr, "vm exit[%d]\n", *pvcpu);
 	fprintf(stderr, "\treason\t\tVMX\n");
 	fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
 	fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
 	fprintf(stderr, "\tstatus\t\t%d\n", vmexit->u.vmx.status);
 	fprintf(stderr, "\texit_reason\t%u (%s)\n", vmexit->u.vmx.exit_reason,
 	    vmexit_vmx_desc(vmexit->u.vmx.exit_reason));
 	fprintf(stderr, "\tqualification\t0x%016lx\n",
 	    vmexit->u.vmx.exit_qualification);
 	fprintf(stderr, "\tinst_type\t\t%d\n", vmexit->u.vmx.inst_type);
 	fprintf(stderr, "\tinst_error\t\t%d\n", vmexit->u.vmx.inst_error);
 #ifdef DEBUG_EPT_MISCONFIG
 	if (vmexit->u.vmx.exit_reason == EXIT_REASON_EPT_MISCONFIG) {
 		vm_get_register(ctx, *pvcpu,
 		    VMCS_IDENT(VMCS_GUEST_PHYSICAL_ADDRESS),
 		    &ept_misconfig_gpa);
 		vm_get_gpa_pmap(ctx, ept_misconfig_gpa, ept_misconfig_pte,
 		    &ept_misconfig_ptenum);
 		fprintf(stderr, "\tEPT misconfiguration:\n");
 		fprintf(stderr, "\t\tGPA: %#lx\n", ept_misconfig_gpa);
 		fprintf(stderr, "\t\tPTE(%d): %#lx %#lx %#lx %#lx\n",
 		    ept_misconfig_ptenum, ept_misconfig_pte[0],
 		    ept_misconfig_pte[1], ept_misconfig_pte[2],
 		    ept_misconfig_pte[3]);
 	}
 #endif	/* DEBUG_EPT_MISCONFIG */
 	return (VMEXIT_ABORT);
 }
 
 static int
 vmexit_svm(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	fprintf(stderr, "vm exit[%d]\n", *pvcpu);
 	fprintf(stderr, "\treason\t\tSVM\n");
 	fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
 	fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
 	fprintf(stderr, "\texitcode\t%#lx\n", vmexit->u.svm.exitcode);
 	fprintf(stderr, "\texitinfo1\t%#lx\n", vmexit->u.svm.exitinfo1);
 	fprintf(stderr, "\texitinfo2\t%#lx\n", vmexit->u.svm.exitinfo2);
 	return (VMEXIT_ABORT);
 }
 
 static int
 vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	assert(vmexit->inst_length == 0);
 
 	stats.vmexit_bogus++;
 
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_reqidle(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	assert(vmexit->inst_length == 0);
 
 	stats.vmexit_reqidle++;
 
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	stats.vmexit_hlt++;
 
 	/*
 	 * Just continue execution with the next instruction. We use
 	 * the HLT VM exit as a way to be friendly with the host
 	 * scheduler.
 	 */
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_pause(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	stats.vmexit_pause++;
 
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	assert(vmexit->inst_length == 0);
 
 	stats.vmexit_mtrap++;
 
 #ifdef BHYVE_SNAPSHOT
 	checkpoint_cpu_suspend(*pvcpu);
 #endif
 	if (gdb_port != 0)
 		gdb_cpu_mtrap(*pvcpu);
 #ifdef BHYVE_SNAPSHOT
 	checkpoint_cpu_resume(*pvcpu);
 #endif
 
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_inst_emul(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 	int err, i, cs_d;
 	struct vie *vie;
 	enum vm_cpu_mode mode;
 
 	stats.vmexit_inst_emul++;
 
 	vie = &vmexit->u.inst_emul.vie;
 	if (!vie->decoded) {
 		/*
 		 * Attempt to decode in userspace as a fallback.  This allows
 		 * updating instruction decode in bhyve without rebooting the
 		 * kernel (rapid prototyping), albeit with much slower
 		 * emulation.
 		 */
 		vie_restart(vie);
 		mode = vmexit->u.inst_emul.paging.cpu_mode;
 		cs_d = vmexit->u.inst_emul.cs_d;
 		if (vmm_decode_instruction(mode, cs_d, vie) != 0)
 			goto fail;
 		if (vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RIP,
 		    vmexit->rip + vie->num_processed) != 0)
 			goto fail;
 	}
 
 	err = emulate_mem(ctx, *pvcpu, vmexit->u.inst_emul.gpa,
 	    vie, &vmexit->u.inst_emul.paging);
 
 	if (err) {
 		if (err == ESRCH) {
 			EPRINTLN("Unhandled memory access to 0x%lx\n",
 			    vmexit->u.inst_emul.gpa);
 		}
 		goto fail;
 	}
 
 	return (VMEXIT_CONTINUE);
 
 fail:
 	fprintf(stderr, "Failed to emulate instruction sequence [ ");
 	for (i = 0; i < vie->num_valid; i++)
 		fprintf(stderr, "%02x", vie->inst[i]);
 	FPRINTLN(stderr, " ] at 0x%lx", vmexit->rip);
 	return (VMEXIT_ABORT);
 }
 
 static pthread_mutex_t resetcpu_mtx = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t resetcpu_cond = PTHREAD_COND_INITIALIZER;
 
 static int
 vmexit_suspend(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 	enum vm_suspend_how how;
 
 	how = vmexit->u.suspended.how;
 
 	fbsdrun_deletecpu(ctx, *pvcpu);
 
 	if (*pvcpu != BSP) {
 		pthread_mutex_lock(&resetcpu_mtx);
 		pthread_cond_signal(&resetcpu_cond);
 		pthread_mutex_unlock(&resetcpu_mtx);
 		pthread_exit(NULL);
 	}
 
 	pthread_mutex_lock(&resetcpu_mtx);
 	while (!CPU_EMPTY(&cpumask)) {
 		pthread_cond_wait(&resetcpu_cond, &resetcpu_mtx);
 	}
 	pthread_mutex_unlock(&resetcpu_mtx);
 
 	switch (how) {
 	case VM_SUSPEND_RESET:
 		exit(0);
 	case VM_SUSPEND_POWEROFF:
 		if (destroy_on_poweroff)
 			vm_destroy(ctx);
 		exit(1);
 	case VM_SUSPEND_HALT:
 		exit(2);
 	case VM_SUSPEND_TRIPLEFAULT:
 		exit(3);
 	default:
 		fprintf(stderr, "vmexit_suspend: invalid reason %d\n", how);
 		exit(100);
 	}
 	return (0);	/* NOTREACHED */
 }
 
 static int
 vmexit_debug(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 #ifdef BHYVE_SNAPSHOT
 	checkpoint_cpu_suspend(*pvcpu);
 #endif
 	if (gdb_port != 0)
 		gdb_cpu_suspend(*pvcpu);
 #ifdef BHYVE_SNAPSHOT
 	checkpoint_cpu_resume(*pvcpu);
 #endif
 	return (VMEXIT_CONTINUE);
 }
 
 static int
 vmexit_breakpoint(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
 {
 
 	if (gdb_port == 0) {
 		fprintf(stderr, "vm_loop: unexpected VMEXIT_DEBUG\n");
 		exit(4);
 	}
 	gdb_cpu_breakpoint(*pvcpu, vmexit);
 	return (VMEXIT_CONTINUE);
 }
 
 static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
 	[VM_EXITCODE_INOUT]  = vmexit_inout,
 	[VM_EXITCODE_INOUT_STR]  = vmexit_inout,
 	[VM_EXITCODE_VMX]    = vmexit_vmx,
 	[VM_EXITCODE_SVM]    = vmexit_svm,
 	[VM_EXITCODE_BOGUS]  = vmexit_bogus,
 	[VM_EXITCODE_REQIDLE] = vmexit_reqidle,
 	[VM_EXITCODE_RDMSR]  = vmexit_rdmsr,
 	[VM_EXITCODE_WRMSR]  = vmexit_wrmsr,
 	[VM_EXITCODE_MTRAP]  = vmexit_mtrap,
 	[VM_EXITCODE_INST_EMUL] = vmexit_inst_emul,
 	[VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
 	[VM_EXITCODE_SUSPENDED] = vmexit_suspend,
 	[VM_EXITCODE_TASK_SWITCH] = vmexit_task_switch,
 	[VM_EXITCODE_DEBUG] = vmexit_debug,
 	[VM_EXITCODE_BPT] = vmexit_breakpoint,
 };
 
 static void
 vm_loop(struct vmctx *ctx, int vcpu, uint64_t startrip)
 {
 	int error, rc;
 	enum vm_exitcode exitcode;
 	cpuset_t active_cpus;
 
 	if (vcpumap[vcpu] != NULL) {
 		error = pthread_setaffinity_np(pthread_self(),
 		    sizeof(cpuset_t), vcpumap[vcpu]);
 		assert(error == 0);
 	}
 
 	error = vm_active_cpus(ctx, &active_cpus);
 	assert(CPU_ISSET(vcpu, &active_cpus));
 
 	error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RIP, startrip);
 	assert(error == 0);
 
 	while (1) {
 		error = vm_run(ctx, vcpu, &vmexit[vcpu]);
 		if (error != 0)
 			break;
 
 		exitcode = vmexit[vcpu].exitcode;
 		if (exitcode >= VM_EXITCODE_MAX || handler[exitcode] == NULL) {
 			fprintf(stderr, "vm_loop: unexpected exitcode 0x%x\n",
 			    exitcode);
 			exit(4);
 		}
 
 		rc = (*handler[exitcode])(ctx, &vmexit[vcpu], &vcpu);
 
 		switch (rc) {
 		case VMEXIT_CONTINUE:
 			break;
 		case VMEXIT_ABORT:
 			abort();
 		default:
 			exit(4);
 		}
 	}
 	fprintf(stderr, "vm_run error %d, errno %d\n", error, errno);
 }
 
 static int
 num_vcpus_allowed(struct vmctx *ctx)
 {
 	int tmp, error;
 
 	error = vm_get_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, &tmp);
 
 	/*
 	 * The guest is allowed to spinup more than one processor only if the
 	 * UNRESTRICTED_GUEST capability is available.
 	 */
 	if (error == 0)
 		return (VM_MAXCPU);
 	else
 		return (1);
 }
 
 void
 fbsdrun_set_capabilities(struct vmctx *ctx, int cpu)
 {
 	int err, tmp;
 
 	if (fbsdrun_vmexit_on_hlt()) {
 		err = vm_get_capability(ctx, cpu, VM_CAP_HALT_EXIT, &tmp);
 		if (err < 0) {
 			fprintf(stderr, "VM exit on HLT not supported\n");
 			exit(4);
 		}
 		vm_set_capability(ctx, cpu, VM_CAP_HALT_EXIT, 1);
 		if (cpu == BSP)
 			handler[VM_EXITCODE_HLT] = vmexit_hlt;
 	}
 
         if (fbsdrun_vmexit_on_pause()) {
 		/*
 		 * pause exit support required for this mode
 		 */
 		err = vm_get_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, &tmp);
 		if (err < 0) {
 			fprintf(stderr,
 			    "SMP mux requested, no pause support\n");
 			exit(4);
 		}
 		vm_set_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, 1);
 		if (cpu == BSP)
 			handler[VM_EXITCODE_PAUSE] = vmexit_pause;
         }
 
 	if (x2apic_mode)
 		err = vm_set_x2apic_state(ctx, cpu, X2APIC_ENABLED);
 	else
 		err = vm_set_x2apic_state(ctx, cpu, X2APIC_DISABLED);
 
 	if (err) {
 		fprintf(stderr, "Unable to set x2apic state (%d)\n", err);
 		exit(4);
 	}
 
 	vm_set_capability(ctx, cpu, VM_CAP_ENABLE_INVPCID, 1);
 }
 
 static struct vmctx *
 do_open(const char *vmname)
 {
 	struct vmctx *ctx;
 	int error;
 	bool reinit, romboot;
 #ifndef WITHOUT_CAPSICUM
 	cap_rights_t rights;
 	const cap_ioctl_t *cmds;	
 	size_t ncmds;
 #endif
 
 	reinit = romboot = false;
 
 	if (lpc_bootrom())
 		romboot = true;
 
 	error = vm_create(vmname);
 	if (error) {
 		if (errno == EEXIST) {
 			if (romboot) {
 				reinit = true;
 			} else {
 				/*
 				 * The virtual machine has been setup by the
 				 * userspace bootloader.
 				 */
 			}
 		} else {
 			perror("vm_create");
 			exit(4);
 		}
 	} else {
 		if (!romboot) {
 			/*
 			 * If the virtual machine was just created then a
 			 * bootrom must be configured to boot it.
 			 */
 			fprintf(stderr, "virtual machine cannot be booted\n");
 			exit(4);
 		}
 	}
 
 	ctx = vm_open(vmname);
 	if (ctx == NULL) {
 		perror("vm_open");
 		exit(4);
 	}
 
 #ifndef WITHOUT_CAPSICUM
 	cap_rights_init(&rights, CAP_IOCTL, CAP_MMAP_RW);
 	if (caph_rights_limit(vm_get_device_fd(ctx), &rights) == -1) 
 		errx(EX_OSERR, "Unable to apply rights for sandbox");
 	vm_get_ioctls(&ncmds);
 	cmds = vm_get_ioctls(NULL);
 	if (cmds == NULL)
 		errx(EX_OSERR, "out of memory");
 	if (caph_ioctls_limit(vm_get_device_fd(ctx), cmds, ncmds) == -1)
 		errx(EX_OSERR, "Unable to apply rights for sandbox");
 	free((cap_ioctl_t *)cmds);
 #endif
  
 	if (reinit) {
 		error = vm_reinit(ctx);
 		if (error) {
 			perror("vm_reinit");
 			exit(4);
 		}
 	}
 	error = vm_set_topology(ctx, sockets, cores, threads, maxcpus);
 	if (error)
 		errx(EX_OSERR, "vm_set_topology");
 	return (ctx);
 }
 
 void
 spinup_vcpu(struct vmctx *ctx, int vcpu)
 {
 	int error;
 	uint64_t rip;
 
 	error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip);
 	assert(error == 0);
 
 	fbsdrun_set_capabilities(ctx, vcpu);
 	error = vm_set_capability(ctx, vcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
 	assert(error == 0);
 
 	fbsdrun_addcpu(ctx, BSP, vcpu, rip);
 }
 
 int
 main(int argc, char *argv[])
 {
-	int c, error, dbg_port, err, bvmcons;
+	int c, error, err;
 	int max_vcpus, mptgen, memflags;
 	int rtc_localtime;
 	bool gdb_stop;
 	struct vmctx *ctx;
 	uint64_t rip;
 	size_t memsize;
 	char *optstr;
 #ifdef BHYVE_SNAPSHOT
 	char *restore_file;
 	struct restore_state rstate;
 	int vcpu;
 
 	restore_file = NULL;
 #endif
 
-	bvmcons = 0;
 	progname = basename(argv[0]);
-	dbg_port = 0;
 	gdb_stop = false;
 	guest_ncpus = 1;
 	sockets = cores = threads = 1;
 	maxcpus = 0;
 	memsize = 256 * MB;
 	mptgen = 1;
 	rtc_localtime = 1;
 	memflags = 0;
 
 #ifdef BHYVE_SNAPSHOT
-	optstr = "abehuwxACDHIPSWYp:g:G:c:s:m:l:U:r:";
+	optstr = "aehuwxACDHIPSWYp:G:c:s:m:l:U:r:";
 #else
-	optstr = "abehuwxACDHIPSWYp:g:G:c:s:m:l:U:";
+	optstr = "aehuwxACDHIPSWYp:G:c:s:m:l:U:";
 #endif
 	while ((c = getopt(argc, argv, optstr)) != -1) {
 		switch (c) {
 		case 'a':
 			x2apic_mode = 0;
 			break;
 		case 'A':
 			acpi = 1;
 			break;
-		case 'b':
-			warnx("-b flag is deprecated and will be removed in FreeBSD 13.0");
-			bvmcons = 1;
-			break;
 		case 'D':
 			destroy_on_poweroff = 1;
 			break;
 		case 'p':
                         if (pincpu_parse(optarg) != 0) {
                             errx(EX_USAGE, "invalid vcpu pinning "
                                  "configuration '%s'", optarg);
                         }
 			break;
                 case 'c':
 			if (topology_parse(optarg) != 0) {
 			    errx(EX_USAGE, "invalid cpu topology "
 				"'%s'", optarg);
 			}
 			break;
 		case 'C':
 			memflags |= VM_MEM_F_INCORE;
 			break;
-		case 'g':
-			warnx("-g flag is deprecated and will be removed in FreeBSD 13.0");
-			dbg_port = atoi(optarg);
-			break;
 		case 'G':
 			if (optarg[0] == 'w') {
 				gdb_stop = true;
 				optarg++;
 			}
 			gdb_port = atoi(optarg);
 			break;
 		case 'l':
 			if (strncmp(optarg, "help", strlen(optarg)) == 0) {
 				lpc_print_supported_devices();
 				exit(0);
 			} else if (lpc_device_parse(optarg) != 0) {
 				errx(EX_USAGE, "invalid lpc device "
 				    "configuration '%s'", optarg);
 			}
 			break;
 #ifdef BHYVE_SNAPSHOT
 		case 'r':
 			restore_file = optarg;
 			break;
 #endif
 		case 's':
 			if (strncmp(optarg, "help", strlen(optarg)) == 0) {
 				pci_print_supported_devices();
 				exit(0);
 			} else if (pci_parse_slot(optarg) != 0)
 				exit(4);
 			else
 				break;
 		case 'S':
 			memflags |= VM_MEM_F_WIRED;
 			break;
                 case 'm':
 			error = vm_parse_memsize(optarg, &memsize);
 			if (error)
 				errx(EX_USAGE, "invalid memsize '%s'", optarg);
 			break;
 		case 'H':
 			guest_vmexit_on_hlt = 1;
 			break;
 		case 'I':
 			/*
 			 * The "-I" option was used to add an ioapic to the
 			 * virtual machine.
 			 *
 			 * An ioapic is now provided unconditionally for each
 			 * virtual machine and this option is now deprecated.
 			 */
 			break;
 		case 'P':
 			guest_vmexit_on_pause = 1;
 			break;
 		case 'e':
 			strictio = 1;
 			break;
 		case 'u':
 			rtc_localtime = 0;
 			break;
 		case 'U':
 			guest_uuid_str = optarg;
 			break;
 		case 'w':
 			strictmsr = 0;
 			break;
 		case 'W':
 			virtio_msix = 0;
 			break;
 		case 'x':
 			x2apic_mode = 1;
 			break;
 		case 'Y':
 			mptgen = 0;
 			break;
 		case 'h':
 			usage(0);			
 		default:
 			usage(1);
 		}
 	}
 	argc -= optind;
 	argv += optind;
 
 #ifdef BHYVE_SNAPSHOT
 	if (argc > 1 || (argc == 0 && restore_file == NULL))
 		usage(1);
 
 	if (restore_file != NULL) {
 		error = load_restore_file(restore_file, &rstate);
 		if (error) {
 			fprintf(stderr, "Failed to read checkpoint info from "
 					"file: '%s'.\n", restore_file);
 			exit(1);
 		}
 	}
 
 	if (argc == 1) {
 		vmname = argv[0];
 	} else {
 		vmname = lookup_vmname(&rstate);
 		if (vmname == NULL) {
 			fprintf(stderr, "Cannot find VM name in restore file. "
 					"Please specify one.\n");
 			exit(1);
 		}
 	}
 #else
 	if (argc != 1)
 		usage(1);
 
 	vmname = argv[0];
 #endif
 	ctx = do_open(vmname);
 
 #ifdef BHYVE_SNAPSHOT
 	if (restore_file != NULL) {
 		guest_ncpus = lookup_guest_ncpus(&rstate);
 		memflags = lookup_memflags(&rstate);
 		memsize = lookup_memsize(&rstate);
 	}
 
 	if (guest_ncpus < 1) {
 		fprintf(stderr, "Invalid guest vCPUs (%d)\n", guest_ncpus);
 		exit(1);
 	}
 #endif
 
 	max_vcpus = num_vcpus_allowed(ctx);
 	if (guest_ncpus > max_vcpus) {
 		fprintf(stderr, "%d vCPUs requested but only %d available\n",
 			guest_ncpus, max_vcpus);
 		exit(4);
 	}
 
 	fbsdrun_set_capabilities(ctx, BSP);
 
 	vm_set_memflags(ctx, memflags);
 	err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
 	if (err) {
 		fprintf(stderr, "Unable to setup memory (%d)\n", errno);
 		exit(4);
 	}
 
 	error = init_msr();
 	if (error) {
 		fprintf(stderr, "init_msr error %d", error);
 		exit(4);
 	}
 
 	init_mem();
 	init_inout();
 	kernemu_dev_init();
 	init_bootrom(ctx);
 	atkbdc_init(ctx);
 	pci_irq_init(ctx);
 	ioapic_init(ctx);
 
 	rtc_init(ctx, rtc_localtime);
 	sci_init(ctx);
 
 	/*
 	 * Exit if a device emulation finds an error in its initilization
 	 */
 	if (init_pci(ctx) != 0) {
 		perror("device emulation initialization error");
 		exit(4);
 	}
 
 	/*
 	 * Initialize after PCI, to allow a bootrom file to reserve the high
 	 * region.
 	 */
 	if (acpi)
 		vmgenc_init(ctx);
 
-	if (dbg_port != 0)
-		init_dbgport(dbg_port);
-
 	if (gdb_port != 0)
 		init_gdb(ctx, gdb_port, gdb_stop);
 
-	if (bvmcons)
-		init_bvmcons();
-
 	if (lpc_bootrom()) {
 		if (vm_set_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, 1)) {
 			fprintf(stderr, "ROM boot failed: unrestricted guest "
 			    "capability not available\n");
 			exit(4);
 		}
 		error = vcpu_reset(ctx, BSP);
 		assert(error == 0);
 	}
 
 #ifdef BHYVE_SNAPSHOT
 	if (restore_file != NULL) {
 		fprintf(stdout, "Pausing pci devs...\r\n");
 		if (vm_pause_user_devs(ctx) != 0) {
 			fprintf(stderr, "Failed to pause PCI device state.\n");
 			exit(1);
 		}
 
 		fprintf(stdout, "Restoring vm mem...\r\n");
 		if (restore_vm_mem(ctx, &rstate) != 0) {
 			fprintf(stderr, "Failed to restore VM memory.\n");
 			exit(1);
 		}
 
 		fprintf(stdout, "Restoring pci devs...\r\n");
 		if (vm_restore_user_devs(ctx, &rstate) != 0) {
 			fprintf(stderr, "Failed to restore PCI device state.\n");
 			exit(1);
 		}
 
 		fprintf(stdout, "Restoring kernel structs...\r\n");
 		if (vm_restore_kern_structs(ctx, &rstate) != 0) {
 			fprintf(stderr, "Failed to restore kernel structs.\n");
 			exit(1);
 		}
 
 		fprintf(stdout, "Resuming pci devs...\r\n");
 		if (vm_resume_user_devs(ctx) != 0) {
 			fprintf(stderr, "Failed to resume PCI device state.\n");
 			exit(1);
 		}
 	}
 #endif
 
 	error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
 	assert(error == 0);
 
 	/*
 	 * build the guest tables, MP etc.
 	 */
 	if (mptgen) {
 		error = mptable_build(ctx, guest_ncpus);
 		if (error) {
 			perror("error to build the guest tables");
 			exit(4);
 		}
 	}
 
 	error = smbios_build(ctx);
 	assert(error == 0);
 
 	if (acpi) {
 		error = acpi_build(ctx, guest_ncpus);
 		assert(error == 0);
 	}
 
 	if (lpc_bootrom())
 		fwctl_init();
 
 	/*
 	 * Change the proc title to include the VM name.
 	 */
 	setproctitle("%s", vmname);
 
 #ifndef WITHOUT_CAPSICUM
 	caph_cache_catpages();
 
 	if (caph_limit_stdout() == -1 || caph_limit_stderr() == -1)
 		errx(EX_OSERR, "Unable to apply rights for sandbox");
 
 	if (caph_enter() == -1)
 		errx(EX_OSERR, "cap_enter() failed");
 #endif
 
 #ifdef BHYVE_SNAPSHOT
 	if (restore_file != NULL)
 		destroy_restore_state(&rstate);
 
 	/*
 	 * checkpointing thread for communication with bhyvectl
 	 */
 	if (init_checkpoint_thread(ctx) < 0)
 		printf("Failed to start checkpoint thread!\r\n");
 
 	if (restore_file != NULL)
 		vm_restore_time(ctx);
 #endif
 
 	/*
 	 * Add CPU 0
 	 */
 	fbsdrun_addcpu(ctx, BSP, BSP, rip);
 
 #ifdef BHYVE_SNAPSHOT
 	/*
 	 * If we restore a VM, start all vCPUs now (including APs), otherwise,
 	 * let the guest OS to spin them up later via vmexits.
 	 */
 	if (restore_file != NULL) {
 		for (vcpu = 0; vcpu < guest_ncpus; vcpu++) {
 			if (vcpu == BSP)
 				continue;
 
 			fprintf(stdout, "spinning up vcpu no %d...\r\n", vcpu);
 			spinup_vcpu(ctx, vcpu);
 		}
 	}
 #endif
 
 	/*
 	 * Head off to the main event dispatch loop
 	 */
 	mevent_dispatch();
 
 	exit(4);
 }
diff --git a/usr.sbin/bhyve/consport.c b/usr.sbin/bhyve/consport.c
deleted file mode 100644
index 634521985541..000000000000
--- a/usr.sbin/bhyve/consport.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2011 NetApp, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#ifndef WITHOUT_CAPSICUM
-#include <sys/capsicum.h>
-#endif
-#include <sys/select.h>
-
-#ifndef WITHOUT_CAPSICUM
-#include <capsicum_helpers.h>
-#endif
-#include <err.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <termios.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <sysexits.h>
-
-#include "inout.h"
-#include "pci_lpc.h"
-#include "debug.h"
-
-#define	BVM_CONSOLE_PORT	0x220
-#define	BVM_CONS_SIG		('b' << 8 | 'v')
-
-static struct termios tio_orig, tio_new;
-
-static void
-ttyclose(void)
-{
-	tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig);
-}
-
-static void
-ttyopen(void)
-{
-	tcgetattr(STDIN_FILENO, &tio_orig);
-
-	cfmakeraw(&tio_new);
-	tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);	
-	raw_stdio = 1;
-
-	atexit(ttyclose);
-}
-
-static bool
-tty_char_available(void)
-{
-	fd_set rfds;
-	struct timeval tv;
-
-	FD_ZERO(&rfds);
-	FD_SET(STDIN_FILENO, &rfds);
-	tv.tv_sec = 0;
-	tv.tv_usec = 0;
-	if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0) {
-		return (true);
-	} else {
-		return (false);
-	}
-}
-
-static int
-ttyread(void)
-{
-	char rb;
-
-	if (tty_char_available()) {
-		read(STDIN_FILENO, &rb, 1);
-		return (rb & 0xff);
-	} else {
-		return (-1);
-	}
-}
-
-static void
-ttywrite(unsigned char wb)
-{
-	(void) write(STDOUT_FILENO, &wb, 1);
-}
-
-static int
-console_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
-		uint32_t *eax, void *arg)
-{
-	static int opened;
-#ifndef WITHOUT_CAPSICUM
-	cap_rights_t rights;
-	cap_ioctl_t cmds[] = { TIOCGETA, TIOCSETA, TIOCGWINSZ };
-#endif
-
-	if (bytes == 2 && in) {
-		*eax = BVM_CONS_SIG;
-		return (0);
-	}
-
-	/*
-	 * Guests might probe this port to look for old ISA devices
-	 * using single-byte reads.  Return 0xff for those.
-	 */
-	if (bytes == 1 && in) {
-		*eax = 0xff;
-		return (0);
-	}
-
-	if (bytes != 4)
-		return (-1);
-
-	if (!opened) {
-#ifndef WITHOUT_CAPSICUM
-		cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ,
-		    CAP_WRITE);
-		if (caph_rights_limit(STDIN_FILENO, &rights) == -1)
-			errx(EX_OSERR, "Unable to apply rights for sandbox");
-		if (caph_ioctls_limit(STDIN_FILENO, cmds, nitems(cmds)) == -1)
-			errx(EX_OSERR, "Unable to apply rights for sandbox");
-#endif
-		ttyopen();
-		opened = 1;
-	}
-	
-	if (in)
-		*eax = ttyread();
-	else
-		ttywrite(*eax);
-
-	return (0);
-}
-
-SYSRES_IO(BVM_CONSOLE_PORT, 4);
-
-static struct inout_port consport = {
-	"bvmcons",
-	BVM_CONSOLE_PORT,
-	1,
-	IOPORT_F_INOUT,
-	console_handler
-};
-
-void
-init_bvmcons(void)
-{
-
-	register_inout(&consport);
-}
diff --git a/usr.sbin/bhyve/dbgport.c b/usr.sbin/bhyve/dbgport.c
deleted file mode 100644
index e0aab7e64ff2..000000000000
--- a/usr.sbin/bhyve/dbgport.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2011 NetApp, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#ifndef WITHOUT_CAPSICUM
-#include <sys/capsicum.h>
-#endif
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/uio.h>
-
-#ifndef WITHOUT_CAPSICUM
-#include <capsicum_helpers.h>
-#endif
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "inout.h"
-#include "dbgport.h"
-#include "pci_lpc.h"
-
-#define	BVM_DBG_PORT	0x224
-#define	BVM_DBG_SIG	('B' << 8 | 'V')
-
-static int listen_fd, conn_fd;
-
-static struct sockaddr_in sin;
-
-static int
-dbg_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
-	    uint32_t *eax, void *arg)
-{
-	int nwritten, nread, printonce;
-	int on = 1;
-	char ch;
-
-	if (bytes == 2 && in) {
-		*eax = BVM_DBG_SIG;
-		return (0);
-	}
-
-	if (bytes != 4)
-		return (-1);
-
-again:
-	printonce = 0;
-	while (conn_fd < 0) {
-		if (!printonce) {
-			printf("Waiting for connection from gdb\r\n");
-			printonce = 1;
-		}
-		conn_fd = accept4(listen_fd, NULL, NULL, SOCK_NONBLOCK);
-		if (conn_fd >= 0) {
-			/* Avoid EPIPE after the client drops off. */
-			(void)setsockopt(conn_fd, SOL_SOCKET, SO_NOSIGPIPE,
-			    &on, sizeof(on));
-			/* Improve latency for one byte at a time tranfers. */
-			(void)setsockopt(conn_fd, IPPROTO_TCP, TCP_NODELAY,
-			    &on, sizeof(on));
-		} else if (errno != EINTR) {
-			perror("accept");
-		}
-	}
-
-	if (in) {
-		nread = read(conn_fd, &ch, 1);
-		if (nread == -1 && errno == EAGAIN)
-			*eax = -1;
-		else if (nread == 1)
-			*eax = ch;
-		else {
-			close(conn_fd);
-			conn_fd = -1;
-			goto again;
-		}
-	} else {
-		ch = *eax;
-		nwritten = write(conn_fd, &ch, 1);
-		if (nwritten != 1) {
-			close(conn_fd);
-			conn_fd = -1;
-			goto again;
-		}
-	}
-	return (0);
-}
-
-static struct inout_port dbgport = {
-	"bvmdbg",
-	BVM_DBG_PORT,
-	1,
-	IOPORT_F_INOUT,
-	dbg_handler
-};
-
-SYSRES_IO(BVM_DBG_PORT, 4);
-
-void
-init_dbgport(int sport)
-{
-	int reuse;
-#ifndef WITHOUT_CAPSICUM
-	cap_rights_t rights;
-#endif
-
-	conn_fd = -1;
-
-	if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("cannot create socket");
-		exit(4);
-	}
-
-	sin.sin_len = sizeof(sin);
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = htonl(INADDR_ANY);
-	sin.sin_port = htons(sport);
-
-	reuse = 1;
-	if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse,
-	    sizeof(reuse)) < 0) {
-		perror("cannot set socket options");
-		exit(4);
-	}
-
-	if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-		perror("cannot bind socket");
-		exit(4);
-	}
-
-	if (listen(listen_fd, 1) < 0) {
-		perror("cannot listen socket");
-		exit(4);
-	}
-
-#ifndef WITHOUT_CAPSICUM
-	cap_rights_init(&rights, CAP_ACCEPT, CAP_READ, CAP_WRITE);
-	if (caph_rights_limit(listen_fd, &rights) == -1)
-		errx(EX_OSERR, "Unable to apply rights for sandbox");
-#endif
-
-	register_inout(&dbgport);
-}
diff --git a/usr.sbin/bhyve/dbgport.h b/usr.sbin/bhyve/dbgport.h
deleted file mode 100644
index 407ff3ffbf5f..000000000000
--- a/usr.sbin/bhyve/dbgport.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2011 NetApp, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _DBGPORT_H_
-#define	_DBGPORT_H_
-
-void	init_dbgport(int port);
-
-#endif
diff --git a/usr.sbin/bhyve/inout.h b/usr.sbin/bhyve/inout.h
index 439fef8bd2c0..45ad5f4ac654 100644
--- a/usr.sbin/bhyve/inout.h
+++ b/usr.sbin/bhyve/inout.h
@@ -1,81 +1,80 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2011 NetApp, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * $FreeBSD$
  */
 
 #ifndef _INOUT_H_
 #define	_INOUT_H_
 
 #include <sys/linker_set.h>
 
 struct vmctx;
 struct vm_exit;
 
 /*
  * inout emulation handlers return 0 on success and -1 on failure.
  */
 typedef int (*inout_func_t)(struct vmctx *ctx, int vcpu, int in, int port,
 			    int bytes, uint32_t *eax, void *arg);
 
 struct inout_port {
 	const char 	*name;
 	int		port;
 	int		size;
 	int		flags;
 	inout_func_t	handler;
 	void		*arg;
 };
 #define	IOPORT_F_IN		0x1
 #define	IOPORT_F_OUT		0x2
 #define	IOPORT_F_INOUT		(IOPORT_F_IN | IOPORT_F_OUT)
 
 /*
  * The following flags are used internally and must not be used by
  * device models.
  */
 #define	IOPORT_F_DEFAULT	0x80000000	/* claimed by default handler */
 
 #define	INOUT_PORT(name, port, flags, handler)				\
 	static struct inout_port __CONCAT(__inout_port, __LINE__) = {	\
 		#name,							\
 		(port),							\
 		1,							\
 		(flags),						\
 		(handler),						\
 		0							\
 	};								\
 	DATA_SET(inout_port_set, __CONCAT(__inout_port, __LINE__))
 	
 void	init_inout(void);
 int	emulate_inout(struct vmctx *, int vcpu, struct vm_exit *vmexit,
 		      int strict);
 int	register_inout(struct inout_port *iop);
 int	unregister_inout(struct inout_port *iop);
-void	init_bvmcons(void);
 
 #endif	/* _INOUT_H_ */
diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c
index 0ad03afd85c0..4ffdb315883c 100644
--- a/usr.sbin/bhyve/snapshot.c
+++ b/usr.sbin/bhyve/snapshot.c
@@ -1,1743 +1,1742 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2016 Flavius Anton
  * Copyright (c) 2016 Mihai Tiganus
  * Copyright (c) 2016-2019 Mihai Carabas
  * Copyright (c) 2017-2019 Darius Mihai
  * Copyright (c) 2017-2019 Elena Mihailescu
  * Copyright (c) 2018-2019 Sergiu Weisz
  * All rights reserved.
  * The bhyve-snapshot feature was developed under sponsorships
  * from Matthew Grooms.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
 #ifndef WITHOUT_CAPSICUM
 #include <sys/capsicum.h>
 #endif
 #include <sys/mman.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/un.h>
 
 #include <machine/atomic.h>
 #include <machine/segments.h>
 
 #ifndef WITHOUT_CAPSICUM
 #include <capsicum_helpers.h>
 #endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
 #include <signal.h>
 #include <unistd.h>
 #include <assert.h>
 #include <errno.h>
 #include <pthread.h>
 #include <pthread_np.h>
 #include <sysexits.h>
 #include <stdbool.h>
 #include <sys/ioctl.h>
 
 #include <machine/vmm.h>
 #ifndef WITHOUT_CAPSICUM
 #include <machine/vmm_dev.h>
 #endif
 #include <machine/vmm_snapshot.h>
 #include <vmmapi.h>
 
 #include "bhyverun.h"
 #include "acpi.h"
 #include "atkbdc.h"
 #include "inout.h"
-#include "dbgport.h"
 #include "fwctl.h"
 #include "ioapic.h"
 #include "mem.h"
 #include "mevent.h"
 #include "mptbl.h"
 #include "pci_emul.h"
 #include "pci_irq.h"
 #include "pci_lpc.h"
 #include "smbiostbl.h"
 #include "snapshot.h"
 #include "xmsr.h"
 #include "spinup_ap.h"
 #include "rtc.h"
 
 #include <libxo/xo.h>
 #include <ucl.h>
 
 struct spinner_info {
 	const size_t *crtval;
 	const size_t maxval;
 	const size_t total;
 };
 
 extern int guest_ncpus;
 
 static struct winsize winsize;
 static sig_t old_winch_handler;
 
 #define	KB		(1024UL)
 #define	MB		(1024UL * KB)
 #define	GB		(1024UL * MB)
 
 #define	SNAPSHOT_CHUNK	(4 * MB)
 #define	PROG_BUF_SZ	(8192)
 
 #define	BHYVE_RUN_DIR "/var/run/bhyve"
 #define	CHECKPOINT_RUN_DIR BHYVE_RUN_DIR "/checkpoint"
 #define	MAX_VMNAME 100
 
 #define	MAX_MSG_SIZE 1024
 
 #define	SNAPSHOT_BUFFER_SIZE (20 * MB)
 
 #define	JSON_STRUCT_ARR_KEY		"structs"
 #define	JSON_DEV_ARR_KEY		"devices"
 #define	JSON_BASIC_METADATA_KEY 	"basic metadata"
 #define	JSON_SNAPSHOT_REQ_KEY		"snapshot_req"
 #define	JSON_SIZE_KEY			"size"
 #define	JSON_FILE_OFFSET_KEY		"file_offset"
 
 #define	JSON_NCPUS_KEY			"ncpus"
 #define	JSON_VMNAME_KEY 		"vmname"
 #define	JSON_MEMSIZE_KEY		"memsize"
 #define	JSON_MEMFLAGS_KEY		"memflags"
 
 #define min(a,b)		\
 ({				\
  __typeof__ (a) _a = (a);	\
  __typeof__ (b) _b = (b); 	\
  _a < _b ? _a : _b;       	\
  })
 
 const struct vm_snapshot_dev_info snapshot_devs[] = {
 	{ "atkbdc",	atkbdc_snapshot,	NULL,		NULL		},
 	{ "virtio-net",	pci_snapshot,		pci_pause,	pci_resume	},
 	{ "virtio-blk",	pci_snapshot,		pci_pause,	pci_resume	},
 	{ "virtio-rnd",	pci_snapshot,		NULL,		NULL		},
 	{ "lpc",	pci_snapshot,		NULL,		NULL		},
 	{ "fbuf",	pci_snapshot,		NULL,		NULL		},
 	{ "xhci",	pci_snapshot,		NULL,		NULL		},
 	{ "e1000",	pci_snapshot,		NULL,		NULL		},
 	{ "ahci",	pci_snapshot,		pci_pause,	pci_resume	},
 	{ "ahci-hd",	pci_snapshot,		pci_pause,	pci_resume	},
 	{ "ahci-cd",	pci_snapshot,		pci_pause,	pci_resume	},
 };
 
 const struct vm_snapshot_kern_info snapshot_kern_structs[] = {
 	{ "vhpet",	STRUCT_VHPET	},
 	{ "vm",		STRUCT_VM	},
 	{ "vmx",	STRUCT_VMX	},
 	{ "vioapic",	STRUCT_VIOAPIC	},
 	{ "vlapic",	STRUCT_VLAPIC	},
 	{ "vmcx",	STRUCT_VMCX	},
 	{ "vatpit",	STRUCT_VATPIT	},
 	{ "vatpic",	STRUCT_VATPIC	},
 	{ "vpmtmr",	STRUCT_VPMTMR	},
 	{ "vrtc",	STRUCT_VRTC	},
 };
 
 static cpuset_t vcpus_active, vcpus_suspended;
 static pthread_mutex_t vcpu_lock;
 static pthread_cond_t vcpus_idle, vcpus_can_run;
 static bool checkpoint_active;
 
 /*
  * TODO: Harden this function and all of its callers since 'base_str' is a user
  * provided string.
  */
 static char *
 strcat_extension(const char *base_str, const char *ext)
 {
 	char *res;
 	size_t base_len, ext_len;
 
 	base_len = strnlen(base_str, MAX_VMNAME);
 	ext_len = strnlen(ext, MAX_VMNAME);
 
 	if (base_len + ext_len > MAX_VMNAME) {
 		fprintf(stderr, "Filename exceeds maximum length.\n");
 		return (NULL);
 	}
 
 	res = malloc(base_len + ext_len + 1);
 	if (res == NULL) {
 		perror("Failed to allocate memory.");
 		return (NULL);
 	}
 
 	memcpy(res, base_str, base_len);
 	memcpy(res + base_len, ext, ext_len);
 	res[base_len + ext_len] = 0;
 
 	return (res);
 }
 
 void
 destroy_restore_state(struct restore_state *rstate)
 {
 	if (rstate == NULL) {
 		fprintf(stderr, "Attempting to destroy NULL restore struct.\n");
 		return;
 	}
 
 	if (rstate->kdata_map != MAP_FAILED)
 		munmap(rstate->kdata_map, rstate->kdata_len);
 
 	if (rstate->kdata_fd > 0)
 		close(rstate->kdata_fd);
 	if (rstate->vmmem_fd > 0)
 		close(rstate->vmmem_fd);
 
 	if (rstate->meta_root_obj != NULL)
 		ucl_object_unref(rstate->meta_root_obj);
 	if (rstate->meta_parser != NULL)
 		ucl_parser_free(rstate->meta_parser);
 }
 
 static int
 load_vmmem_file(const char *filename, struct restore_state *rstate)
 {
 	struct stat sb;
 	int err;
 
 	rstate->vmmem_fd = open(filename, O_RDONLY);
 	if (rstate->vmmem_fd < 0) {
 		perror("Failed to open restore file");
 		return (-1);
 	}
 
 	err = fstat(rstate->vmmem_fd, &sb);
 	if (err < 0) {
 		perror("Failed to stat restore file");
 		goto err_load_vmmem;
 	}
 
 	if (sb.st_size == 0) {
 		fprintf(stderr, "Restore file is empty.\n");
 		goto err_load_vmmem;
 	}
 
 	rstate->vmmem_len = sb.st_size;
 
 	return (0);
 
 err_load_vmmem:
 	if (rstate->vmmem_fd > 0)
 		close(rstate->vmmem_fd);
 	return (-1);
 }
 
 static int
 load_kdata_file(const char *filename, struct restore_state *rstate)
 {
 	struct stat sb;
 	int err;
 
 	rstate->kdata_fd = open(filename, O_RDONLY);
 	if (rstate->kdata_fd < 0) {
 		perror("Failed to open kernel data file");
 		return (-1);
 	}
 
 	err = fstat(rstate->kdata_fd, &sb);
 	if (err < 0) {
 		perror("Failed to stat kernel data file");
 		goto err_load_kdata;
 	}
 
 	if (sb.st_size == 0) {
 		fprintf(stderr, "Kernel data file is empty.\n");
 		goto err_load_kdata;
 	}
 
 	rstate->kdata_len = sb.st_size;
 	rstate->kdata_map = mmap(NULL, rstate->kdata_len, PROT_READ,
 				 MAP_SHARED, rstate->kdata_fd, 0);
 	if (rstate->kdata_map == MAP_FAILED) {
 		perror("Failed to map restore file");
 		goto err_load_kdata;
 	}
 
 	return (0);
 
 err_load_kdata:
 	if (rstate->kdata_fd > 0)
 		close(rstate->kdata_fd);
 	return (-1);
 }
 
 static int
 load_metadata_file(const char *filename, struct restore_state *rstate)
 {
 	const ucl_object_t *obj;
 	struct ucl_parser *parser;
 	int err;
 
 	parser = ucl_parser_new(UCL_PARSER_DEFAULT);
 	if (parser == NULL) {
 		fprintf(stderr, "Failed to initialize UCL parser.\n");
 		goto err_load_metadata;
 	}
 
 	err = ucl_parser_add_file(parser, filename);
 	if (err == 0) {
 		fprintf(stderr, "Failed to parse metadata file: '%s'\n",
 			filename);
 		err = -1;
 		goto err_load_metadata;
 	}
 
 	obj = ucl_parser_get_object(parser);
 	if (obj == NULL) {
 		fprintf(stderr, "Failed to parse object.\n");
 		err = -1;
 		goto err_load_metadata;
 	}
 
 	rstate->meta_parser = parser;
 	rstate->meta_root_obj = (ucl_object_t *)obj;
 
 	return (0);
 
 err_load_metadata:
 	if (parser != NULL)
 		ucl_parser_free(parser);
 	return (err);
 }
 
 int
 load_restore_file(const char *filename, struct restore_state *rstate)
 {
 	int err = 0;
 	char *kdata_filename = NULL, *meta_filename = NULL;
 
 	assert(filename != NULL);
 	assert(rstate != NULL);
 
 	memset(rstate, 0, sizeof(*rstate));
 	rstate->kdata_map = MAP_FAILED;
 
 	err = load_vmmem_file(filename, rstate);
 	if (err != 0) {
 		fprintf(stderr, "Failed to load guest RAM file.\n");
 		goto err_restore;
 	}
 
 	kdata_filename = strcat_extension(filename, ".kern");
 	if (kdata_filename == NULL) {
 		fprintf(stderr, "Failed to construct kernel data filename.\n");
 		goto err_restore;
 	}
 
 	err = load_kdata_file(kdata_filename, rstate);
 	if (err != 0) {
 		fprintf(stderr, "Failed to load guest kernel data file.\n");
 		goto err_restore;
 	}
 
 	meta_filename = strcat_extension(filename, ".meta");
 	if (meta_filename == NULL) {
 		fprintf(stderr, "Failed to construct kernel metadata filename.\n");
 		goto err_restore;
 	}
 
 	err = load_metadata_file(meta_filename, rstate);
 	if (err != 0) {
 		fprintf(stderr, "Failed to load guest metadata file.\n");
 		goto err_restore;
 	}
 
 	return (0);
 
 err_restore:
 	destroy_restore_state(rstate);
 	if (kdata_filename != NULL)
 		free(kdata_filename);
 	if (meta_filename != NULL)
 		free(meta_filename);
 	return (-1);
 }
 
 #define JSON_GET_INT_OR_RETURN(key, obj, result_ptr, ret)			\
 do {										\
 	const ucl_object_t *obj__;						\
 	obj__ = ucl_object_lookup(obj, key);					\
 	if (obj__ == NULL) {							\
 		fprintf(stderr, "Missing key: '%s'", key);			\
 		return (ret);							\
 	}									\
 	if (!ucl_object_toint_safe(obj__, result_ptr)) {			\
 		fprintf(stderr, "Cannot convert '%s' value to int.", key);	\
 		return (ret);							\
 	}									\
 } while(0)
 
 #define JSON_GET_STRING_OR_RETURN(key, obj, result_ptr, ret)			\
 do {										\
 	const ucl_object_t *obj__;						\
 	obj__ = ucl_object_lookup(obj, key);					\
 	if (obj__ == NULL) {							\
 		fprintf(stderr, "Missing key: '%s'", key);			\
 		return (ret);							\
 	}									\
 	if (!ucl_object_tostring_safe(obj__, result_ptr)) {			\
 		fprintf(stderr, "Cannot convert '%s' value to string.", key);	\
 		return (ret);							\
 	}									\
 } while(0)
 
 static void *
 lookup_struct(enum snapshot_req struct_id, struct restore_state *rstate,
 	      size_t *struct_size)
 {
 	const ucl_object_t *structs = NULL, *obj = NULL;
 	ucl_object_iter_t it = NULL;
 	int64_t snapshot_req, size, file_offset;
 
 	structs = ucl_object_lookup(rstate->meta_root_obj, JSON_STRUCT_ARR_KEY);
 	if (structs == NULL) {
 		fprintf(stderr, "Failed to find '%s' object.\n",
 			JSON_STRUCT_ARR_KEY);
 		return (NULL);
 	}
 
 	if (ucl_object_type((ucl_object_t *)structs) != UCL_ARRAY) {
 		fprintf(stderr, "Object '%s' is not an array.\n",
 		JSON_STRUCT_ARR_KEY);
 		return (NULL);
 	}
 
 	while ((obj = ucl_object_iterate(structs, &it, true)) != NULL) {
 		snapshot_req = -1;
 		JSON_GET_INT_OR_RETURN(JSON_SNAPSHOT_REQ_KEY, obj,
 				       &snapshot_req, NULL);
 		assert(snapshot_req >= 0);
 		if ((enum snapshot_req) snapshot_req == struct_id) {
 			JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
 					       &size, NULL);
 			assert(size >= 0);
 
 			JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
 					       &file_offset, NULL);
 			assert(file_offset >= 0);
 			assert(file_offset + size <= rstate->kdata_len);
 
 			*struct_size = (size_t)size;
 			return (rstate->kdata_map + file_offset);
 		}
 	}
 
 	return (NULL);
 }
 
 static void *
 lookup_check_dev(const char *dev_name, struct restore_state *rstate,
 		 const ucl_object_t *obj, size_t *data_size)
 {
 	const char *snapshot_req;
 	int64_t size, file_offset;
 
 	snapshot_req = NULL;
 	JSON_GET_STRING_OR_RETURN(JSON_SNAPSHOT_REQ_KEY, obj,
 				  &snapshot_req, NULL);
 	assert(snapshot_req != NULL);
 	if (!strcmp(snapshot_req, dev_name)) {
 		JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
 				       &size, NULL);
 		assert(size >= 0);
 
 		JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
 				       &file_offset, NULL);
 		assert(file_offset >= 0);
 		assert(file_offset + size <= rstate->kdata_len);
 
 		*data_size = (size_t)size;
 		return (rstate->kdata_map + file_offset);
 	}
 
 	return (NULL);
 }
 
 static void*
 lookup_dev(const char *dev_name, struct restore_state *rstate,
 	   size_t *data_size)
 {
 	const ucl_object_t *devs = NULL, *obj = NULL;
 	ucl_object_iter_t it = NULL;
 	void *ret;
 
 	devs = ucl_object_lookup(rstate->meta_root_obj, JSON_DEV_ARR_KEY);
 	if (devs == NULL) {
 		fprintf(stderr, "Failed to find '%s' object.\n",
 			JSON_DEV_ARR_KEY);
 		return (NULL);
 	}
 
 	if (ucl_object_type((ucl_object_t *)devs) != UCL_ARRAY) {
 		fprintf(stderr, "Object '%s' is not an array.\n",
 			JSON_DEV_ARR_KEY);
 		return (NULL);
 	}
 
 	while ((obj = ucl_object_iterate(devs, &it, true)) != NULL) {
 		ret = lookup_check_dev(dev_name, rstate, obj, data_size);
 		if (ret != NULL)
 			return (ret);
 	}
 
 	return (NULL);
 }
 
 static const ucl_object_t *
 lookup_basic_metadata_object(struct restore_state *rstate)
 {
 	const ucl_object_t *basic_meta_obj = NULL;
 
 	basic_meta_obj = ucl_object_lookup(rstate->meta_root_obj,
 					   JSON_BASIC_METADATA_KEY);
 	if (basic_meta_obj == NULL) {
 		fprintf(stderr, "Failed to find '%s' object.\n",
 			JSON_BASIC_METADATA_KEY);
 		return (NULL);
 	}
 
 	if (ucl_object_type((ucl_object_t *)basic_meta_obj) != UCL_OBJECT) {
 		fprintf(stderr, "Object '%s' is not a JSON object.\n",
 		JSON_BASIC_METADATA_KEY);
 		return (NULL);
 	}
 
 	return (basic_meta_obj);
 }
 
 const char *
 lookup_vmname(struct restore_state *rstate)
 {
 	const char *vmname;
 	const ucl_object_t *obj;
 
 	obj = lookup_basic_metadata_object(rstate);
 	if (obj == NULL)
 		return (NULL);
 
 	JSON_GET_STRING_OR_RETURN(JSON_VMNAME_KEY, obj, &vmname, NULL);
 	return (vmname);
 }
 
 int
 lookup_memflags(struct restore_state *rstate)
 {
 	int64_t memflags;
 	const ucl_object_t *obj;
 
 	obj = lookup_basic_metadata_object(rstate);
 	if (obj == NULL)
 		return (0);
 
 	JSON_GET_INT_OR_RETURN(JSON_MEMFLAGS_KEY, obj, &memflags, 0);
 
 	return ((int)memflags);
 }
 
 size_t
 lookup_memsize(struct restore_state *rstate)
 {
 	int64_t memsize;
 	const ucl_object_t *obj;
 
 	obj = lookup_basic_metadata_object(rstate);
 	if (obj == NULL)
 		return (0);
 
 	JSON_GET_INT_OR_RETURN(JSON_MEMSIZE_KEY, obj, &memsize, 0);
 	if (memsize < 0)
 		memsize = 0;
 
 	return ((size_t)memsize);
 }
 
 
 int
 lookup_guest_ncpus(struct restore_state *rstate)
 {
 	int64_t ncpus;
 	const ucl_object_t *obj;
 
 	obj = lookup_basic_metadata_object(rstate);
 	if (obj == NULL)
 		return (0);
 
 	JSON_GET_INT_OR_RETURN(JSON_NCPUS_KEY, obj, &ncpus, 0);
 	return ((int)ncpus);
 }
 
 static void
 winch_handler(int signal)
 {
 #ifdef TIOCGWINSZ
 	ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
 #endif /* TIOCGWINSZ */
 }
 
 static int
 print_progress(size_t crtval, const size_t maxval)
 {
 	size_t rc;
 	double crtval_gb, maxval_gb;
 	size_t i, win_width, prog_start, prog_done, prog_end;
 	int mval_len;
 
 	static char prog_buf[PROG_BUF_SZ];
 	static const size_t len = sizeof(prog_buf);
 
 	static size_t div;
 	static char *div_str;
 
 	static char wip_bar[] = { '/', '-', '\\', '|' };
 	static int wip_idx = 0;
 
 	if (maxval == 0) {
 		printf("[0B / 0B]\r\n");
 		return (0);
 	}
 
 	if (crtval > maxval)
 		crtval = maxval;
 
 	if (maxval > 10 * GB) {
 		div = GB;
 		div_str = "GiB";
 	} else if (maxval > 10 * MB) {
 		div = MB;
 		div_str = "MiB";
 	} else {
 		div = KB;
 		div_str = "KiB";
 	}
 
 	crtval_gb = (double) crtval / div;
 	maxval_gb = (double) maxval / div;
 
 	rc = snprintf(prog_buf, len, "%.03lf", maxval_gb);
 	if (rc == len) {
 		fprintf(stderr, "Maxval too big\n");
 		return (-1);
 	}
 	mval_len = rc;
 
 	rc = snprintf(prog_buf, len, "\r[%*.03lf%s / %.03lf%s] |",
 		mval_len, crtval_gb, div_str, maxval_gb, div_str);
 
 	if (rc == len) {
 		fprintf(stderr, "Buffer too small to print progress\n");
 		return (-1);
 	}
 
 	win_width = min(winsize.ws_col, len);
 	prog_start = rc;
 
 	if (prog_start < (win_width - 2)) {
 		prog_end = win_width - prog_start - 2;
 		prog_done = prog_end * (crtval_gb / maxval_gb);
 
 		for (i = prog_start; i < prog_start + prog_done; i++)
 			prog_buf[i] = '#';
 
 		if (crtval != maxval) {
 			prog_buf[i] = wip_bar[wip_idx];
 			wip_idx = (wip_idx + 1) % sizeof(wip_bar);
 			i++;
 		} else {
 			prog_buf[i++] = '#';
 		}
 
 		for (; i < win_width - 2; i++)
 			prog_buf[i] = '_';
 
 		prog_buf[win_width - 2] = '|';
 	}
 
 	prog_buf[win_width - 1] = '\0';
 	write(STDOUT_FILENO, prog_buf, win_width);
 
 	return (0);
 }
 
 static void *
 snapshot_spinner_cb(void *arg)
 {
 	int rc;
 	size_t crtval, maxval, total;
 	struct spinner_info *si;
 	struct timespec ts;
 
 	si = arg;
 	if (si == NULL)
 		pthread_exit(NULL);
 
 	ts.tv_sec = 0;
 	ts.tv_nsec = 50 * 1000 * 1000; /* 50 ms sleep time */
 
 	do {
 		crtval = *si->crtval;
 		maxval = si->maxval;
 		total = si->total;
 
 		rc = print_progress(crtval, total);
 		if (rc < 0) {
 			fprintf(stderr, "Failed to parse progress\n");
 			break;
 		}
 
 		nanosleep(&ts, NULL);
 	} while (crtval < maxval);
 
 	pthread_exit(NULL);
 	return NULL;
 }
 
 static int
 vm_snapshot_mem_part(const int snapfd, const size_t foff, void *src,
 		     const size_t len, const size_t totalmem, const bool op_wr)
 {
 	int rc;
 	size_t part_done, todo, rem;
 	ssize_t done;
 	bool show_progress;
 	pthread_t spinner_th;
 	struct spinner_info *si;
 
 	if (lseek(snapfd, foff, SEEK_SET) < 0) {
 		perror("Failed to change file offset");
 		return (-1);
 	}
 
 	show_progress = false;
 	if (isatty(STDIN_FILENO) && (winsize.ws_col != 0))
 		show_progress = true;
 
 	part_done = foff;
 	rem = len;
 
 	if (show_progress) {
 		si = &(struct spinner_info) {
 			.crtval = &part_done,
 			.maxval = foff + len,
 			.total = totalmem
 		};
 
 		rc = pthread_create(&spinner_th, 0, snapshot_spinner_cb, si);
 		if (rc) {
 			perror("Unable to create spinner thread");
 			show_progress = false;
 		}
 	}
 
 	while (rem > 0) {
 		if (show_progress)
 			todo = min(SNAPSHOT_CHUNK, rem);
 		else
 			todo = rem;
 
 		if (op_wr)
 			done = write(snapfd, src, todo);
 		else
 			done = read(snapfd, src, todo);
 		if (done < 0) {
 			perror("Failed to write in file");
 			return (-1);
 		}
 
 		src += done;
 		part_done += done;
 		rem -= done;
 	}
 
 	if (show_progress) {
 		rc = pthread_join(spinner_th, NULL);
 		if (rc)
 			perror("Unable to end spinner thread");
 	}
 
 	return (0);
 }
 
 static size_t
 vm_snapshot_mem(struct vmctx *ctx, int snapfd, size_t memsz, const bool op_wr)
 {
 	int ret;
 	size_t lowmem, highmem, totalmem;
 	char *baseaddr;
 
 	ret = vm_get_guestmem_from_ctx(ctx, &baseaddr, &lowmem, &highmem);
 	if (ret) {
 		fprintf(stderr, "%s: unable to retrieve guest memory size\r\n",
 			__func__);
 		return (0);
 	}
 	totalmem = lowmem + highmem;
 
 	if ((op_wr == false) && (totalmem != memsz)) {
 		fprintf(stderr, "%s: mem size mismatch: %ld vs %ld\r\n",
 			__func__, totalmem, memsz);
 		return (0);
 	}
 
 	winsize.ws_col = 80;
 #ifdef TIOCGWINSZ
 	ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
 #endif /* TIOCGWINSZ */
 	old_winch_handler = signal(SIGWINCH, winch_handler);
 
 	ret = vm_snapshot_mem_part(snapfd, 0, baseaddr, lowmem,
 		totalmem, op_wr);
 	if (ret) {
 		fprintf(stderr, "%s: Could not %s lowmem\r\n",
 			__func__, op_wr ? "write" : "read");
 		totalmem = 0;
 		goto done;
 	}
 
 	if (highmem == 0)
 		goto done;
 
 	ret = vm_snapshot_mem_part(snapfd, lowmem, baseaddr + 4*GB,
 		highmem, totalmem, op_wr);
 	if (ret) {
 		fprintf(stderr, "%s: Could not %s highmem\r\n",
 		        __func__, op_wr ? "write" : "read");
 		totalmem = 0;
 		goto done;
 	}
 
 done:
 	printf("\r\n");
 	signal(SIGWINCH, old_winch_handler);
 
 	return (totalmem);
 }
 
 int
 restore_vm_mem(struct vmctx *ctx, struct restore_state *rstate)
 {
 	size_t restored;
 
 	restored = vm_snapshot_mem(ctx, rstate->vmmem_fd, rstate->vmmem_len,
 				   false);
 
 	if (restored != rstate->vmmem_len)
 		return (-1);
 
 	return (0);
 }
 
 static int
 vm_restore_kern_struct(struct vmctx *ctx, struct restore_state *rstate,
 		       const struct vm_snapshot_kern_info *info)
 {
 	void *struct_ptr;
 	size_t struct_size;
 	int ret;
 	struct vm_snapshot_meta *meta;
 
 	struct_ptr = lookup_struct(info->req, rstate, &struct_size);
 	if (struct_ptr == NULL) {
 		fprintf(stderr, "%s: Failed to lookup struct %s\r\n",
 			__func__, info->struct_name);
 		ret = -1;
 		goto done;
 	}
 
 	if (struct_size == 0) {
 		fprintf(stderr, "%s: Kernel struct size was 0 for: %s\r\n",
 			__func__, info->struct_name);
 		ret = -1;
 		goto done;
 	}
 
 	meta = &(struct vm_snapshot_meta) {
 		.ctx = ctx,
 		.dev_name = info->struct_name,
 		.dev_req  = info->req,
 
 		.buffer.buf_start = struct_ptr,
 		.buffer.buf_size = struct_size,
 
 		.buffer.buf = struct_ptr,
 		.buffer.buf_rem = struct_size,
 
 		.op = VM_SNAPSHOT_RESTORE,
 	};
 
 	ret = vm_snapshot_req(meta);
 	if (ret != 0) {
 		fprintf(stderr, "%s: Failed to restore struct: %s\r\n",
 			__func__, info->struct_name);
 		goto done;
 	}
 
 done:
 	return (ret);
 }
 
 int
 vm_restore_kern_structs(struct vmctx *ctx, struct restore_state *rstate)
 {
 	int ret;
 	int i;
 
 	for (i = 0; i < nitems(snapshot_kern_structs); i++) {
 		ret = vm_restore_kern_struct(ctx, rstate,
 					     &snapshot_kern_structs[i]);
 		if (ret != 0)
 			return (ret);
 	}
 
 	return (0);
 }
 
 int
 vm_restore_user_dev(struct vmctx *ctx, struct restore_state *rstate,
 		    const struct vm_snapshot_dev_info *info)
 {
 	void *dev_ptr;
 	size_t dev_size;
 	int ret;
 	struct vm_snapshot_meta *meta;
 
 	dev_ptr = lookup_dev(info->dev_name, rstate, &dev_size);
 	if (dev_ptr == NULL) {
 		fprintf(stderr, "Failed to lookup dev: %s\r\n", info->dev_name);
 		fprintf(stderr, "Continuing the restore/migration process\r\n");
 		return (0);
 	}
 
 	if (dev_size == 0) {
 		fprintf(stderr, "%s: Device size is 0. "
 			"Assuming %s is not used\r\n",
 			__func__, info->dev_name);
 		return (0);
 	}
 
 	meta = &(struct vm_snapshot_meta) {
 		.ctx = ctx,
 		.dev_name = info->dev_name,
 
 		.buffer.buf_start = dev_ptr,
 		.buffer.buf_size = dev_size,
 
 		.buffer.buf = dev_ptr,
 		.buffer.buf_rem = dev_size,
 
 		.op = VM_SNAPSHOT_RESTORE,
 	};
 
 	ret = (*info->snapshot_cb)(meta);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to restore dev: %s\r\n",
 			info->dev_name);
 		return (-1);
 	}
 
 	return (0);
 }
 
 
 int
 vm_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate)
 {
 	int ret;
 	int i;
 
 	for (i = 0; i < nitems(snapshot_devs); i++) {
 		ret = vm_restore_user_dev(ctx, rstate, &snapshot_devs[i]);
 		if (ret != 0)
 			return (ret);
 	}
 
 	return 0;
 }
 
 int
 vm_pause_user_devs(struct vmctx *ctx)
 {
 	const struct vm_snapshot_dev_info *info;
 	int ret;
 	int i;
 
 	for (i = 0; i < nitems(snapshot_devs); i++) {
 		info = &snapshot_devs[i];
 		if (info->pause_cb == NULL)
 			continue;
 
 		ret = info->pause_cb(ctx, info->dev_name);
 		if (ret != 0)
 			return (ret);
 	}
 
 	return (0);
 }
 
 int
 vm_resume_user_devs(struct vmctx *ctx)
 {
 	const struct vm_snapshot_dev_info *info;
 	int ret;
 	int i;
 
 	for (i = 0; i < nitems(snapshot_devs); i++) {
 		info = &snapshot_devs[i];
 		if (info->resume_cb == NULL)
 			continue;
 
 		ret = info->resume_cb(ctx, info->dev_name);
 		if (ret != 0)
 			return (ret);
 	}
 
 	return (0);
 }
 
 static int
 vm_snapshot_kern_struct(int data_fd, xo_handle_t *xop, const char *array_key,
 			struct vm_snapshot_meta *meta, off_t *offset)
 {
 	int ret;
 	size_t data_size;
 	ssize_t write_cnt;
 
 	ret = vm_snapshot_req(meta);
 	if (ret != 0) {
 		fprintf(stderr, "%s: Failed to snapshot struct %s\r\n",
 			__func__, meta->dev_name);
 		ret = -1;
 		goto done;
 	}
 
 	data_size = vm_get_snapshot_size(meta);
 
 	write_cnt = write(data_fd, meta->buffer.buf_start, data_size);
 	if (write_cnt != data_size) {
 		perror("Failed to write all snapshotted data.");
 		ret = -1;
 		goto done;
 	}
 
 	/* Write metadata. */
 	xo_open_instance_h(xop, array_key);
 	xo_emit_h(xop, "{:debug_name/%s}\n", meta->dev_name);
 	xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%d}\n",
 		  meta->dev_req);
 	xo_emit_h(xop, "{:" JSON_SIZE_KEY "/%lu}\n", data_size);
 	xo_emit_h(xop, "{:" JSON_FILE_OFFSET_KEY "/%lu}\n", *offset);
 	xo_close_instance_h(xop, JSON_STRUCT_ARR_KEY);
 
 	*offset += data_size;
 
 done:
 	return (ret);
 }
 
 static int
 vm_snapshot_kern_structs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
 {
 	int ret, i, error;
 	size_t offset, buf_size;
 	char *buffer;
 	struct vm_snapshot_meta *meta;
 
 	error = 0;
 	offset = 0;
 	buf_size = SNAPSHOT_BUFFER_SIZE;
 
 	buffer = malloc(SNAPSHOT_BUFFER_SIZE * sizeof(char));
 	if (buffer == NULL) {
 		error = ENOMEM;
 		perror("Failed to allocate memory for snapshot buffer");
 		goto err_vm_snapshot_kern_data;
 	}
 
 	meta = &(struct vm_snapshot_meta) {
 		.ctx = ctx,
 
 		.buffer.buf_start = buffer,
 		.buffer.buf_size = buf_size,
 
 		.op = VM_SNAPSHOT_SAVE,
 	};
 
 	xo_open_list_h(xop, JSON_STRUCT_ARR_KEY);
 	for (i = 0; i < nitems(snapshot_kern_structs); i++) {
 		meta->dev_name = snapshot_kern_structs[i].struct_name;
 		meta->dev_req  = snapshot_kern_structs[i].req;
 
 		memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
 		meta->buffer.buf = meta->buffer.buf_start;
 		meta->buffer.buf_rem = meta->buffer.buf_size;
 
 		ret = vm_snapshot_kern_struct(data_fd, xop, JSON_DEV_ARR_KEY,
 					      meta, &offset);
 		if (ret != 0) {
 			error = -1;
 			goto err_vm_snapshot_kern_data;
 		}
 	}
 	xo_close_list_h(xop, JSON_STRUCT_ARR_KEY);
 
 err_vm_snapshot_kern_data:
 	if (buffer != NULL)
 		free(buffer);
 	return (error);
 }
 
 static int
 vm_snapshot_basic_metadata(struct vmctx *ctx, xo_handle_t *xop, size_t memsz)
 {
 	int error;
 	int memflags;
 	char vmname_buf[MAX_VMNAME];
 
 	memset(vmname_buf, 0, MAX_VMNAME);
 	error = vm_get_name(ctx, vmname_buf, MAX_VMNAME - 1);
 	if (error != 0) {
 		perror("Failed to get VM name");
 		goto err;
 	}
 
 	memflags = vm_get_memflags(ctx);
 
 	xo_open_container_h(xop, JSON_BASIC_METADATA_KEY);
 	xo_emit_h(xop, "{:" JSON_NCPUS_KEY "/%ld}\n", guest_ncpus);
 	xo_emit_h(xop, "{:" JSON_VMNAME_KEY "/%s}\n", vmname_buf);
 	xo_emit_h(xop, "{:" JSON_MEMSIZE_KEY "/%lu}\n", memsz);
 	xo_emit_h(xop, "{:" JSON_MEMFLAGS_KEY "/%d}\n", memflags);
 	xo_close_container_h(xop, JSON_BASIC_METADATA_KEY);
 
 err:
 	return (error);
 }
 
 static int
 vm_snapshot_dev_write_data(int data_fd, xo_handle_t *xop, const char *array_key,
 			   struct vm_snapshot_meta *meta, off_t *offset)
 {
 	int ret;
 	size_t data_size;
 
 	data_size = vm_get_snapshot_size(meta);
 
 	ret = write(data_fd, meta->buffer.buf_start, data_size);
 	if (ret != data_size) {
 		perror("Failed to write all snapshotted data.");
 		return (-1);
 	}
 
 	/* Write metadata. */
 	xo_open_instance_h(xop, array_key);
 	xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%s}\n", meta->dev_name);
 	xo_emit_h(xop, "{:" JSON_SIZE_KEY "/%lu}\n", data_size);
 	xo_emit_h(xop, "{:" JSON_FILE_OFFSET_KEY "/%lu}\n", *offset);
 	xo_close_instance_h(xop, array_key);
 
 	*offset += data_size;
 
 	return (0);
 }
 
 static int
 vm_snapshot_user_dev(const struct vm_snapshot_dev_info *info,
 		     int data_fd, xo_handle_t *xop,
 		     struct vm_snapshot_meta *meta, off_t *offset)
 {
 	int ret;
 
 	ret = (*info->snapshot_cb)(meta);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to snapshot %s; ret=%d\r\n",
 			meta->dev_name, ret);
 		return (ret);
 	}
 
 	ret = vm_snapshot_dev_write_data(data_fd, xop, JSON_DEV_ARR_KEY, meta,
 					 offset);
 	if (ret != 0)
 		return (ret);
 
 	return (0);
 }
 
 static int
 vm_snapshot_user_devs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
 {
 	int ret, i;
 	off_t offset;
 	void *buffer;
 	size_t buf_size;
 	struct vm_snapshot_meta *meta;
 
 	buf_size = SNAPSHOT_BUFFER_SIZE;
 
 	offset = lseek(data_fd, 0, SEEK_CUR);
 	if (offset < 0) {
 		perror("Failed to get data file current offset.");
 		return (-1);
 	}
 
 	buffer = malloc(buf_size);
 	if (buffer == NULL) {
 		perror("Failed to allocate memory for snapshot buffer");
 		ret = ENOSPC;
 		goto snapshot_err;
 	}
 
 	meta = &(struct vm_snapshot_meta) {
 		.ctx = ctx,
 
 		.buffer.buf_start = buffer,
 		.buffer.buf_size = buf_size,
 
 		.op = VM_SNAPSHOT_SAVE,
 	};
 
 	xo_open_list_h(xop, JSON_DEV_ARR_KEY);
 
 	/* Restore other devices that support this feature */
 	for (i = 0; i < nitems(snapshot_devs); i++) {
 		meta->dev_name = snapshot_devs[i].dev_name;
 
 		memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
 		meta->buffer.buf = meta->buffer.buf_start;
 		meta->buffer.buf_rem = meta->buffer.buf_size;
 
 		ret = vm_snapshot_user_dev(&snapshot_devs[i], data_fd, xop,
 					   meta, &offset);
 		if (ret != 0)
 			goto snapshot_err;
 	}
 
 	xo_close_list_h(xop, JSON_DEV_ARR_KEY);
 
 snapshot_err:
 	if (buffer != NULL)
 		free(buffer);
 	return (ret);
 }
 
 void
 checkpoint_cpu_add(int vcpu)
 {
 
 	pthread_mutex_lock(&vcpu_lock);
 	CPU_SET(vcpu, &vcpus_active);
 
 	if (checkpoint_active) {
 		CPU_SET(vcpu, &vcpus_suspended);
 		while (checkpoint_active)
 			pthread_cond_wait(&vcpus_can_run, &vcpu_lock);
 		CPU_CLR(vcpu, &vcpus_suspended);
 	}
 	pthread_mutex_unlock(&vcpu_lock);
 }
 
 /*
  * When a vCPU is suspended for any reason, it calls
  * checkpoint_cpu_suspend().  This records that the vCPU is idle.
  * Before returning from suspension, checkpoint_cpu_resume() is
  * called.  In suspend we note that the vCPU is idle.  In resume we
  * pause the vCPU thread until the checkpoint is complete.  The reason
  * for the two-step process is that vCPUs might already be stopped in
  * the debug server when a checkpoint is requested.  This approach
  * allows us to account for and handle those vCPUs.
  */
 void
 checkpoint_cpu_suspend(int vcpu)
 {
 
 	pthread_mutex_lock(&vcpu_lock);
 	CPU_SET(vcpu, &vcpus_suspended);
 	if (checkpoint_active && CPU_CMP(&vcpus_active, &vcpus_suspended) == 0)
 		pthread_cond_signal(&vcpus_idle);
 	pthread_mutex_unlock(&vcpu_lock);
 }
 
 void
 checkpoint_cpu_resume(int vcpu)
 {
 
 	pthread_mutex_lock(&vcpu_lock);
 	while (checkpoint_active)
 		pthread_cond_wait(&vcpus_can_run, &vcpu_lock);
 	CPU_CLR(vcpu, &vcpus_suspended);
 	pthread_mutex_unlock(&vcpu_lock);
 }
 
 static void
 vm_vcpu_pause(struct vmctx *ctx)
 {
 
 	pthread_mutex_lock(&vcpu_lock);
 	checkpoint_active = true;
 	vm_suspend_cpu(ctx, -1);
 	while (CPU_CMP(&vcpus_active, &vcpus_suspended) != 0)
 		pthread_cond_wait(&vcpus_idle, &vcpu_lock);
 	pthread_mutex_unlock(&vcpu_lock);
 }
 
 static void
 vm_vcpu_resume(struct vmctx *ctx)
 {
 
 	pthread_mutex_lock(&vcpu_lock);
 	checkpoint_active = false;
 	pthread_mutex_unlock(&vcpu_lock);
 	vm_resume_cpu(ctx, -1);
 	pthread_cond_broadcast(&vcpus_can_run);
 }
 
 static int
 vm_checkpoint(struct vmctx *ctx, char *checkpoint_file, bool stop_vm)
 {
 	int fd_checkpoint = 0, kdata_fd = 0;
 	int ret = 0;
 	int error = 0;
 	size_t memsz;
 	xo_handle_t *xop = NULL;
 	char *meta_filename = NULL;
 	char *kdata_filename = NULL;
 	FILE *meta_file = NULL;
 
 	kdata_filename = strcat_extension(checkpoint_file, ".kern");
 	if (kdata_filename == NULL) {
 		fprintf(stderr, "Failed to construct kernel data filename.\n");
 		return (-1);
 	}
 
 	kdata_fd = open(kdata_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700);
 	if (kdata_fd < 0) {
 		perror("Failed to open kernel data snapshot file.");
 		error = -1;
 		goto done;
 	}
 
 	fd_checkpoint = open(checkpoint_file, O_RDWR | O_CREAT | O_TRUNC, 0700);
 
 	if (fd_checkpoint < 0) {
 		perror("Failed to create checkpoint file");
 		error = -1;
 		goto done;
 	}
 
 	meta_filename = strcat_extension(checkpoint_file, ".meta");
 	if (meta_filename == NULL) {
 		fprintf(stderr, "Failed to construct vm metadata filename.\n");
 		goto done;
 	}
 
 	meta_file = fopen(meta_filename, "w");
 	if (meta_file == NULL) {
 		perror("Failed to open vm metadata snapshot file.");
 		goto done;
 	}
 
 	xop = xo_create_to_file(meta_file, XO_STYLE_JSON, XOF_PRETTY);
 	if (xop == NULL) {
 		perror("Failed to get libxo handle on metadata file.");
 		goto done;
 	}
 
 	vm_vcpu_pause(ctx);
 
 	ret = vm_pause_user_devs(ctx);
 	if (ret != 0) {
 		fprintf(stderr, "Could not pause devices\r\n");
 		error = ret;
 		goto done;
 	}
 
 	memsz = vm_snapshot_mem(ctx, fd_checkpoint, 0, true);
 	if (memsz == 0) {
 		perror("Could not write guest memory to file");
 		error = -1;
 		goto done;
 	}
 
 	ret = vm_snapshot_basic_metadata(ctx, xop, memsz);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to snapshot vm basic metadata.\n");
 		error = -1;
 		goto done;
 	}
 
 
 	ret = vm_snapshot_kern_structs(ctx, kdata_fd, xop);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to snapshot vm kernel data.\n");
 		error = -1;
 		goto done;
 	}
 
 	ret = vm_snapshot_user_devs(ctx, kdata_fd, xop);
 	if (ret != 0) {
 		fprintf(stderr, "Failed to snapshot device state.\n");
 		error = -1;
 		goto done;
 	}
 
 	xo_finish_h(xop);
 
 	if (stop_vm) {
 		vm_destroy(ctx);
 		exit(0);
 	}
 
 done:
 	ret = vm_resume_user_devs(ctx);
 	if (ret != 0)
 		fprintf(stderr, "Could not resume devices\r\n");
 	vm_vcpu_resume(ctx);
 	if (fd_checkpoint > 0)
 		close(fd_checkpoint);
 	if (meta_filename != NULL)
 		free(meta_filename);
 	if (kdata_filename != NULL)
 		free(kdata_filename);
 	if (xop != NULL)
 		xo_destroy(xop);
 	if (meta_file != NULL)
 		fclose(meta_file);
 	if (kdata_fd > 0)
 		close(kdata_fd);
 	return (error);
 }
 
 int
 get_checkpoint_msg(int conn_fd, struct vmctx *ctx)
 {
 	unsigned char buf[MAX_MSG_SIZE];
 	struct checkpoint_op *checkpoint_op;
 	int len, recv_len, total_recv = 0;
 	int err = 0;
 
 	len = sizeof(struct checkpoint_op); /* expected length */
 	while ((recv_len = recv(conn_fd, buf + total_recv, len - total_recv, 0)) > 0) {
 		total_recv += recv_len;
 	}
 	if (recv_len < 0) {
 		perror("Error while receiving data from bhyvectl");
 		err = -1;
 		goto done;
 	}
 
 	checkpoint_op = (struct checkpoint_op *)buf;
 	switch (checkpoint_op->op) {
 		case START_CHECKPOINT:
 			err = vm_checkpoint(ctx, checkpoint_op->snapshot_filename, false);
 			break;
 		case START_SUSPEND:
 			err = vm_checkpoint(ctx, checkpoint_op->snapshot_filename, true);
 			break;
 		default:
 			fprintf(stderr, "Unrecognized checkpoint operation.\n");
 			err = -1;
 	}
 
 done:
 	close(conn_fd);
 	return (err);
 }
 
 /*
  * Listen for commands from bhyvectl
  */
 void *
 checkpoint_thread(void *param)
 {
 	struct checkpoint_thread_info *thread_info;
 	int conn_fd, ret;
 
 	pthread_set_name_np(pthread_self(), "checkpoint thread");
 	thread_info = (struct checkpoint_thread_info *)param;
 
 	while ((conn_fd = accept(thread_info->socket_fd, NULL, NULL)) > -1) {
 		ret = get_checkpoint_msg(conn_fd, thread_info->ctx);
 		if (ret != 0) {
 			fprintf(stderr, "Failed to read message on checkpoint "
 					"socket. Retrying.\n");
 		}
 	}
 	if (conn_fd < -1) {
 		perror("Failed to accept connection");
 	}
 
 	return (NULL);
 }
 
 /*
  * Create directory tree to store runtime specific information:
  * i.e. UNIX sockets for IPC with bhyvectl.
  */
 static int
 make_checkpoint_dir(void)
 {
 	int err;
 
 	err = mkdir(BHYVE_RUN_DIR, 0755);
 	if (err < 0 && errno != EEXIST)
 		return (err);
 
 	err = mkdir(CHECKPOINT_RUN_DIR, 0755);
 	if (err < 0 && errno != EEXIST)
 		return (err);
 
 	return 0;
 }
 
 /*
  * Create the listening socket for IPC with bhyvectl
  */
 int
 init_checkpoint_thread(struct vmctx *ctx)
 {
 	struct checkpoint_thread_info *checkpoint_info = NULL;
 	struct sockaddr_un addr;
 	int socket_fd;
 	pthread_t checkpoint_pthread;
 	char vmname_buf[MAX_VMNAME];
 	int ret, err = 0;
 
 	memset(&addr, 0, sizeof(addr));
 
 	err = pthread_mutex_init(&vcpu_lock, NULL);
 	if (err != 0)
 		errc(1, err, "checkpoint mutex init");
 	err = pthread_cond_init(&vcpus_idle, NULL);
 	if (err == 0)
 		err = pthread_cond_init(&vcpus_can_run, NULL);
 	if (err != 0)
 		errc(1, err, "checkpoint cv init");
 
 	socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
 	if (socket_fd < 0) {
 		perror("Socket creation failed (IPC with bhyvectl");
 		err = -1;
 		goto fail;
 	}
 
 	err = make_checkpoint_dir();
 	if (err < 0) {
 		perror("Failed to create checkpoint runtime directory");
 		goto fail;
 	}
 
 	addr.sun_family = AF_UNIX;
 
 	err = vm_get_name(ctx, vmname_buf, MAX_VMNAME - 1);
 	if (err != 0) {
 		perror("Failed to get VM name");
 		goto fail;
 	}
 
 	snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s",
 		 CHECKPOINT_RUN_DIR, vmname_buf);
 	addr.sun_len = SUN_LEN(&addr);
 	unlink(addr.sun_path);
 
 	if (bind(socket_fd, (struct sockaddr *)&addr, addr.sun_len) != 0) {
 		perror("Failed to bind socket (IPC with bhyvectl)");
 		err = -1;
 		goto fail;
 	}
 
 	if (listen(socket_fd, 10) < 0) {
 		perror("Failed to listen on socket (IPC with bhyvectl)");
 		err = -1;
 		goto fail;
 	}
 
 	checkpoint_info = calloc(1, sizeof(*checkpoint_info));
 	checkpoint_info->ctx = ctx;
 	checkpoint_info->socket_fd = socket_fd;
 
 	ret = pthread_create(&checkpoint_pthread, NULL, checkpoint_thread,
 		checkpoint_info);
 	if (ret < 0) {
 		err = ret;
 		goto fail;
 	}
 
 	return (0);
 fail:
 	free(checkpoint_info);
 	if (socket_fd > 0)
 		close(socket_fd);
 	unlink(addr.sun_path);
 
 	return (err);
 }
 
 void
 vm_snapshot_buf_err(const char *bufname, const enum vm_snapshot_op op)
 {
 	const char *__op;
 
 	if (op == VM_SNAPSHOT_SAVE)
 		__op = "save";
 	else if (op == VM_SNAPSHOT_RESTORE)
 		__op = "restore";
 	else
 		__op = "unknown";
 
 	fprintf(stderr, "%s: snapshot-%s failed for %s\r\n",
 		__func__, __op, bufname);
 }
 
 int
 vm_snapshot_buf(volatile void *data, size_t data_size,
 		struct vm_snapshot_meta *meta)
 {
 	struct vm_snapshot_buffer *buffer;
 	int op;
 
 	buffer = &meta->buffer;
 	op = meta->op;
 
 	if (buffer->buf_rem < data_size) {
 		fprintf(stderr, "%s: buffer too small\r\n", __func__);
 		return (E2BIG);
 	}
 
 	if (op == VM_SNAPSHOT_SAVE)
 		memcpy(buffer->buf, (uint8_t *) data, data_size);
 	else if (op == VM_SNAPSHOT_RESTORE)
 		memcpy((uint8_t *) data, buffer->buf, data_size);
 	else
 		return (EINVAL);
 
 	buffer->buf += data_size;
 	buffer->buf_rem -= data_size;
 
 	return (0);
 }
 
 size_t
 vm_get_snapshot_size(struct vm_snapshot_meta *meta)
 {
 	size_t length;
 	struct vm_snapshot_buffer *buffer;
 
 	buffer = &meta->buffer;
 
 	if (buffer->buf_size < buffer->buf_rem) {
 		fprintf(stderr, "%s: Invalid buffer: size = %zu, rem = %zu\r\n",
 			__func__, buffer->buf_size, buffer->buf_rem);
 		length = 0;
 	} else {
 		length = buffer->buf_size - buffer->buf_rem;
 	}
 
 	return (length);
 }
 
 int
 vm_snapshot_guest2host_addr(void **addrp, size_t len, bool restore_null,
 			    struct vm_snapshot_meta *meta)
 {
 	int ret;
 	vm_paddr_t gaddr;
 
 	if (meta->op == VM_SNAPSHOT_SAVE) {
 		gaddr = paddr_host2guest(meta->ctx, *addrp);
 		if (gaddr == (vm_paddr_t) -1) {
 			if (!restore_null ||
 			    (restore_null && (*addrp != NULL))) {
 				ret = EFAULT;
 				goto done;
 			}
 		}
 
 		SNAPSHOT_VAR_OR_LEAVE(gaddr, meta, ret, done);
 	} else if (meta->op == VM_SNAPSHOT_RESTORE) {
 		SNAPSHOT_VAR_OR_LEAVE(gaddr, meta, ret, done);
 		if (gaddr == (vm_paddr_t) -1) {
 			if (!restore_null) {
 				ret = EFAULT;
 				goto done;
 			}
 		}
 
 		*addrp = paddr_guest2host(meta->ctx, gaddr, len);
 	} else {
 		ret = EINVAL;
 	}
 
 done:
 	return (ret);
 }
 
 int
 vm_snapshot_buf_cmp(volatile void *data, size_t data_size,
 		    struct vm_snapshot_meta *meta)
 {
 	struct vm_snapshot_buffer *buffer;
 	int op;
 	int ret;
 
 	buffer = &meta->buffer;
 	op = meta->op;
 
 	if (buffer->buf_rem < data_size) {
 		fprintf(stderr, "%s: buffer too small\r\n", __func__);
 		ret = E2BIG;
 		goto done;
 	}
 
 	if (op == VM_SNAPSHOT_SAVE) {
 		ret = 0;
 		memcpy(buffer->buf, (uint8_t *) data, data_size);
 	} else if (op == VM_SNAPSHOT_RESTORE) {
 		ret = memcmp((uint8_t *) data, buffer->buf, data_size);
 	} else {
 		ret = EINVAL;
 		goto done;
 	}
 
 	buffer->buf += data_size;
 	buffer->buf_rem -= data_size;
 
 done:
 	return (ret);
 }