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