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