diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/bhyve/bhyverun.c | 15 | ||||
-rwxr-xr-x | usr/src/cmd/smbsrv/fksmbd/Run.sh | 2 | ||||
-rw-r--r-- | usr/src/cmd/zpool/zpool_main.c | 77 | ||||
-rw-r--r-- | usr/src/common/zfs/zprop_common.c | 6 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_preauth_pkcs.c | 131 | ||||
-rw-r--r-- | usr/src/lib/smhba/common/SMHBAAPILIB.c | 2 | ||||
-rw-r--r-- | usr/src/pkg/manifests/system-bhyve-tests.p5m | 1 | ||||
-rw-r--r-- | usr/src/test/bhyve-tests/runfiles/default.run | 3 | ||||
-rw-r--r-- | usr/src/test/bhyve-tests/tests/common/in_guest.c | 28 | ||||
-rw-r--r-- | usr/src/test/bhyve-tests/tests/common/payload_common.h | 1 | ||||
-rw-r--r-- | usr/src/test/bhyve-tests/tests/inst_emul/Makefile | 6 | ||||
-rw-r--r-- | usr/src/test/bhyve-tests/tests/inst_emul/exit_paging.c | 79 | ||||
-rw-r--r-- | usr/src/test/bhyve-tests/tests/inst_emul/payload_exit_paging.s | 30 | ||||
-rw-r--r-- | usr/src/test/bhyve-tests/tests/vmm/interface_version.c | 22 | ||||
-rw-r--r-- | usr/src/uts/intel/io/vmm/vmm.c | 21 | ||||
-rw-r--r-- | usr/src/uts/intel/io/vmm/vmm_sol_dev.c | 12 |
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) { |