diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-02-12 17:08:40 +0000 |
---|---|---|
committer | Patrick Mooney <pmooney@pfmooney.com> | 2018-03-07 15:52:37 +0000 |
commit | d895d9b0600a1c4955ffc6aa3a34a22c69154b43 (patch) | |
tree | 59af0cc2968c02c1fd4c841c722355349284480e | |
parent | 7570433cf8265bc05b2f886601908b42eaff28c0 (diff) | |
download | illumos-joyent-d895d9b0600a1c4955ffc6aa3a34a22c69154b43.tar.gz |
OS-6675 need tool to detect bhyve support
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Mike Gerdts <mike.gerdts@joyent.com>
Approved by: John Levon <john.levon@joyent.com>
-rw-r--r-- | manifest | 1 | ||||
-rw-r--r-- | usr/src/lib/brand/bhyve/zone/Makefile | 7 | ||||
-rw-r--r-- | usr/src/lib/brand/bhyve/zone/bhhwcompat.c | 71 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/intel/vmx.c | 93 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c | 23 | ||||
-rw-r--r-- | usr/src/uts/i86pc/sys/vmm_dev.h | 1 |
6 files changed, 195 insertions, 1 deletions
@@ -5094,6 +5094,7 @@ f usr/lib/autofs/automountd 0555 root bin d usr/lib/brand 0755 root bin d usr/lib/brand/bhyve 0555 root sys f usr/lib/brand/bhyve/attach 0555 root sys +f usr/lib/brand/bhyve/bhhwcompat 0555 root sys f usr/lib/brand/bhyve/boot 0555 root sys f usr/lib/brand/bhyve/detach 0555 root sys f usr/lib/brand/bhyve/uninstall 0555 root sys diff --git a/usr/src/lib/brand/bhyve/zone/Makefile b/usr/src/lib/brand/bhyve/zone/Makefile index 8e9586f525..f778fda27a 100644 --- a/usr/src/lib/brand/bhyve/zone/Makefile +++ b/usr/src/lib/brand/bhyve/zone/Makefile @@ -18,9 +18,14 @@ include $(SRC)/cmd/Makefile.cmd.64 PROGS = attach detach statechange uninstall PROG1 = boot -PROGS += $(PROG1) +PROG2 = bhhwcompat +PROGS += $(PROG1) $(PROG2) CLEANFILES += $(PROGS) + $(PROG1) := LDLIBS += -lnvpair +$(PROG2) := CPPFLAGS = -I$(COMPAT)/freebsd -I$(CONTRIB)/freebsd \ + $(CPPFLAGS.master) -I$(SRC)/uts/i86pc \ + -I$(COMPAT)/freebsd/amd64 -I$(CONTRIB)/freebsd/amd64 TEMPLATES = SYSbhyve.xml XMLDOCS = config.xml platform.xml diff --git a/usr/src/lib/brand/bhyve/zone/bhhwcompat.c b/usr/src/lib/brand/bhyve/zone/bhhwcompat.c new file mode 100644 index 0000000000..8d8d10cf96 --- /dev/null +++ b/usr/src/lib/brand/bhyve/zone/bhhwcompat.c @@ -0,0 +1,71 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2018, Joyent, Inc. + */ + +/* + * Exit 0 if the current hardware is bhyve-compatible, non-zero otherwise. + * A '-v' option can be used to print the incompatibility reason provided by + * the kernel. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> + +#include <sys/param.h> +#include <sys/cpuset.h> +#include <sys/vmm.h> +#include <sys/vmm_dev.h> + +static void +usage() +{ + fprintf(stderr, "bhhwcompat [-v]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int fd, c; + char emsg[128]; + boolean_t verbose = B_FALSE; + + while ((c = getopt(argc, argv, "v")) != -1) { + switch (c) { + case 'v': + verbose = B_TRUE; + break; + default: + usage(); + } + } + + if ((fd = open(VMM_CTL_DEV, O_RDONLY | O_EXCL)) < 0) { + if (verbose) + fprintf(stderr, "missing %s\n", VMM_CTL_DEV); + exit(1); + } + + emsg[0] = '\0'; + if (ioctl(fd, VMM_VM_SUPPORTED, emsg) < 0) { + if (verbose) + fprintf(stderr, "%s\n", emsg); + exit(1); + } + + (void) close(fd); + return (0); +} diff --git a/usr/src/uts/i86pc/io/vmm/intel/vmx.c b/usr/src/uts/i86pc/io/vmm/intel/vmx.c index c1810b8ed9..3aa1d473d6 100644 --- a/usr/src/uts/i86pc/io/vmm/intel/vmx.c +++ b/usr/src/uts/i86pc/io/vmm/intel/vmx.c @@ -3634,3 +3634,96 @@ struct vmm_ops vmm_ops_intel = { vmx_vlapic_init, vmx_vlapic_cleanup, }; + +#ifndef __FreeBSD__ +/* Side-effect free HW validation derived from checks in vmx_init. */ +int +vmx_x86_supported(char **msg) +{ + int error; + uint64_t basic, feature_control; + uint32_t tmp; + + if (!is_x86_feature(x86_featureset, X86FSET_VMX)) { + *msg = "processor does not support VMX operation"; + return (ENXIO); + } + + /* + * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits + * are set (bits 0 and 2 respectively). + */ + feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL); + if ((feature_control & IA32_FEATURE_CONTROL_LOCK) == 1 && + (feature_control & IA32_FEATURE_CONTROL_VMX_EN) == 0) { + *msg = "VMX operation disabled by BIOS"; + return (ENXIO); + } + + /* + * Verify capabilities MSR_VMX_BASIC: + * - bit 54 indicates support for INS/OUTS decoding + */ + basic = rdmsr(MSR_VMX_BASIC); + if ((basic & (1UL << 54)) == 0) { + *msg = "processor does not support desired basic capabilities"; + return (EINVAL); + } + + /* Check support for primary processor-based VM-execution controls */ + error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS, + MSR_VMX_TRUE_PROCBASED_CTLS, PROCBASED_CTLS_ONE_SETTING, + PROCBASED_CTLS_ZERO_SETTING, &tmp); + if (error) { + *msg = "processor does not support desired primary " + "processor-based controls"; + return (error); + } + + /* Check support for secondary processor-based VM-execution controls */ + error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, + MSR_VMX_PROCBASED_CTLS2, PROCBASED_CTLS2_ONE_SETTING, + PROCBASED_CTLS2_ZERO_SETTING, &tmp); + if (error) { + *msg = "processor does not support desired secondary " + "processor-based controls"; + return (error); + } + + /* Check support for pin-based VM-execution controls */ + error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS, + MSR_VMX_TRUE_PINBASED_CTLS, PINBASED_CTLS_ONE_SETTING, + PINBASED_CTLS_ZERO_SETTING, &tmp); + if (error) { + *msg = "processor does not support desired pin-based controls"; + return (error); + } + + /* Check support for VM-exit controls */ + error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS, MSR_VMX_TRUE_EXIT_CTLS, + VM_EXIT_CTLS_ONE_SETTING, VM_EXIT_CTLS_ZERO_SETTING, &tmp); + if (error) { + *msg = "processor does not support desired exit controls"; + return (error); + } + + /* Check support for VM-entry controls */ + error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS, MSR_VMX_TRUE_ENTRY_CTLS, + VM_ENTRY_CTLS_ONE_SETTING, VM_ENTRY_CTLS_ZERO_SETTING, &tmp); + if (error) { + *msg = "processor does not support desired entry controls"; + return (error); + } + + /* Unrestricted guest is nominally optional, but not for us. */ + error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, MSR_VMX_PROCBASED_CTLS2, + PROCBASED2_UNRESTRICTED_GUEST, 0, &tmp); + if (error) { + *msg = "processor does not support desired unrestricted guest " + "controls"; + return (error); + } + + return (0); +} +#endif diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c index f83ee78c31..977987589f 100644 --- a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c +++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c @@ -45,6 +45,7 @@ #include "io/vhpet.h" #include "vmm_lapic.h" #include "vmm_stat.h" +#include "vmm_util.h" #include "vm/vm_glue.h" /* @@ -73,6 +74,9 @@ static const char *vmmdev_hvm_name = "bhyve"; #define VMM_SDEV_ROOT "/dev/vmm" static sdev_plugin_hdl_t vmm_sdev_hdl; +/* From uts/i86pc/io/vmm/intel/vmx.c */ +extern int vmx_x86_supported(char **); + /* * vmm trace ring */ @@ -1680,6 +1684,23 @@ vmm_close(dev_t dev, int flag, int otyp, cred_t *credp) } static int +vmm_is_supported(intptr_t arg) +{ + int r; + char *msg; + + if (!vmm_is_intel()) + return (ENXIO); + + r = vmx_x86_supported(&msg); + if (r != 0 && arg != NULL) { + if (copyoutstr(msg, (char *)arg, strlen(msg), NULL) != 0) + return (EFAULT); + } + return (r); +} + +static int vmm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { @@ -1713,6 +1734,8 @@ vmm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, if ((mode & FWRITE) == 0) return (EPERM); return (vmmdev_do_vm_destroy(name, credp)); + case VMM_VM_SUPPORTED: + return (vmm_is_supported(arg)); default: /* No other actions are legal on ctl device */ return (ENOTTY); diff --git a/usr/src/uts/i86pc/sys/vmm_dev.h b/usr/src/uts/i86pc/sys/vmm_dev.h index d2c77b77c2..d9cb23ece9 100644 --- a/usr/src/uts/i86pc/sys/vmm_dev.h +++ b/usr/src/uts/i86pc/sys/vmm_dev.h @@ -467,6 +467,7 @@ enum { #define VMM_IOC_BASE (('V' << 16) | ('M' << 8)) #define VMM_CREATE_VM (VMM_IOC_BASE | 0x01) #define VMM_DESTROY_VM (VMM_IOC_BASE | 0x02) +#define VMM_VM_SUPPORTED (VMM_IOC_BASE | 0x03) #define VMM_CTL_DEV "/dev/vmmctl" |