summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/bhyve/bhyverun.c15
-rwxr-xr-xusr/src/cmd/smbsrv/fksmbd/Run.sh2
-rw-r--r--usr/src/cmd/zpool/zpool_main.c77
-rw-r--r--usr/src/common/zfs/zprop_common.c6
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c131
-rw-r--r--usr/src/lib/smhba/common/SMHBAAPILIB.c2
-rw-r--r--usr/src/pkg/manifests/system-bhyve-tests.p5m1
-rw-r--r--usr/src/test/bhyve-tests/runfiles/default.run3
-rw-r--r--usr/src/test/bhyve-tests/tests/common/in_guest.c28
-rw-r--r--usr/src/test/bhyve-tests/tests/common/payload_common.h1
-rw-r--r--usr/src/test/bhyve-tests/tests/inst_emul/Makefile6
-rw-r--r--usr/src/test/bhyve-tests/tests/inst_emul/exit_paging.c79
-rw-r--r--usr/src/test/bhyve-tests/tests/inst_emul/payload_exit_paging.s30
-rw-r--r--usr/src/test/bhyve-tests/tests/vmm/interface_version.c22
-rw-r--r--usr/src/uts/intel/io/vmm/vmm.c21
-rw-r--r--usr/src/uts/intel/io/vmm/vmm_sol_dev.c12
16 files changed, 378 insertions, 58 deletions
diff --git a/usr/src/cmd/bhyve/bhyverun.c b/usr/src/cmd/bhyve/bhyverun.c
index fb64e059fc..304bd5ab11 100644
--- a/usr/src/cmd/bhyve/bhyverun.c
+++ b/usr/src/cmd/bhyve/bhyverun.c
@@ -39,7 +39,7 @@
*
* Copyright 2015 Pluribus Networks Inc.
* Copyright 2018 Joyent, Inc.
- * Copyright 2021 Oxide Computer Company
+ * Copyright 2022 Oxide Computer Company
* Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
*/
@@ -840,6 +840,18 @@ vmexit_run_state(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
fprintf(stderr, "unexpected run-state VM exit");
return (VMEXIT_ABORT);
}
+
+static int
+vmexit_paging(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+ fprintf(stderr, "vm exit[%d]\n", *pvcpu);
+ fprintf(stderr, "\treason\t\tPAGING\n");
+ fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
+ fprintf(stderr, "\tgpa\t\t0x%016lx\n", vmexit->u.paging.gpa);
+ fprintf(stderr, "\tfault_type\t\t%d\n", vmexit->u.paging.fault_type);
+
+ return (VMEXIT_ABORT);
+}
#endif /* __FreeBSD__ */
#ifdef __FreeBSD__
@@ -1113,6 +1125,7 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
[VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
#else
[VM_EXITCODE_RUN_STATE] = vmexit_run_state,
+ [VM_EXITCODE_PAGING] = vmexit_paging,
#endif
[VM_EXITCODE_SUSPENDED] = vmexit_suspend,
[VM_EXITCODE_TASK_SWITCH] = vmexit_task_switch,
diff --git a/usr/src/cmd/smbsrv/fksmbd/Run.sh b/usr/src/cmd/smbsrv/fksmbd/Run.sh
index fb76e791e6..32ec31c08f 100755
--- a/usr/src/cmd/smbsrv/fksmbd/Run.sh
+++ b/usr/src/cmd/smbsrv/fksmbd/Run.sh
@@ -56,7 +56,7 @@ LD_LIBRARY_PATH=$ROOT/usr/lib/smbsrv:$ROOT/usr/lib:$ROOT/lib
export LD_LIBRARY_PATH
# Enable everything, for debugging
-export SMB_MAX_PROTOCOL=300
+export SMB_MAX_PROTOCOL=311
export SMB_SIGNING=require
# normally runs with cwd=/ but this is more careful
diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c
index 5eb4eacc46..612f03540a 100644
--- a/usr/src/cmd/zpool/zpool_main.c
+++ b/usr/src/cmd/zpool/zpool_main.c
@@ -5151,8 +5151,8 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
}
static void
-print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
- boolean_t valid, enum zfs_nicenum_format format)
+print_one_column(zpool_prop_t prop, uint64_t value, const char *str,
+ boolean_t scripted, boolean_t valid, enum zfs_nicenum_format format)
{
char propval[64];
boolean_t fixed;
@@ -5161,6 +5161,7 @@ print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
switch (prop) {
case ZPOOL_PROP_EXPANDSZ:
case ZPOOL_PROP_CHECKPOINT:
+ case ZPOOL_PROP_DEDUPRATIO:
if (value == 0)
(void) strlcpy(propval, "-", sizeof (propval));
else
@@ -5188,6 +5189,10 @@ print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
value < 1000 ? "%1.2f%%" : value < 10000 ?
"%2.1f%%" : "%3.0f%%", value / 100.0);
break;
+ case ZPOOL_PROP_HEALTH:
+ width = 8;
+ (void) strlcpy(propval, str, sizeof (propval));
+ break;
default:
zfs_nicenum_format(value, propval, sizeof (propval), format);
}
@@ -5206,7 +5211,7 @@ print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
*/
void
print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
- list_cbdata_t *cb, int depth)
+ list_cbdata_t *cb, int depth, boolean_t isspare)
{
nvlist_t **child;
vdev_stat_t *vs;
@@ -5214,7 +5219,8 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
char *vname;
boolean_t scripted = cb->cb_scripted;
uint64_t islog = B_FALSE;
- char *dashes = "%-*s - - - - - -\n";
+ char *dashes = " %-*s - - - - "
+ "- - - - -\n";
verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) == 0);
@@ -5223,6 +5229,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
boolean_t toplevel = (vs->vs_space != 0);
uint64_t cap;
enum zfs_nicenum_format format;
+ const char *state;
if (cb->cb_literal)
format = ZFS_NICENUM_RAW;
@@ -5246,24 +5253,35 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
* 'toplevel' boolean value is passed to the print_one_column()
* to indicate that the value is valid.
*/
- print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
- toplevel, format);
- print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
+ print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, NULL, scripted,
toplevel, format);
- print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
+ print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, NULL,
scripted, toplevel, format);
+ print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
+ NULL, scripted, toplevel, format);
print_one_column(ZPOOL_PROP_CHECKPOINT,
- vs->vs_checkpoint_space, scripted, toplevel, format);
- print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
- B_TRUE, format);
+ vs->vs_checkpoint_space, NULL, scripted, toplevel, format);
+ print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, NULL,
+ scripted, B_TRUE, format);
print_one_column(ZPOOL_PROP_FRAGMENTATION,
- vs->vs_fragmentation, scripted,
+ vs->vs_fragmentation, NULL, scripted,
(vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel),
format);
cap = (vs->vs_space == 0) ? 0 :
(vs->vs_alloc * 10000 / vs->vs_space);
- print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel,
- format);
+ print_one_column(ZPOOL_PROP_CAPACITY, cap, NULL,
+ scripted, toplevel, format);
+ print_one_column(ZPOOL_PROP_DEDUPRATIO, 0, NULL,
+ scripted, toplevel, format);
+ state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
+ if (isspare) {
+ if (vs->vs_aux == VDEV_AUX_SPARED)
+ state = "INUSE";
+ else if (vs->vs_state == VDEV_STATE_HEALTHY)
+ state = "AVAIL";
+ }
+ print_one_column(ZPOOL_PROP_HEALTH, 0, state, scripted,
+ B_TRUE, format);
(void) printf("\n");
}
@@ -5288,7 +5306,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
vname = zpool_vdev_name(g_zfs, zhp, child[c],
cb->cb_name_flags);
- print_list_stats(zhp, vname, child[c], cb, depth + 2);
+ print_list_stats(zhp, vname, child[c], cb, depth + 1, B_FALSE);
free(vname);
}
@@ -5315,38 +5333,38 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
continue;
if (!printed) {
- /* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth,
class_name[n]);
printed = B_TRUE;
}
vname = zpool_vdev_name(g_zfs, zhp, child[c],
cb->cb_name_flags);
- print_list_stats(zhp, vname, child[c], cb, depth + 2);
+ print_list_stats(zhp, vname, child[c], cb, depth + 2,
+ B_FALSE);
free(vname);
}
}
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
&child, &children) == 0 && children > 0) {
- /* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth, "cache");
for (c = 0; c < children; c++) {
vname = zpool_vdev_name(g_zfs, zhp, child[c],
cb->cb_name_flags);
- print_list_stats(zhp, vname, child[c], cb, depth + 2);
+ print_list_stats(zhp, vname, child[c], cb, depth + 2,
+ B_FALSE);
free(vname);
}
}
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
&children) == 0 && children > 0) {
- /* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth, "spare");
for (c = 0; c < children; c++) {
vname = zpool_vdev_name(g_zfs, zhp, child[c],
cb->cb_name_flags);
- print_list_stats(zhp, vname, child[c], cb, depth + 2);
+ print_list_stats(zhp, vname, child[c], cb, depth + 2,
+ B_TRUE);
free(vname);
}
}
@@ -5359,27 +5377,18 @@ int
list_callback(zpool_handle_t *zhp, void *data)
{
list_cbdata_t *cbp = data;
- nvlist_t *config;
- nvlist_t *nvroot;
- config = zpool_get_config(zhp, NULL);
+ print_pool(zhp, cbp);
if (cbp->cb_verbose) {
- config = zpool_get_config(zhp, NULL);
+ nvlist_t *config, *nvroot;
+ config = zpool_get_config(zhp, NULL);
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvroot) == 0);
+ print_list_stats(zhp, NULL, nvroot, cbp, 0, B_FALSE);
}
- if (cbp->cb_verbose)
- cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
- cbp->cb_name_flags);
-
- print_pool(zhp, cbp);
-
- if (cbp->cb_verbose)
- print_list_stats(zhp, NULL, nvroot, cbp, 0);
-
return (0);
}
diff --git a/usr/src/common/zfs/zprop_common.c b/usr/src/common/zfs/zprop_common.c
index 03919f0e91..5517782337 100644
--- a/usr/src/common/zfs/zprop_common.c
+++ b/usr/src/common/zfs/zprop_common.c
@@ -410,6 +410,12 @@ zprop_width(int prop, boolean_t *fixed, zfs_type_t type)
*/
if (prop == ZFS_PROP_CREATION)
*fixed = B_FALSE;
+ /*
+ * 'health' is handled specially because it's a number
+ * internally, but displayed as a fixed 8 character string.
+ */
+ if (prop == ZPOOL_PROP_HEALTH)
+ ret = 8;
break;
case PROP_TYPE_INDEX:
idx = prop_tbl[prop].pd_table;
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c
index 5abb8535c3..a792dcca21 100644
--- a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c
@@ -10,28 +10,149 @@
*/
/*
- * Copyright 2020 RackTop Systems, Inc.
+ * Copyright 2021 RackTop Systems, Inc.
*/
-#include <smbsrv/smb_ktypes.h>
-#include <smbsrv/mbuf.h>
+#include <stdlib.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_kcrypt.h>
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
/*
- * not implemented yet
+ * SMB 3.1.1 Preauth Integrity
+ */
+static int
+getmech_sha512(smb_crypto_mech_t *mech)
+{
+ ulong_t mid = CKM_SHA512;
+ CK_SESSION_HANDLE hdl;
+ CK_RV rv;
+
+ rv = SUNW_C_GetMechSession(mid, &hdl);
+ if (rv != CKR_OK) {
+ cmn_err(CE_NOTE, "PKCS#11: no mech 0x%x",
+ (unsigned int)mid);
+ return (-1);
+ }
+ (void) C_CloseSession(hdl);
+
+ mech->mechanism = mid;
+ mech->pParameter = NULL;
+ mech->ulParameterLen = 0;
+ return (0);
+}
+
+/*
+ * (called from smb2_negotiate_common)
*/
void
smb31_preauth_init_mech(smb_session_t *s)
{
+ smb_crypto_mech_t *mech;
+ int rc;
+
+ ASSERT3S(s->dialect, >=, SMB_VERS_3_11);
+
+ if (s->preauth_mech != NULL)
+ return;
+
+ mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
+ rc = getmech_sha512(mech);
+ if (rc != 0) {
+ kmem_free(mech, sizeof (*mech));
+ return;
+ }
+ s->preauth_mech = mech;
}
void
smb31_preauth_fini(smb_session_t *s)
{
+ smb_crypto_mech_t *mech;
+
+ if ((mech = s->preauth_mech) != NULL) {
+ kmem_free(mech, sizeof (*mech));
+ s->preauth_mech = NULL;
+ }
+}
+
+/*
+ * Start the KCF session, load the key
+ */
+int
+smb_sha512_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech)
+{
+ CK_RV rv;
+
+ rv = SUNW_C_GetMechSession(mech->mechanism, ctxp);
+ if (rv != CKR_OK)
+ return (-1);
+
+ rv = C_DigestInit(*ctxp, mech);
+
+ return (rv == CKR_OK ? 0 : -1);
+}
+
+/*
+ * Digest one segment
+ */
+int
+smb_sha512_update(smb_sign_ctx_t ctx, void *buf, size_t len)
+{
+ CK_RV rv;
+
+ rv = C_DigestUpdate(ctx, buf, len);
+ if (rv != CKR_OK)
+ (void) C_CloseSession(ctx);
+
+ return (rv == CKR_OK ? 0 : -1);
+}
+
+/*
+ * Get the final digest.
+ */
+int
+smb_sha512_final(smb_sign_ctx_t ctx, uint8_t *digest)
+{
+ CK_ULONG len = SHA512_DIGEST_LENGTH;
+ CK_RV rv;
+
+ rv = C_DigestFinal(ctx, digest, &len);
+ (void) C_CloseSession(ctx);
+
+ return (rv == CKR_OK ? 0 : -1);
}
int
smb31_preauth_sha512_calc(smb_request_t *sr, struct mbuf_chain *mbc,
uint8_t *in_hashval, uint8_t *out_hashval)
{
- return (0);
+ smb_session_t *s = sr->session;
+ smb_sign_ctx_t ctx = 0;
+ struct mbuf *mbuf = mbc->chain;
+ int rc;
+
+ ASSERT3U(s->smb31_preauth_hashid, !=, 0);
+
+ if (s->preauth_mech == NULL)
+ return (-1);
+
+ if ((rc = smb_sha512_init(&ctx, s->preauth_mech)) != 0)
+ return (rc);
+
+ /* Digest current hashval */
+ rc = smb_sha512_update(ctx, in_hashval, SHA512_DIGEST_LENGTH);
+ if (rc != 0)
+ return (rc);
+
+ while (mbuf != NULL) {
+ rc = smb_sha512_update(ctx, mbuf->m_data, mbuf->m_len);
+ if (rc != 0)
+ return (rc);
+ mbuf = mbuf->m_next;
+ }
+
+ rc = smb_sha512_final(ctx, out_hashval);
+ return (rc);
}
diff --git a/usr/src/lib/smhba/common/SMHBAAPILIB.c b/usr/src/lib/smhba/common/SMHBAAPILIB.c
index 50f8e71c7f..86bb63f43c 100644
--- a/usr/src/lib/smhba/common/SMHBAAPILIB.c
+++ b/usr/src/lib/smhba/common/SMHBAAPILIB.c
@@ -946,6 +946,7 @@ HBA_LoadLibrary()
if (lib_infop == NULL) {
(void) fprintf(stderr, "HBA_LoadLibrary: out of memeory\n");
RELEASE_MUTEX(&_hbaapi_LL_mutex);
+ fclose(hbaconf);
return (HBA_STATUS_ERROR);
}
lib_infop->status = HBA_LIBRARY_NOT_LOADED;
@@ -1085,6 +1086,7 @@ HBA_LoadLibrary()
/* successfully loaded library */
lib_infop->status = HBA_LIBRARY_LOADED;
}
+ fclose(hbaconf);
#endif /* WIN32 or UNIX */
#ifdef POSIX_THREADS
/*
diff --git a/usr/src/pkg/manifests/system-bhyve-tests.p5m b/usr/src/pkg/manifests/system-bhyve-tests.p5m
index 992b75c231..65bdca9781 100644
--- a/usr/src/pkg/manifests/system-bhyve-tests.p5m
+++ b/usr/src/pkg/manifests/system-bhyve-tests.p5m
@@ -32,6 +32,7 @@ file path=opt/bhyve-tests/runfiles/default.run mode=0444
dir path=opt/bhyve-tests/tests
dir path=opt/bhyve-tests/tests/inst_emul
file path=opt/bhyve-tests/tests/inst_emul/cpuid mode=0555
+file path=opt/bhyve-tests/tests/inst_emul/exit_paging mode=0555
file path=opt/bhyve-tests/tests/inst_emul/rdmsr mode=0555
file path=opt/bhyve-tests/tests/inst_emul/triple_fault mode=0555
file path=opt/bhyve-tests/tests/inst_emul/wrmsr mode=0555
diff --git a/usr/src/test/bhyve-tests/runfiles/default.run b/usr/src/test/bhyve-tests/runfiles/default.run
index 9f95ed7299..e31690b520 100644
--- a/usr/src/test/bhyve-tests/runfiles/default.run
+++ b/usr/src/test/bhyve-tests/runfiles/default.run
@@ -57,7 +57,8 @@ tests = [
'cpuid',
'rdmsr',
'wrmsr',
- 'triple_fault'
+ 'triple_fault',
+ 'exit_paging'
]
[/opt/bhyve-tests/tests/viona]
diff --git a/usr/src/test/bhyve-tests/tests/common/in_guest.c b/usr/src/test/bhyve-tests/tests/common/in_guest.c
index dbd6bdf22a..7d27cf194d 100644
--- a/usr/src/test/bhyve-tests/tests/common/in_guest.c
+++ b/usr/src/test/bhyve-tests/tests/common/in_guest.c
@@ -27,6 +27,7 @@
#include <sys/sysmacros.h>
#include <sys/varargs.h>
#include <sys/debug.h>
+#include <sys/mman.h>
#include <sys/vmm.h>
#include <sys/vmm_dev.h>
@@ -61,6 +62,28 @@
static struct vmctx *test_vmctx = NULL;
static const char *test_name = NULL;
+static int
+setup_rom(struct vmctx *ctx)
+{
+ const size_t seg_sz = 0x1000;
+ const uintptr_t seg_addr = MEM_LOC_ROM;
+ const int fd = vm_get_device_fd(ctx);
+ int err;
+
+ struct vm_memseg memseg = {
+ .segid = VM_BOOTROM,
+ .len = 0x1000,
+ };
+ (void) strlcpy(memseg.name, "testrom", sizeof (memseg.name));
+ err = ioctl(fd, VM_ALLOC_MEMSEG, &memseg);
+ if (err != 0) {
+ return (err);
+ }
+ err = vm_mmap_memseg(ctx, seg_addr, VM_BOOTROM, 0, seg_sz,
+ PROT_READ | PROT_EXEC);
+ return (err);
+}
+
static void
populate_identity_table(struct vmctx *ctx)
{
@@ -313,6 +336,11 @@ test_initialize(const char *tname)
test_fail_errno(err, "Could not set up VM memory");
}
+ err = setup_rom(ctx);
+ if (err != 0) {
+ test_fail_errno(err, "Could not set up VM ROM segment");
+ }
+
populate_identity_table(ctx);
populate_desc_tables(ctx);
diff --git a/usr/src/test/bhyve-tests/tests/common/payload_common.h b/usr/src/test/bhyve-tests/tests/common/payload_common.h
index 4141cec219..826927f884 100644
--- a/usr/src/test/bhyve-tests/tests/common/payload_common.h
+++ b/usr/src/test/bhyve-tests/tests/common/payload_common.h
@@ -27,6 +27,7 @@
#define MEM_LOC_IDT 0x207000
#define MEM_LOC_STACK 0x400000
#define MEM_LOC_PAYLOAD 0x800000
+#define MEM_LOC_ROM 0xffff000
/* IO port set aside for emitting test result */
#define IOP_TEST_RESULT 0xef00U
diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/Makefile b/usr/src/test/bhyve-tests/tests/inst_emul/Makefile
index 7a7844d65c..023a416ae9 100644
--- a/usr/src/test/bhyve-tests/tests/inst_emul/Makefile
+++ b/usr/src/test/bhyve-tests/tests/inst_emul/Makefile
@@ -17,9 +17,13 @@ include $(SRC)/test/Makefile.com
PROG = rdmsr \
wrmsr \
- triple_fault \
cpuid
+# These should probably go in the `vmm` tests, but since they depend on
+# in-guest payloads, it is easier to build them here.
+PROG += triple_fault \
+ exit_paging
+
# C-based payloads need additional utils object
CPAYLOADS = cpuid
diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/exit_paging.c b/usr/src/test/bhyve-tests/tests/inst_emul/exit_paging.c
new file mode 100644
index 0000000000..8b0ce84e41
--- /dev/null
+++ b/usr/src/test/bhyve-tests/tests/inst_emul/exit_paging.c
@@ -0,0 +1,79 @@
+/*
+ * 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 2022 Oxide Computer Company
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <libgen.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/debug.h>
+#include <sys/mman.h>
+#include <sys/vmm.h>
+#include <sys/vmm_dev.h>
+#include <vmmapi.h>
+
+#include "in_guest.h"
+
+int
+main(int argc, char *argv[])
+{
+ const char *test_suite_name = basename(argv[0]);
+ struct vmctx *ctx = NULL;
+ int err;
+
+ ctx = test_initialize(test_suite_name);
+
+ err = test_setup_vcpu(ctx, 0, MEM_LOC_PAYLOAD, MEM_LOC_STACK);
+ if (err != 0) {
+ test_fail_errno(err, "Could not initialize vcpu0");
+ }
+
+ struct vm_entry ventry = { 0 };
+ struct vm_exit vexit = { 0 };
+
+ const uintptr_t expected_gpa = MEM_LOC_ROM;
+ const int expected_ftype = PROT_WRITE;
+
+ do {
+ const enum vm_exit_kind kind =
+ test_run_vcpu(ctx, 0, &ventry, &vexit);
+ switch (kind) {
+ case VEK_REENTR:
+ break;
+ case VEK_UNHANDLED:
+ if (vexit.exitcode != VM_EXITCODE_PAGING) {
+ test_fail_vmexit(&vexit);
+ }
+ if (vexit.u.paging.gpa != expected_gpa) {
+ test_fail_msg("gpa %08x != %08x\n",
+ vexit.u.paging.gpa, expected_gpa);
+ }
+ if (vexit.u.paging.fault_type != expected_ftype) {
+ test_fail_msg("fault_type %x != %x\n",
+ vexit.u.paging.fault_type, expected_ftype);
+ }
+ test_pass();
+ break;
+
+ default:
+ test_fail_vmexit(&vexit);
+ break;
+ }
+ } while (true);
+}
diff --git a/usr/src/test/bhyve-tests/tests/inst_emul/payload_exit_paging.s b/usr/src/test/bhyve-tests/tests/inst_emul/payload_exit_paging.s
new file mode 100644
index 0000000000..836f6b62cd
--- /dev/null
+++ b/usr/src/test/bhyve-tests/tests/inst_emul/payload_exit_paging.s
@@ -0,0 +1,30 @@
+/*
+ * 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 2022 Oxide Computer Company
+ */
+
+#include <sys/asm_linkage.h>
+#include "payload_common.h"
+
+
+ENTRY(start)
+ /* Attempt to write to ROM, which should result in paging exit */
+ xorl %eax, %eax
+ movq %rax, MEM_LOC_ROM
+
+ /* This should not be reached */
+ movw $IOP_TEST_RESULT, %dx
+ movb $TEST_RESULT_FAIL, %al
+ outb (%dx)
+ hlt
+SET_SIZE(start)
diff --git a/usr/src/test/bhyve-tests/tests/vmm/interface_version.c b/usr/src/test/bhyve-tests/tests/vmm/interface_version.c
index b3de2f4f4f..58ef314e2c 100644
--- a/usr/src/test/bhyve-tests/tests/vmm/interface_version.c
+++ b/usr/src/test/bhyve-tests/tests/vmm/interface_version.c
@@ -18,9 +18,13 @@
#include <stdlib.h>
#include <fcntl.h>
#include <libgen.h>
+#include <err.h>
#include <sys/vmm.h>
#include <sys/vmm_dev.h>
+#include <vmmapi.h>
+
+#include "common.h"
int
main(int argc, char *argv[])
@@ -41,8 +45,24 @@ main(int argc, char *argv[])
version, VMM_CURRENT_INTERFACE_VERSION);
return (EXIT_FAILURE);
}
-
(void) close(ctl_fd);
+
+ /* Query the version via an instance fd as well */
+ struct vmctx *ctx = create_test_vm(suite_name);
+ if (ctx == NULL) {
+ err(EXIT_FAILURE, "could not open test VM");
+ }
+ version = ioctl(vm_get_device_fd(ctx), VMM_INTERFACE_VERSION, 0);
+ if (version < 0) {
+ err(EXIT_FAILURE,
+ "VMM_INTERFACE_VERSION ioctl failed on vmm fd");
+ }
+ if (version != VMM_CURRENT_INTERFACE_VERSION) {
+ errx(EXIT_FAILURE, "kernel version %d != expected %d",
+ version, VMM_CURRENT_INTERFACE_VERSION);
+ }
+ vm_destroy(ctx);
+
(void) printf("%s\tPASS\n", suite_name);
return (0);
}
diff --git a/usr/src/uts/intel/io/vmm/vmm.c b/usr/src/uts/intel/io/vmm/vmm.c
index e28c235b4c..6f85f13be6 100644
--- a/usr/src/uts/intel/io/vmm/vmm.c
+++ b/usr/src/uts/intel/io/vmm/vmm.c
@@ -1516,20 +1516,19 @@ vm_handle_paging(struct vm *vm, int vcpuid)
struct vcpu *vcpu = &vm->vcpu[vcpuid];
vm_client_t *vmc = vcpu->vmclient;
struct vm_exit *vme = &vcpu->exitinfo;
- int rv, ftype;
+ const int ftype = vme->u.paging.fault_type;
- KASSERT(vme->inst_length == 0, ("%s: invalid inst_length %d",
- __func__, vme->inst_length));
+ ASSERT0(vme->inst_length);
+ ASSERT(ftype == PROT_READ || ftype == PROT_WRITE || ftype == PROT_EXEC);
- ftype = vme->u.paging.fault_type;
- KASSERT(ftype == PROT_READ ||
- ftype == PROT_WRITE || ftype == PROT_EXEC,
- ("vm_handle_paging: invalid fault_type %d", ftype));
-
- rv = vmc_fault(vmc, vme->u.paging.gpa, ftype);
+ if (vmc_fault(vmc, vme->u.paging.gpa, ftype) != 0) {
+ /*
+ * If the fault cannot be serviced, kick it out to userspace for
+ * handling (or more likely, halting the instance).
+ */
+ return (-1);
+ }
- if (rv != 0)
- return (EFAULT);
return (0);
}
diff --git a/usr/src/uts/intel/io/vmm/vmm_sol_dev.c b/usr/src/uts/intel/io/vmm/vmm_sol_dev.c
index 26b58dff79..882d22b435 100644
--- a/usr/src/uts/intel/io/vmm/vmm_sol_dev.c
+++ b/usr/src/uts/intel/io/vmm/vmm_sol_dev.c
@@ -2935,9 +2935,6 @@ vmm_ctl_ioctl(int cmd, intptr_t arg, int md, cred_t *cr, int *rvalp)
}
case VMM_VM_SUPPORTED:
return (vmm_is_supported(arg));
- case VMM_INTERFACE_VERSION:
- *rvalp = VMM_CURRENT_INTERFACE_VERSION;
- return (0);
case VMM_CHECK_IOMMU:
if (!vmm_check_iommu()) {
return (ENXIO);
@@ -2974,6 +2971,15 @@ vmm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
return (ENOTSUP);
}
+ /*
+ * Regardless of minor (vmmctl or instance), we respond to queries of
+ * the interface version.
+ */
+ if (cmd == VMM_INTERFACE_VERSION) {
+ *rvalp = VMM_CURRENT_INTERFACE_VERSION;
+ return (0);
+ }
+
minor = getminor(dev);
if (minor == VMM_CTL_MINOR) {