diff options
author | Conrad Meyer <cem@FreeBSD.org> | 2020-06-25 00:18:42 +0000 |
---|---|---|
committer | Conrad Meyer <cem@FreeBSD.org> | 2020-06-25 00:18:42 +0000 |
commit | 4daa95f85d4c5b077295b4e1be1f5163b5dacfe9 (patch) | |
tree | 4c95208c87ab228ca816d2f97f9c6b30dc91c531 /sys/amd64/vmm | |
parent | 54cca285fc3d32e0be4028d17c055424b49f4f7d (diff) | |
download | src-4daa95f85d4c5b077295b4e1be1f5163b5dacfe9.tar.gz src-4daa95f85d4c5b077295b4e1be1f5163b5dacfe9.zip |
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
Notes
Notes:
svn path=/head/; revision=362600
Diffstat (limited to 'sys/amd64/vmm')
-rw-r--r-- | sys/amd64/vmm/vmm_instruction_emul.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index 70d2dfe55b76..70d77186be91 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -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_reg_name seg, 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 |