xref: /openbsd-src/usr.sbin/vmd/mmio.h (revision ba66f5646b2078267ada7f93fdb09284b0ca3a3d)
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