File: [local] / src / usr.sbin / vmd / mmio.h (download)
Revision 1.1, Thu Nov 10 11:46:39 2022 UTC (18 months, 3 weeks ago) by dv
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, HEAD
vmd(8): import mmio decode and emulation, disabled for now.
The initial mmio support for vmd adds support for only specific MOV
and MOVZX instructions. Plan is to begin iterating in-tree on other
missing pieces. All functionality is gated behind an #if for now.
Only change to vmm(4) is reordering register #define's in vmmvar.h.
ok mlarkin@
|
/* $OpenBSD: mmio.h,v 1.1 2022/11/10 11:46:39 dv Exp $ */
/*
* Copyright (c) 2022 Dave Voutila <dv@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _MMIO_H_
#define _MMIO_H_
#include <sys/types.h>
#include <machine/vmmvar.h>
/* Code segment bits */
#define CS_L (1 << 13)
#define CS_D (1 << 14)
#define EFLAGS_VM (1 << 17) /* Virtual 8086 Mode enabled */
/* Instruction Prefixes (SDM Vol 2, 2.1.1) */
#define LEG_1_LOCK 0xF0
#define LEG_1_REPNE 0xF2
#define LEG_1_REP 0xF3
#define LEG_2_CS 0x2E
#define LEG_2_SS 0x36
#define LEG_2_DS 0x3E
#define LEG_2_ES 0x26
#define LEG_2_FS 0x64
#define LEG_2_GS 0x65
#define LEG_3_OPSZ 0x66 /* Operand size override */
#define LEG_4_ADDRSZ 0x67 /* Address size override */
/* REX prefix bit fields */
#define REX_B 0x01
#define REX_X 0x02
#define REX_R 0x04
#define REX_W 0x08
#define REX_BASE 0x40
#define REX_NONE 0x00
/* VEX prefixes (unsupported) */
#define VEX_2_BYTE 0xC5
#define VEX_3_BYTE 0xC4
#define ESCAPE 0x0F
struct x86_prefix {
uint8_t pfx_group1; /* LOCK, REP, or REPNE */
uint8_t pfx_group2; /* Segment overrides */
uint8_t pfx_group3; /* Operand size override */
uint8_t pfx_group4; /* Address size override */
uint8_t pfx_rex; /* REX prefix for long mode */
};
enum x86_opcode_type {
OP_UNKNOWN = 0, /* Default value when undecoded. */
OP_IN,
OP_INS,
OP_MOV,
OP_MOVZX,
OP_OUT,
OP_OUTS,
OP_TWO_BYTE, /* Opcode is two bytes, not one. */
OP_UNSUPPORTED, /* Valid decode, but no current support. */
};
/* Instruction Operand Encoding as described in the SDM Vol 2, Ch 3-5. */
enum x86_operand_enc {
OP_ENC_UNKNOWN = 0,
OP_ENC_I, /* Only immediate operand */
OP_ENC_MI, /* Immediate to ModRM */
OP_ENC_MR, /* Register to ModRM */
OP_ENC_RM, /* ModRm to Register */
OP_ENC_FD, /* Value @ segment offset to RAX */
OP_ENC_TD, /* RAX to segment offset */
OP_ENC_OI, /* Immediate to Register (no emul. needed!) */
OP_ENC_ZO, /* No ModRM byte. */
};
/* Displacement bytes */
enum x86_disp_type {
DISP_NONE = 0,
DISP_0,
DISP_1,
DISP_2, /* Requires Legacy prefix LEG_4_ADDRSZ */
DISP_4,
};
struct x86_opcode {
uint8_t op_bytes[2]; /* VEX unsupported */
uint8_t op_bytes_len; /* Length of opcode */
enum x86_opcode_type op_type; /* Type of opcode */
enum x86_operand_enc op_encoding; /* Operand encoding */
};
struct x86_insn {
uint8_t insn_bytes[15]; /* Original payload */
uint8_t insn_bytes_len; /* Size of payload */
int insn_cpu_mode; /* CPU mode */
struct x86_prefix insn_prefix; /* Combined prefixes */
struct x86_opcode insn_opcode;
uint8_t insn_modrm; /* ModR/M */
#define MODRM_MOD(x) ((x >> 6) & 0x3)
#define MODRM_REGOP(x) ((x >> 3) & 0x7)
#define MODRM_RM(x) ((x >> 0) & 0x7)
uint8_t insn_modrm_valid; /* Is ModR/M set? */
vaddr_t insn_gva; /* Guest Virtual Addr */
int insn_reg; /* Register */
uint8_t insn_sib; /* Scale-Index-Base */
uint8_t insn_sib_valid; /* SIB byte set? */
uint64_t insn_disp; /* Displacement */
enum x86_disp_type insn_disp_type;
uint64_t insn_immediate; /* Immediate data */
uint8_t insn_immediate_len;
};
int insn_decode(struct vm_exit *, struct x86_insn *);
int insn_emulate(struct vm_exit *, struct x86_insn *);
#endif /* _MMIO_H_ */