summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2018-02-12 17:08:40 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2018-03-07 15:52:37 +0000
commitd895d9b0600a1c4955ffc6aa3a34a22c69154b43 (patch)
tree59af0cc2968c02c1fd4c841c722355349284480e
parent7570433cf8265bc05b2f886601908b42eaff28c0 (diff)
downloadillumos-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--manifest1
-rw-r--r--usr/src/lib/brand/bhyve/zone/Makefile7
-rw-r--r--usr/src/lib/brand/bhyve/zone/bhhwcompat.c71
-rw-r--r--usr/src/uts/i86pc/io/vmm/intel/vmx.c93
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c23
-rw-r--r--usr/src/uts/i86pc/sys/vmm_dev.h1
6 files changed, 195 insertions, 1 deletions
diff --git a/manifest b/manifest
index ba9cd9bf8b..553c82f6b5 100644
--- a/manifest
+++ b/manifest
@@ -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"