xref: /illumos-gate/usr/src/uts/intel/sys/vmm_data.h (revision 0dd92943)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 /* This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE */
12 
13 /*
14  * Copyright 2023 Oxide Computer Company
15  */
16 
17 #ifndef _VMM_DATA_H_
18 #define	_VMM_DATA_H_
19 
20 /* VMM Data Classes */
21 #define	VDC_VERSION	1	/* Version information for each data class */
22 
23 /* Classes bearing per-CPU data */
24 #define	VDC_REGISTER	2	/* Registers (GPR, segment, etc) */
25 #define	VDC_MSR		3	/* Model-specific registers */
26 #define	VDC_FPU		4	/* FPU (and associated SIMD) */
27 #define	VDC_LAPIC	5	/* Local APIC */
28 #define	VDC_VMM_ARCH	6	/* Arch-specific VMM state (VMX/SVM) */
29 
30 /* Classes for system-wide devices */
31 #define	VDC_IOAPIC	7	/* bhyve IO-APIC */
32 #define	VDC_ATPIT	8	/* i8254 PIT */
33 #define	VDC_ATPIC	9	/* i8259 PIC */
34 #define	VDC_HPET	10	/* HPET */
35 #define	VDC_PM_TIMER	11	/* ACPI Power Management Timer */
36 #define	VDC_RTC		12	/* IBM PC Real Time Clock */
37 
38 /* Indicates top of VMM Data Class range, updated as classes are added */
39 #define	VDC_MAX		(VDC_RTC + 1)
40 
41 
42 /* VMM Data Identifiers */
43 
44 /*
45  * Generic field encoding for 64-bit (or smaller) data which are identified by a
46  * 32-bit (or smaller) name.
47  *
48  * Used by the following classes/version:
49  * - VDC_REGISTER v1: `vm_reg_name` identifiers
50  * - VDC_MSR v1: MSR identifiers
51  * - VDC_VMM_ARCH v1: Identifiers described below
52  */
53 struct vdi_field_entry_v1 {
54 	uint32_t	vfe_ident;
55 	uint32_t	_pad;
56 	uint64_t	vfe_value;
57 };
58 
59 /* VDC_VERSION */
60 struct vdi_version_entry_v1 {
61 	uint16_t	vve_class;
62 	uint16_t	vve_version;
63 	uint16_t	vve_len_expect;
64 	uint16_t	vve_len_per_item;
65 };
66 
67 /*
68  * VDC_FPU:
69  *
70  * Unimplemented for now.  Use VM_GET_FPU/VM_SET_FPU ioctls.
71  */
72 
73 /* VDC_LAPIC: */
74 
75 struct vdi_lapic_page_v1 {
76 	uint32_t	vlp_id;
77 	uint32_t	vlp_version;
78 	uint32_t	vlp_tpr;
79 	uint32_t	vlp_apr;
80 	uint32_t	vlp_ldr;
81 	uint32_t	vlp_dfr;
82 	uint32_t	vlp_svr;
83 	uint32_t	vlp_isr[8];
84 	uint32_t	vlp_tmr[8];
85 	uint32_t	vlp_irr[8];
86 	uint32_t	vlp_esr;
87 	uint32_t	vlp_lvt_cmci;
88 	uint64_t	vlp_icr;
89 	uint32_t	vlp_lvt_timer;
90 	uint32_t	vlp_lvt_thermal;
91 	uint32_t	vlp_lvt_pcint;
92 	uint32_t	vlp_lvt_lint0;
93 	uint32_t	vlp_lvt_lint1;
94 	uint32_t	vlp_lvt_error;
95 	uint32_t	vlp_icr_timer;
96 	uint32_t	vlp_dcr_timer;
97 };
98 
99 struct vdi_lapic_v1 {
100 	struct vdi_lapic_page_v1 vl_lapic;
101 	uint64_t		vl_msr_apicbase;
102 	int64_t			vl_timer_target;
103 	uint32_t		vl_esr_pending;
104 };
105 
106 /*
107  * VDC_VMM_ARCH:
108  */
109 
110 /*
111  * Version 1 identifiers:
112  */
113 
114 /*
115  * VM-wide:
116  */
117 
118 /* Offset of guest TSC from system at time of boot */
119 #define	VAI_TSC_BOOT_OFFSET	1
120 /* Time that guest (nominally) booted, as hrtime */
121 #define	VAI_BOOT_HRTIME		2
122 /* Guest TSC frequency measured by hrtime (not effected by wall clock adj.) */
123 #define	VAI_TSC_FREQ		3
124 /* Is the VM currently in the "paused" state? (0 or 1) */
125 #define	VAI_VM_IS_PAUSED	4
126 
127 /*
128  * per-vCPU:
129  *
130  * Note: While these are currently defined with values disjoint from those in
131  * the VM-wide category, it is not required that they be.  The VM-wide and
132  * per-vCPU identifiers are distinguished by vm_data_xfer`vdx_vcpuid.
133  */
134 
135 /* NMI pending injection for vCPU (0 or 1) */
136 #define	VAI_PEND_NMI		10
137 /* extint pending injection for vCPU (0 or 1) */
138 #define	VAI_PEND_EXTINT		11
139 /* HW exception pending injection for vCPU */
140 #define	VAI_PEND_EXCP		12
141 /* exception/interrupt pending injection for vCPU */
142 #define	VAI_PEND_INTINFO	13
143 
144 
145 /* VDC_IOAPIC: */
146 
147 struct vdi_ioapic_v1 {
148 	uint64_t	vi_pin_reg[32];
149 	uint32_t	vi_pin_level[32];
150 	uint32_t	vi_id;
151 	uint32_t	vi_reg_sel;
152 };
153 
154 /* VDC_ATPIT: */
155 
156 struct vdi_atpit_channel_v1 {
157 	uint16_t	vac_initial;
158 	uint16_t	vac_reg_cr;
159 	uint16_t	vac_reg_ol;
160 	uint8_t		vac_reg_status;
161 	uint8_t		vac_mode;
162 	/*
163 	 * vac_status bits:
164 	 * - 0b00001 status latched
165 	 * - 0b00010 output latched
166 	 * - 0b00100 control register sel
167 	 * - 0b01000 output latch sel
168 	 * - 0b10000 free-running timer
169 	 */
170 	uint8_t		vac_status;
171 
172 	int64_t		vac_time_target;
173 };
174 
175 struct vdi_atpit_v1 {
176 	struct vdi_atpit_channel_v1 va_channel[3];
177 };
178 
179 /* VDC_ATPIC: */
180 
181 struct vdi_atpic_chip_v1 {
182 	uint8_t		vac_icw_state;
183 	/*
184 	 * vac_status bits:
185 	 * - 0b00000001 ready
186 	 * - 0b00000010 auto EOI
187 	 * - 0b00000100 poll
188 	 * - 0b00001000 rotate
189 	 * - 0b00010000 special full nested
190 	 * - 0b00100000 read isr next
191 	 * - 0b01000000 intr raised
192 	 * - 0b10000000 special mask mode
193 	 */
194 	uint8_t		vac_status;
195 	uint8_t		vac_reg_irr;
196 	uint8_t		vac_reg_isr;
197 	uint8_t		vac_reg_imr;
198 	uint8_t		vac_irq_base;
199 	uint8_t		vac_lowprio;
200 	uint8_t		vac_elc;
201 	uint32_t	vac_level[8];
202 };
203 
204 struct vdi_atpic_v1 {
205 	struct vdi_atpic_chip_v1 va_chip[2];
206 };
207 
208 /* VDC_HPET: */
209 
210 struct vdi_hpet_timer_v1 {
211 	uint64_t	vht_config;
212 	uint64_t	vht_msi;
213 	uint32_t	vht_comp_val;
214 	uint32_t	vht_comp_rate;
215 	int64_t		vht_time_target;
216 };
217 
218 struct vdi_hpet_v1 {
219 	uint64_t	vh_config;
220 	uint64_t	vh_isr;
221 	uint32_t	vh_count_base;
222 	int64_t		vh_time_base;
223 
224 	struct vdi_hpet_timer_v1	vh_timers[8];
225 };
226 
227 /* VDC_PM_TIMER: */
228 
229 struct vdi_pm_timer_v1 {
230 	int64_t		vpt_time_base;
231 	/*
232 	 * Since the PM-timer IO port registration can be set by a dedicated
233 	 * ioctl today, it is considered a read-only field in the vmm data
234 	 * interface and its contents will be ignored when writing state data to
235 	 * the timer.
236 	 */
237 	uint16_t	vpt_ioport;
238 };
239 
240 /* VDC_RTC: */
241 
242 struct vdi_rtc_v1 {
243 	uint8_t		vr_content[128];
244 	uint8_t		vr_addr;
245 	int64_t		vr_time_base;
246 	uint64_t	vr_rtc_sec;
247 	uint64_t	vr_rtc_nsec;
248 };
249 
250 #endif /* _VMM_DATA_H_ */
251