From owner-svn-src-head@freebsd.org Thu Jun 25 00:18:43 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 925F234757F; Thu, 25 Jun 2020 00:18:43 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49sgbl37LWz4Gty; Thu, 25 Jun 2020 00:18:43 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 66B791A4BF; Thu, 25 Jun 2020 00:18:43 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 05P0IheI062945; Thu, 25 Jun 2020 00:18:43 GMT (envelope-from cem@FreeBSD.org) Received: (from cem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 05P0IgEi062942; Thu, 25 Jun 2020 00:18:42 GMT (envelope-from cem@FreeBSD.org) Message-Id: <202006250018.05P0IgEi062942@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: cem set sender to cem@FreeBSD.org using -f From: Conrad Meyer Date: Thu, 25 Jun 2020 00:18:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r362600 - in head: sys/amd64/include sys/amd64/vmm usr.sbin/bhyve X-SVN-Group: head X-SVN-Commit-Author: cem X-SVN-Commit-Paths: in head: sys/amd64/include sys/amd64/vmm usr.sbin/bhyve X-SVN-Commit-Revision: 362600 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 25 Jun 2020 00:18:43 -0000 Author: cem Date: Thu Jun 25 00:18:42 2020 New Revision: 362600 URL: https://svnweb.freebsd.org/changeset/base/362600 Log: bhyve(8): For prototyping, reattempt decode in userspace If userspace has a newer bhyve than the kernel, it may be able to decode and emulate some instructions vmm.ko is unaware of. In this scenario, reset decoder state and try again. Reviewed by: grehan Differential Revision: https://reviews.freebsd.org/D24464 Modified: head/sys/amd64/include/vmm.h head/sys/amd64/include/vmm_instruction_emul.h head/sys/amd64/vmm/vmm_instruction_emul.c head/usr.sbin/bhyve/bhyverun.c Modified: head/sys/amd64/include/vmm.h ============================================================================== --- head/sys/amd64/include/vmm.h Thu Jun 25 00:09:43 2020 (r362599) +++ head/sys/amd64/include/vmm.h Thu Jun 25 00:18:42 2020 (r362600) @@ -546,6 +546,9 @@ _Static_assert(_Alignof(struct vie_op) == 2, "ABI"); struct vie { uint8_t inst[VIE_INST_SIZE]; /* instruction bytes */ uint8_t num_valid; /* size of the instruction */ + +/* The following fields are all zeroed upon restart. */ +#define vie_startzero num_processed uint8_t num_processed; uint8_t addrsize:4, opsize:4; /* address and operand sizes */ Modified: head/sys/amd64/include/vmm_instruction_emul.h ============================================================================== --- head/sys/amd64/include/vmm_instruction_emul.h Thu Jun 25 00:09:43 2020 (r362599) +++ head/sys/amd64/include/vmm_instruction_emul.h Thu Jun 25 00:18:42 2020 (r362600) @@ -105,6 +105,7 @@ int vm_gla2gpa_nofault(struct vm *vm, int vcpuid, stru uint64_t gla, int prot, uint64_t *gpa, int *is_fault); #endif /* _KERNEL */ +void vie_restart(struct vie *vie); void vie_init(struct vie *vie, const char *inst_bytes, int inst_length); /* Modified: head/sys/amd64/vmm/vmm_instruction_emul.c ============================================================================== --- head/sys/amd64/vmm/vmm_instruction_emul.c Thu Jun 25 00:09:43 2020 (r362599) +++ head/sys/amd64/vmm/vmm_instruction_emul.c Thu Jun 25 00:18:42 2020 (r362600) @@ -53,7 +53,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #define KASSERT(exp,msg) assert((exp)) @@ -1990,22 +1992,36 @@ vie_calculate_gla(enum vm_cpu_mode cpu_mode, enum vm_r return (0); } +/* + * Prepare a partially decoded vie for a 2nd attempt. + */ void -vie_init(struct vie *vie, const char *inst_bytes, int inst_length) +vie_restart(struct vie *vie) { - KASSERT(inst_length >= 0 && inst_length <= VIE_INST_SIZE, - ("%s: invalid instruction length (%d)", __func__, inst_length)); + _Static_assert( + offsetof(struct vie, inst) < offsetof(struct vie, vie_startzero) && + offsetof(struct vie, num_valid) < offsetof(struct vie, vie_startzero), + "restart should not erase instruction length or contents"); - bzero(vie, sizeof(struct vie)); + memset((char *)vie + offsetof(struct vie, vie_startzero), 0, + sizeof(*vie) - offsetof(struct vie, vie_startzero)); vie->base_register = VM_REG_LAST; vie->index_register = VM_REG_LAST; vie->segment_register = VM_REG_LAST; +} - if (inst_length) { - bcopy(inst_bytes, vie->inst, inst_length); - vie->num_valid = inst_length; - } +void +vie_init(struct vie *vie, const char *inst_bytes, int inst_length) +{ + KASSERT(inst_length >= 0 && inst_length <= VIE_INST_SIZE, + ("%s: invalid instruction length (%d)", __func__, inst_length)); + + vie_restart(vie); + memset(vie->inst, 0, sizeof(vie->inst)); + if (inst_length != 0) + memcpy(vie->inst, inst_bytes, inst_length); + vie->num_valid = inst_length; } #ifdef _KERNEL Modified: head/usr.sbin/bhyve/bhyverun.c ============================================================================== --- head/usr.sbin/bhyve/bhyverun.c Thu Jun 25 00:09:43 2020 (r362599) +++ head/usr.sbin/bhyve/bhyverun.c Thu Jun 25 00:18:42 2020 (r362600) @@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$"); #ifndef WITHOUT_CAPSICUM #include #endif +#include #include #include "bhyverun.h" @@ -746,12 +747,26 @@ vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit static int vmexit_inst_emul(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu) { - int err, i; + 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; + (void)vmm_decode_instruction(mode, cs_d, vie); + } + err = emulate_mem(ctx, *pvcpu, vmexit->u.inst_emul.gpa, vie, &vmexit->u.inst_emul.paging);