aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/vmm
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2020-06-25 00:18:42 +0000
committerConrad Meyer <cem@FreeBSD.org>2020-06-25 00:18:42 +0000
commit4daa95f85d4c5b077295b4e1be1f5163b5dacfe9 (patch)
tree4c95208c87ab228ca816d2f97f9c6b30dc91c531 /sys/amd64/vmm
parent54cca285fc3d32e0be4028d17c055424b49f4f7d (diff)
downloadsrc-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.c32
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