1*ba66f564Sdv /* $OpenBSD: mmio.h,v 1.2 2024/07/09 09:31:37 dv Exp $ */ 2bee70036Sdv 3bee70036Sdv /* 4bee70036Sdv * Copyright (c) 2022 Dave Voutila <dv@openbsd.org> 5bee70036Sdv * 6bee70036Sdv * Permission to use, copy, modify, and distribute this software for any 7bee70036Sdv * purpose with or without fee is hereby granted, provided that the above 8bee70036Sdv * copyright notice and this permission notice appear in all copies. 9bee70036Sdv * 10bee70036Sdv * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11bee70036Sdv * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12bee70036Sdv * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13bee70036Sdv * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14bee70036Sdv * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15bee70036Sdv * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16bee70036Sdv * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17bee70036Sdv */ 18bee70036Sdv 19bee70036Sdv #ifndef _MMIO_H_ 20bee70036Sdv #define _MMIO_H_ 21bee70036Sdv 22bee70036Sdv #include <sys/types.h> 23bee70036Sdv 24bee70036Sdv /* Code segment bits */ 25bee70036Sdv #define CS_L (1 << 13) 26bee70036Sdv #define CS_D (1 << 14) 27bee70036Sdv 28bee70036Sdv #define EFLAGS_VM (1 << 17) /* Virtual 8086 Mode enabled */ 29bee70036Sdv 30bee70036Sdv /* Instruction Prefixes (SDM Vol 2, 2.1.1) */ 31bee70036Sdv #define LEG_1_LOCK 0xF0 32bee70036Sdv #define LEG_1_REPNE 0xF2 33bee70036Sdv #define LEG_1_REP 0xF3 34bee70036Sdv #define LEG_2_CS 0x2E 35bee70036Sdv #define LEG_2_SS 0x36 36bee70036Sdv #define LEG_2_DS 0x3E 37bee70036Sdv #define LEG_2_ES 0x26 38bee70036Sdv #define LEG_2_FS 0x64 39bee70036Sdv #define LEG_2_GS 0x65 40bee70036Sdv #define LEG_3_OPSZ 0x66 /* Operand size override */ 41bee70036Sdv #define LEG_4_ADDRSZ 0x67 /* Address size override */ 42bee70036Sdv 43bee70036Sdv /* REX prefix bit fields */ 44bee70036Sdv #define REX_B 0x01 45bee70036Sdv #define REX_X 0x02 46bee70036Sdv #define REX_R 0x04 47bee70036Sdv #define REX_W 0x08 48bee70036Sdv #define REX_BASE 0x40 49bee70036Sdv 50bee70036Sdv #define REX_NONE 0x00 51bee70036Sdv 52bee70036Sdv /* VEX prefixes (unsupported) */ 53bee70036Sdv #define VEX_2_BYTE 0xC5 54bee70036Sdv #define VEX_3_BYTE 0xC4 55bee70036Sdv 56bee70036Sdv #define ESCAPE 0x0F 57bee70036Sdv 58bee70036Sdv struct x86_prefix { 59bee70036Sdv uint8_t pfx_group1; /* LOCK, REP, or REPNE */ 60bee70036Sdv uint8_t pfx_group2; /* Segment overrides */ 61bee70036Sdv uint8_t pfx_group3; /* Operand size override */ 62bee70036Sdv uint8_t pfx_group4; /* Address size override */ 63bee70036Sdv uint8_t pfx_rex; /* REX prefix for long mode */ 64bee70036Sdv }; 65bee70036Sdv 66bee70036Sdv enum x86_opcode_type { 67bee70036Sdv OP_UNKNOWN = 0, /* Default value when undecoded. */ 68bee70036Sdv OP_IN, 69bee70036Sdv OP_INS, 70bee70036Sdv OP_MOV, 71bee70036Sdv OP_MOVZX, 72bee70036Sdv OP_OUT, 73bee70036Sdv OP_OUTS, 74bee70036Sdv OP_TWO_BYTE, /* Opcode is two bytes, not one. */ 75bee70036Sdv OP_UNSUPPORTED, /* Valid decode, but no current support. */ 76bee70036Sdv }; 77bee70036Sdv 78bee70036Sdv /* Instruction Operand Encoding as described in the SDM Vol 2, Ch 3-5. */ 79bee70036Sdv enum x86_operand_enc { 80bee70036Sdv OP_ENC_UNKNOWN = 0, 81bee70036Sdv OP_ENC_I, /* Only immediate operand */ 82bee70036Sdv OP_ENC_MI, /* Immediate to ModRM */ 83bee70036Sdv OP_ENC_MR, /* Register to ModRM */ 84bee70036Sdv OP_ENC_RM, /* ModRm to Register */ 85bee70036Sdv OP_ENC_FD, /* Value @ segment offset to RAX */ 86bee70036Sdv OP_ENC_TD, /* RAX to segment offset */ 87bee70036Sdv OP_ENC_OI, /* Immediate to Register (no emul. needed!) */ 88bee70036Sdv OP_ENC_ZO, /* No ModRM byte. */ 89bee70036Sdv }; 90bee70036Sdv 91bee70036Sdv /* Displacement bytes */ 92bee70036Sdv enum x86_disp_type { 93bee70036Sdv DISP_NONE = 0, 94bee70036Sdv DISP_0, 95bee70036Sdv DISP_1, 96bee70036Sdv DISP_2, /* Requires Legacy prefix LEG_4_ADDRSZ */ 97bee70036Sdv DISP_4, 98bee70036Sdv }; 99bee70036Sdv 100bee70036Sdv struct x86_opcode { 101bee70036Sdv uint8_t op_bytes[2]; /* VEX unsupported */ 102bee70036Sdv uint8_t op_bytes_len; /* Length of opcode */ 103bee70036Sdv enum x86_opcode_type op_type; /* Type of opcode */ 104bee70036Sdv enum x86_operand_enc op_encoding; /* Operand encoding */ 105bee70036Sdv }; 106bee70036Sdv 107bee70036Sdv struct x86_insn { 108bee70036Sdv uint8_t insn_bytes[15]; /* Original payload */ 109bee70036Sdv uint8_t insn_bytes_len; /* Size of payload */ 110bee70036Sdv int insn_cpu_mode; /* CPU mode */ 111bee70036Sdv 112bee70036Sdv struct x86_prefix insn_prefix; /* Combined prefixes */ 113bee70036Sdv struct x86_opcode insn_opcode; 114bee70036Sdv 115bee70036Sdv uint8_t insn_modrm; /* ModR/M */ 116bee70036Sdv #define MODRM_MOD(x) ((x >> 6) & 0x3) 117bee70036Sdv #define MODRM_REGOP(x) ((x >> 3) & 0x7) 118bee70036Sdv #define MODRM_RM(x) ((x >> 0) & 0x7) 119bee70036Sdv uint8_t insn_modrm_valid; /* Is ModR/M set? */ 120bee70036Sdv 121bee70036Sdv vaddr_t insn_gva; /* Guest Virtual Addr */ 122bee70036Sdv int insn_reg; /* Register */ 123bee70036Sdv 124bee70036Sdv uint8_t insn_sib; /* Scale-Index-Base */ 125bee70036Sdv uint8_t insn_sib_valid; /* SIB byte set? */ 126bee70036Sdv 127bee70036Sdv uint64_t insn_disp; /* Displacement */ 128bee70036Sdv enum x86_disp_type insn_disp_type; 129bee70036Sdv 130bee70036Sdv uint64_t insn_immediate; /* Immediate data */ 131bee70036Sdv uint8_t insn_immediate_len; 132bee70036Sdv }; 133bee70036Sdv 134bee70036Sdv int insn_decode(struct vm_exit *, struct x86_insn *); 135bee70036Sdv int insn_emulate(struct vm_exit *, struct x86_insn *); 136bee70036Sdv 137bee70036Sdv #endif /* _MMIO_H_ */ 138