Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libnvmm Two changes:
details: https://anonhg.NetBSD.org/src/rev/7ff383ecc6ea
branches: trunk
changeset: 446714:7ff383ecc6ea
user: maxv <maxv%NetBSD.org@localhost>
date: Sat Dec 15 13:09:02 2018 +0000
description:
Two changes:
- Fix the I/O Assist, for INS* it is RDI and not RSI, and the register
gets updated regardless of the REP prefix.
- Fill in the Mem Assist. We decode and emulate certain instructions,
and pass a mem descriptor to the callback to handle the transaction.
The disassembler could use some polishing, and there are still a
few instructions missing; but basically it works.
diffstat:
lib/libnvmm/libnvmm_x86.c | 1938 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 1922 insertions(+), 16 deletions(-)
diffs (truncated from 2002 to 300 lines):
diff -r 957f48b635a0 -r 7ff383ecc6ea lib/libnvmm/libnvmm_x86.c
--- a/lib/libnvmm/libnvmm_x86.c Sat Dec 15 12:52:36 2018 +0000
+++ b/lib/libnvmm/libnvmm_x86.c Sat Dec 15 13:09:02 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: libnvmm_x86.c,v 1.4 2018/11/17 16:11:33 maxv Exp $ */
+/* $NetBSD: libnvmm_x86.c,v 1.5 2018/12/15 13:09:02 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -388,6 +388,26 @@
/* -------------------------------------------------------------------------- */
static inline bool
+is_64bit(struct nvmm_x64_state *state)
+{
+ return (state->segs[NVMM_X64_SEG_CS].attrib.lng != 0);
+}
+
+static inline bool
+is_32bit(struct nvmm_x64_state *state)
+{
+ return (state->segs[NVMM_X64_SEG_CS].attrib.lng == 0) &&
+ (state->segs[NVMM_X64_SEG_CS].attrib.def32 == 1);
+}
+
+static inline bool
+is_16bit(struct nvmm_x64_state *state)
+{
+ return (state->segs[NVMM_X64_SEG_CS].attrib.lng == 0) &&
+ (state->segs[NVMM_X64_SEG_CS].attrib.def32 == 0);
+}
+
+static inline bool
is_long_mode(struct nvmm_x64_state *state)
{
return (state->msrs[NVMM_X64_MSR_EFER] & EFER_LME) != 0;
@@ -440,9 +460,9 @@
uintptr_t hva;
gvaddr_t gva, off;
gpaddr_t gpa;
- uint64_t rsi;
uint8_t tmp[8];
uint8_t *ptr, *ptr2;
+ int reg = 0; /* GCC */
bool cross;
int ret;
@@ -466,18 +486,22 @@
if (!exit->u.io.str) {
ptr = (uint8_t *)&state.gprs[NVMM_X64_GPR_RAX];
} else {
- rsi = state.gprs[NVMM_X64_GPR_RSI];
+ if (io.in) {
+ reg = NVMM_X64_GPR_RDI;
+ } else {
+ reg = NVMM_X64_GPR_RSI;
+ }
switch (exit->u.io.address_size) {
case 8:
- gva = rsi;
+ gva = state.gprs[reg];
break;
case 4:
- gva = (rsi & 0x00000000FFFFFFFF);
+ gva = (state.gprs[reg] & 0x00000000FFFFFFFF);
break;
case 2:
default: /* impossible */
- gva = (rsi & 0x000000000000FFFF);
+ gva = (state.gprs[reg] & 0x000000000000FFFF);
break;
}
@@ -553,18 +577,19 @@
/* nothing to do */
}
+ if (exit->u.io.str) {
+ if (state.gprs[NVMM_X64_GPR_RFLAGS] & PSL_D) {
+ state.gprs[reg] -= io.size;
+ } else {
+ state.gprs[reg] += io.size;
+ }
+ }
+
if (exit->u.io.rep) {
state.gprs[NVMM_X64_GPR_RCX] -= 1;
if (state.gprs[NVMM_X64_GPR_RCX] == 0) {
state.gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc;
}
- if (exit->u.io.str) {
- if (state.gprs[NVMM_X64_GPR_RFLAGS] & PSL_D) {
- state.gprs[NVMM_X64_GPR_RSI] -= io.size;
- } else {
- state.gprs[NVMM_X64_GPR_RSI] += io.size;
- }
- }
} else {
state.gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc;
}
@@ -578,16 +603,1897 @@
/* -------------------------------------------------------------------------- */
+static void x86_emul_or(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+static void x86_emul_and(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+static void x86_emul_xor(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+static void x86_emul_mov(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+static void x86_emul_stos(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+static void x86_emul_lods(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+
+enum x86_legpref {
+ /* Group 1 */
+ LEG_LOCK = 0,
+ LEG_REPN, /* REPNE/REPNZ */
+ LEG_REP, /* REP/REPE/REPZ */
+ /* Group 2 */
+ LEG_OVR_CS,
+ LEG_OVR_SS,
+ LEG_OVR_DS,
+ LEG_OVR_ES,
+ LEG_OVR_FS,
+ LEG_OVR_GS,
+ LEG_BRN_TAKEN,
+ LEG_BRN_NTAKEN,
+ /* Group 3 */
+ LEG_OPR_OVR,
+ /* Group 4 */
+ LEG_ADR_OVR,
+
+ NLEG
+};
+
+struct x86_rexpref {
+ bool present;
+ bool w;
+ bool r;
+ bool x;
+ bool b;
+};
+
+struct x86_reg {
+ int num; /* NVMM GPR state index */
+ uint64_t mask;
+};
+
+enum x86_disp_type {
+ DISP_NONE,
+ DISP_0,
+ DISP_1,
+ DISP_4
+};
+
+struct x86_disp {
+ enum x86_disp_type type;
+ uint8_t data[4];
+};
+
+enum REGMODRM__Mod {
+ MOD_DIS0, /* also, register indirect */
+ MOD_DIS1,
+ MOD_DIS4,
+ MOD_REG
+};
+
+enum REGMODRM__Reg {
+ REG_000, /* these fields are indexes to the register map */
+ REG_001,
+ REG_010,
+ REG_011,
+ REG_100,
+ REG_101,
+ REG_110,
+ REG_111
+};
+
+enum REGMODRM__Rm {
+ RM_000, /* reg */
+ RM_001, /* reg */
+ RM_010, /* reg */
+ RM_011, /* reg */
+ RM_RSP_SIB, /* reg or SIB, depending on the MOD */
+ RM_RBP_DISP32, /* reg or displacement-only (= RIP-relative on amd64) */
+ RM_110,
+ RM_111
+};
+
+struct x86_regmodrm {
+ bool present;
+ enum REGMODRM__Mod mod;
+ enum REGMODRM__Reg reg;
+ enum REGMODRM__Rm rm;
+};
+
+struct x86_immediate {
+ size_t size; /* 1/2/4/8 */
+ uint8_t data[8];
+};
+
+struct x86_sib {
+ uint8_t scale;
+ const struct x86_reg *idx;
+ const struct x86_reg *bas;
+};
+
+enum x86_store_type {
+ STORE_NONE,
+ STORE_REG,
+ STORE_IMM,
+ STORE_SIB,
+ STORE_DMO
+};
+
+struct x86_store {
+ enum x86_store_type type;
+ union {
+ const struct x86_reg *reg;
+ struct x86_immediate imm;
+ struct x86_sib sib;
+ uint64_t dmo;
+ } u;
+ struct x86_disp disp;
+};
+
+struct x86_instr {
+ size_t len;
+ bool legpref[NLEG];
+ struct x86_rexpref rexpref;
+ size_t operand_size;
+ size_t address_size;
+
+ struct x86_regmodrm regmodrm;
+
+ const struct x86_opcode *opcode;
+
+ struct x86_store src;
+ struct x86_store dst;
+
+ struct x86_store *strm;
+
+ void (*emul)(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+};
+
+struct x86_decode_fsm {
+ /* vcpu */
+ bool is64bit;
+ bool is32bit;
+ bool is16bit;
+
+ /* fsm */
+ int (*fn)(struct x86_decode_fsm *, struct x86_instr *);
+ uint8_t *buf;
+ uint8_t *end;
+};
+
+struct x86_opcode {
+ uint8_t byte;
+ bool regmodrm;
+ bool regtorm;
+ bool dmo;
+ bool todmo;
+ bool stos;
+ bool lods;
+ bool szoverride;
+ int defsize;
+ int allsize;
+ bool group11;
+ bool immediate;
+ int immsize;
+ int flags;
+ void (*emul)(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+};
+
+struct x86_group_entry {
+ void (*emul)(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
+};
+
+#define OPSIZE_BYTE 0x01
+#define OPSIZE_WORD 0x02 /* 2 bytes */
+#define OPSIZE_DOUB 0x04 /* 4 bytes */
+#define OPSIZE_QUAD 0x08 /* 8 bytes */
+
+#define FLAG_z 0x02
+
+static const struct x86_group_entry group11[8] = {
+ [0] = { .emul = x86_emul_mov }
+};
+
+static const struct x86_opcode primary_opcode_table[] = {
+ /*
+ * Group11
+ */
+ {
+ .byte = 0xC6,
+ .regmodrm = true,
+ .regtorm = true,
+ .szoverride = false,
+ .defsize = OPSIZE_BYTE,
+ .allsize = -1,
Home |
Main Index |
Thread Index |
Old Index