xref: /openbsd/usr.sbin/vmd/mmio.h (revision ba66f564)
1 /*	$OpenBSD: mmio.h,v 1.2 2024/07/09 09:31:37 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 
24 /* Code segment bits  */
25 #define CS_L		(1 << 13)
26 #define CS_D		(1 << 14)
27 
28 #define EFLAGS_VM	(1 << 17)	/* Virtual 8086 Mode enabled */
29 
30 /* Instruction Prefixes (SDM Vol 2, 2.1.1) */
31 #define LEG_1_LOCK	0xF0
32 #define LEG_1_REPNE	0xF2
33 #define LEG_1_REP	0xF3
34 #define LEG_2_CS	0x2E
35 #define LEG_2_SS	0x36
36 #define LEG_2_DS	0x3E
37 #define LEG_2_ES	0x26
38 #define LEG_2_FS	0x64
39 #define LEG_2_GS	0x65
40 #define LEG_3_OPSZ	0x66		/* Operand size override */
41 #define LEG_4_ADDRSZ	0x67		/* Address size override */
42 
43 /* REX prefix bit fields */
44 #define REX_B		0x01
45 #define REX_X		0x02
46 #define REX_R		0x04
47 #define REX_W		0x08
48 #define REX_BASE	0x40
49 
50 #define REX_NONE	0x00
51 
52 /* VEX prefixes (unsupported) */
53 #define VEX_2_BYTE	0xC5
54 #define VEX_3_BYTE	0xC4
55 
56 #define ESCAPE		0x0F
57 
58 struct x86_prefix {
59 	uint8_t		pfx_group1;	/* LOCK, REP, or REPNE */
60 	uint8_t		pfx_group2;	/* Segment overrides */
61 	uint8_t		pfx_group3;	/* Operand size override */
62 	uint8_t		pfx_group4;	/* Address size override */
63 	uint8_t		pfx_rex;	/* REX prefix for long mode */
64 };
65 
66 enum x86_opcode_type {
67 	OP_UNKNOWN = 0,		/* Default value when undecoded. */
68 	OP_IN,
69 	OP_INS,
70 	OP_MOV,
71 	OP_MOVZX,
72 	OP_OUT,
73 	OP_OUTS,
74 	OP_TWO_BYTE,		/* Opcode is two bytes, not one. */
75 	OP_UNSUPPORTED,		/* Valid decode, but no current support. */
76 };
77 
78 /* Instruction Operand Encoding as described in the SDM Vol 2, Ch 3-5. */
79 enum x86_operand_enc {
80 	OP_ENC_UNKNOWN = 0,
81 	OP_ENC_I,		/* Only immediate operand */
82 	OP_ENC_MI,		/* Immediate to ModRM */
83 	OP_ENC_MR,		/* Register to ModRM */
84 	OP_ENC_RM,		/* ModRm to Register */
85 	OP_ENC_FD,		/* Value @ segment offset to RAX */
86 	OP_ENC_TD,		/* RAX to segment offset */
87 	OP_ENC_OI,		/* Immediate to Register (no emul. needed!) */
88 	OP_ENC_ZO,		/* No ModRM byte. */
89 };
90 
91 /* Displacement bytes */
92 enum x86_disp_type {
93 	DISP_NONE = 0,
94 	DISP_0,
95 	DISP_1,
96 	DISP_2,			/* Requires Legacy prefix LEG_4_ADDRSZ */
97 	DISP_4,
98 };
99 
100 struct x86_opcode {
101 	uint8_t			op_bytes[2];		/* VEX unsupported */
102 	uint8_t			op_bytes_len;		/* Length of opcode */
103 	enum x86_opcode_type	op_type;		/* Type of opcode */
104 	enum x86_operand_enc	op_encoding;		/* Operand encoding */
105 };
106 
107 struct x86_insn {
108 	uint8_t			insn_bytes[15];		/* Original payload */
109 	uint8_t			insn_bytes_len;		/* Size of payload */
110 	int			insn_cpu_mode;		/* CPU mode */
111 
112 	struct x86_prefix 	insn_prefix;		/* Combined prefixes */
113 	struct x86_opcode	insn_opcode;
114 
115 	uint8_t			insn_modrm;		/* ModR/M */
116 #define MODRM_MOD(x)		((x >> 6) & 0x3)
117 #define MODRM_REGOP(x)		((x >> 3) & 0x7)
118 #define MODRM_RM(x)		((x >> 0) & 0x7)
119 	uint8_t			insn_modrm_valid;	/* Is ModR/M set? */
120 
121 	vaddr_t			insn_gva;		/* Guest Virtual Addr */
122 	int			insn_reg;		/* Register */
123 
124 	uint8_t			insn_sib;		/* Scale-Index-Base */
125 	uint8_t			insn_sib_valid;		/* SIB byte set? */
126 
127 	uint64_t		insn_disp;		/* Displacement */
128 	enum x86_disp_type	insn_disp_type;
129 
130 	uint64_t		insn_immediate;		/* Immediate data */
131 	uint8_t			insn_immediate_len;
132 };
133 
134 int	insn_decode(struct vm_exit *, struct x86_insn *);
135 int	insn_emulate(struct vm_exit *, struct x86_insn *);
136 
137 #endif /* _MMIO_H_ */
138