1/*	$NetBSD: nvmm_x86.h,v 1.21 2021/03/26 15:59:53 reinoud Exp $	*/
  2
  3/*
  4 * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
  5 * All rights reserved.
  6 *
  7 * This code is part of the NVMM hypervisor.
  8 *
  9 * Redistribution and use in source and binary forms, with or without
 10 * modification, are permitted provided that the following conditions
 11 * are met:
 12 * 1. Redistributions of source code must retain the above copyright
 13 *    notice, this list of conditions and the following disclaimer.
 14 * 2. Redistributions in binary form must reproduce the above copyright
 15 *    notice, this list of conditions and the following disclaimer in the
 16 *    documentation and/or other materials provided with the distribution.
 17 *
 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 28 * SUCH DAMAGE.
 29 */
 30
 31#ifndef _NVMM_X86_H_
 32#define _NVMM_X86_H_
 33
 34/* -------------------------------------------------------------------------- */
 35
 36#ifndef ASM_NVMM
 37
 38struct nvmm_x86_exit_memory {
 39	int prot;
 40	gpaddr_t gpa;
 41	uint8_t inst_len;
 42	uint8_t inst_bytes[15];
 43};
 44
 45struct nvmm_x86_exit_io {
 46	bool in;
 47	uint16_t port;
 48	int8_t seg;
 49	uint8_t address_size;
 50	uint8_t operand_size;
 51	bool rep;
 52	bool str;
 53	uint64_t npc;
 54};
 55
 56struct nvmm_x86_exit_rdmsr {
 57	uint32_t msr;
 58	uint64_t npc;
 59};
 60
 61struct nvmm_x86_exit_wrmsr {
 62	uint32_t msr;
 63	uint64_t val;
 64	uint64_t npc;
 65};
 66
 67struct nvmm_x86_exit_insn {
 68	uint64_t npc;
 69};
 70
 71struct nvmm_x86_exit_invalid {
 72	uint64_t hwcode;
 73};
 74
 75/* Generic. */
 76#define NVMM_VCPU_EXIT_NONE		0x0000000000000000ULL
 77#define NVMM_VCPU_EXIT_STOPPED		0xFFFFFFFFFFFFFFFEULL
 78#define NVMM_VCPU_EXIT_INVALID		0xFFFFFFFFFFFFFFFFULL
 79/* x86: operations. */
 80#define NVMM_VCPU_EXIT_MEMORY		0x0000000000000001ULL
 81#define NVMM_VCPU_EXIT_IO		0x0000000000000002ULL
 82/* x86: changes in VCPU state. */
 83#define NVMM_VCPU_EXIT_SHUTDOWN		0x0000000000001000ULL
 84#define NVMM_VCPU_EXIT_INT_READY	0x0000000000001001ULL
 85#define NVMM_VCPU_EXIT_NMI_READY	0x0000000000001002ULL
 86#define NVMM_VCPU_EXIT_HALTED		0x0000000000001003ULL
 87#define NVMM_VCPU_EXIT_TPR_CHANGED	0x0000000000001004ULL
 88/* x86: instructions. */
 89#define NVMM_VCPU_EXIT_RDMSR		0x0000000000002000ULL
 90#define NVMM_VCPU_EXIT_WRMSR		0x0000000000002001ULL
 91#define NVMM_VCPU_EXIT_MONITOR		0x0000000000002002ULL
 92#define NVMM_VCPU_EXIT_MWAIT		0x0000000000002003ULL
 93#define NVMM_VCPU_EXIT_CPUID		0x0000000000002004ULL
 94
 95struct nvmm_x86_exit {
 96	uint64_t reason;
 97	union {
 98		struct nvmm_x86_exit_memory mem;
 99		struct nvmm_x86_exit_io io;
100		struct nvmm_x86_exit_rdmsr rdmsr;
101		struct nvmm_x86_exit_wrmsr wrmsr;
102		struct nvmm_x86_exit_insn insn;
103		struct nvmm_x86_exit_invalid inv;
104	} u;
105	struct {
106		uint64_t rflags;
107		uint64_t cr8;
108		uint64_t int_shadow:1;
109		uint64_t int_window_exiting:1;
110		uint64_t nmi_window_exiting:1;
111		uint64_t evt_pending:1;
112		uint64_t rsvd:60;
113	} exitstate;
114};
115
116#define NVMM_VCPU_EVENT_EXCP	0
117#define NVMM_VCPU_EVENT_INTR	1
118
119struct nvmm_x86_event {
120	u_int type;
121	uint8_t vector;
122	union {
123		struct {
124			uint64_t error;
125		} excp;
126	} u;
127};
128
129struct nvmm_cap_md {
130	uint64_t mach_conf_support;
131
132	uint64_t vcpu_conf_support;
133#define NVMM_CAP_ARCH_VCPU_CONF_CPUID	__BIT(0)
134#define NVMM_CAP_ARCH_VCPU_CONF_TPR	__BIT(1)
135
136	uint64_t xcr0_mask;
137	uint32_t mxcsr_mask;
138	uint32_t conf_cpuid_maxops;
139	uint64_t rsvd[6];
140};
141
142#endif
143
144/* -------------------------------------------------------------------------- */
145
146/*
147 * Segment state indexes. We use X64 as naming convention, not to confuse with
148 * X86 which originally implied 32bit.
149 */
150
151/* Segments. */
152#define NVMM_X64_SEG_ES			0
153#define NVMM_X64_SEG_CS			1
154#define NVMM_X64_SEG_SS			2
155#define NVMM_X64_SEG_DS			3
156#define NVMM_X64_SEG_FS			4
157#define NVMM_X64_SEG_GS			5
158#define NVMM_X64_SEG_GDT		6
159#define NVMM_X64_SEG_IDT		7
160#define NVMM_X64_SEG_LDT		8
161#define NVMM_X64_SEG_TR			9
162#define NVMM_X64_NSEG			10
163
164/* General Purpose Registers. */
165#define NVMM_X64_GPR_RAX		0
166#define NVMM_X64_GPR_RCX		1
167#define NVMM_X64_GPR_RDX		2
168#define NVMM_X64_GPR_RBX		3
169#define NVMM_X64_GPR_RSP		4
170#define NVMM_X64_GPR_RBP		5
171#define NVMM_X64_GPR_RSI		6
172#define NVMM_X64_GPR_RDI		7
173#define NVMM_X64_GPR_R8			8
174#define NVMM_X64_GPR_R9			9
175#define NVMM_X64_GPR_R10		10
176#define NVMM_X64_GPR_R11		11
177#define NVMM_X64_GPR_R12		12
178#define NVMM_X64_GPR_R13		13
179#define NVMM_X64_GPR_R14		14
180#define NVMM_X64_GPR_R15		15
181#define NVMM_X64_GPR_RIP		16
182#define NVMM_X64_GPR_RFLAGS		17
183#define NVMM_X64_NGPR			18
184
185/* Control Registers. */
186#define NVMM_X64_CR_CR0			0
187#define NVMM_X64_CR_CR2			1
188#define NVMM_X64_CR_CR3			2
189#define NVMM_X64_CR_CR4			3
190#define NVMM_X64_CR_CR8			4
191#define NVMM_X64_CR_XCR0		5
192#define NVMM_X64_NCR			6
193
194/* Debug Registers. */
195#define NVMM_X64_DR_DR0			0
196#define NVMM_X64_DR_DR1			1
197#define NVMM_X64_DR_DR2			2
198#define NVMM_X64_DR_DR3			3
199#define NVMM_X64_DR_DR6			4
200#define NVMM_X64_DR_DR7			5
201#define NVMM_X64_NDR			6
202
203/* MSRs. */
204#define NVMM_X64_MSR_EFER		0
205#define NVMM_X64_MSR_STAR		1
206#define NVMM_X64_MSR_LSTAR		2
207#define NVMM_X64_MSR_CSTAR		3
208#define NVMM_X64_MSR_SFMASK		4
209#define NVMM_X64_MSR_KERNELGSBASE	5
210#define NVMM_X64_MSR_SYSENTER_CS	6
211#define NVMM_X64_MSR_SYSENTER_ESP	7
212#define NVMM_X64_MSR_SYSENTER_EIP	8
213#define NVMM_X64_MSR_PAT		9
214#define NVMM_X64_MSR_TSC		10
215#define NVMM_X64_NMSR			11
216
217#ifndef ASM_NVMM
218
219#include <sys/types.h>
220#include <x86/cpu_extended_state.h>
221
222struct nvmm_x64_state_seg {
223	uint16_t selector;
224	struct {		/* hidden */
225		uint16_t type:4;
226		uint16_t s:1;
227		uint16_t dpl:2;
228		uint16_t p:1;
229		uint16_t avl:1;
230		uint16_t l:1;
231		uint16_t def:1;
232		uint16_t g:1;
233		uint16_t rsvd:4;
234	} attrib;
235	uint32_t limit;		/* hidden */
236	uint64_t base;		/* hidden */
237};
238
239struct nvmm_x64_state_intr {
240	uint64_t int_shadow:1;
241	uint64_t int_window_exiting:1;
242	uint64_t nmi_window_exiting:1;
243	uint64_t evt_pending:1;
244	uint64_t rsvd:60;
245};
246
247/* Flags. */
248#define NVMM_X64_STATE_SEGS	0x01
249#define NVMM_X64_STATE_GPRS	0x02
250#define NVMM_X64_STATE_CRS	0x04
251#define NVMM_X64_STATE_DRS	0x08
252#define NVMM_X64_STATE_MSRS	0x10
253#define NVMM_X64_STATE_INTR	0x20
254#define NVMM_X64_STATE_FPU	0x40
255#define NVMM_X64_STATE_ALL	\
256	(NVMM_X64_STATE_SEGS | NVMM_X64_STATE_GPRS | NVMM_X64_STATE_CRS | \
257	 NVMM_X64_STATE_DRS | NVMM_X64_STATE_MSRS | NVMM_X64_STATE_INTR | \
258	 NVMM_X64_STATE_FPU)
259
260struct nvmm_x64_state {
261	struct nvmm_x64_state_seg segs[NVMM_X64_NSEG];
262	uint64_t gprs[NVMM_X64_NGPR];
263	uint64_t crs[NVMM_X64_NCR];
264	uint64_t drs[NVMM_X64_NDR];
265	uint64_t msrs[NVMM_X64_NMSR];
266	struct nvmm_x64_state_intr intr;
267	struct fxsave fpu;
268};
269
270#define NVMM_VCPU_CONF_CPUID	NVMM_VCPU_CONF_MD_BEGIN
271#define NVMM_VCPU_CONF_TPR	(NVMM_VCPU_CONF_MD_BEGIN + 1)
272
273struct nvmm_vcpu_conf_cpuid {
274	/* The options. */
275	uint32_t mask:1;
276	uint32_t exit:1;
277	uint32_t rsvd:30;
278
279	/* The leaf. */
280	uint32_t leaf;
281
282	/* The params. */
283	union {
284		struct {
285			struct {
286				uint32_t eax;
287				uint32_t ebx;
288				uint32_t ecx;
289				uint32_t edx;
290			} set;
291			struct {
292				uint32_t eax;
293				uint32_t ebx;
294				uint32_t ecx;
295				uint32_t edx;
296			} del;
297		} mask;
298	} u;
299};
300
301struct nvmm_vcpu_conf_tpr {
302	uint32_t exit_changed:1;
303	uint32_t rsvd:31;
304};
305
306#define nvmm_vcpu_exit		nvmm_x86_exit
307#define nvmm_vcpu_event		nvmm_x86_event
308#define nvmm_vcpu_state		nvmm_x64_state
309
310#ifdef _KERNEL
311#define NVMM_X86_MACH_NCONF	0
312#define NVMM_X86_VCPU_NCONF	2
313struct nvmm_x86_cpuid_mask {
314	uint32_t eax;
315	uint32_t ebx;
316	uint32_t ecx;
317	uint32_t edx;
318};
319extern const struct nvmm_x64_state nvmm_x86_reset_state;
320extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000001;
321extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000007;
322extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000001;
323extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000007;
324extern const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000008;
325bool nvmm_x86_pat_validate(uint64_t);
326#endif
327
328#endif /* ASM_NVMM */
329
330#endif /* _NVMM_X86_H_ */