Date: Thu, 25 Jun 2020 00:18:42 +0000 (UTC) From: Conrad Meyer <cem@FreeBSD.org> 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 Message-ID: <202006250018.05P0IgEi062942@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <err.h> #include <assert.h> #include <stdbool.h> +#include <stddef.h> #include <stdio.h> +#include <string.h> #include <strings.h> #include <vmmapi.h> #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 <machine/vmm_dev.h> #endif +#include <machine/vmm_instruction_emul.h> #include <vmmapi.h> #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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202006250018.05P0IgEi062942>