xref: /illumos-gate/usr/src/uts/intel/sys/vmm_data.h (revision a1d41cf940fc4cda50098ad61e6a78b19c7483cd)
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 #define	VDC_VMM_TIME	13	/* Time-related VMM data */
39 
40 /* Indicates top of VMM Data Class range, updated as classes are added */
41 #define	VDC_MAX		(VDC_VMM_TIME + 1)
42 
43 
44 /* VMM Data Identifiers */
45 
46 /*
47  * Generic field encoding for 64-bit (or smaller) data which are identified by a
48  * 32-bit (or smaller) name.
49  *
50  * Used by the following classes/version:
51  * - VDC_REGISTER v1: `vm_reg_name` identifiers
52  * - VDC_MSR v1: MSR identifiers
53  * - VDC_VMM_ARCH v1: Identifiers described below
54  */
55 struct vdi_field_entry_v1 {
56 	uint32_t	vfe_ident;
57 	uint32_t	_pad;
58 	uint64_t	vfe_value;
59 };
60 
61 /* VDC_VERSION */
62 struct vdi_version_entry_v1 {
63 	uint16_t	vve_class;
64 	uint16_t	vve_version;
65 	uint16_t	vve_len_expect;
66 	uint16_t	vve_len_per_item;
67 };
68 
69 /*
70  * VDC_FPU:
71  *
72  * Unimplemented for now.  Use VM_GET_FPU/VM_SET_FPU ioctls.
73  */
74 
75 /* VDC_LAPIC: */
76 
77 struct vdi_lapic_page_v1 {
78 	uint32_t	vlp_id;
79 	uint32_t	vlp_version;
80 	uint32_t	vlp_tpr;
81 	uint32_t	vlp_apr;
82 	uint32_t	vlp_ldr;
83 	uint32_t	vlp_dfr;
84 	uint32_t	vlp_svr;
85 	uint32_t	vlp_isr[8];
86 	uint32_t	vlp_tmr[8];
87 	uint32_t	vlp_irr[8];
88 	uint32_t	vlp_esr;
89 	uint32_t	vlp_lvt_cmci;
90 	uint64_t	vlp_icr;
91 	uint32_t	vlp_lvt_timer;
92 	uint32_t	vlp_lvt_thermal;
93 	uint32_t	vlp_lvt_pcint;
94 	uint32_t	vlp_lvt_lint0;
95 	uint32_t	vlp_lvt_lint1;
96 	uint32_t	vlp_lvt_error;
97 	uint32_t	vlp_icr_timer;
98 	uint32_t	vlp_dcr_timer;
99 };
100 
101 struct vdi_lapic_v1 {
102 	struct vdi_lapic_page_v1 vl_lapic;
103 	uint64_t		vl_msr_apicbase;
104 	int64_t			vl_timer_target;
105 	uint32_t		vl_esr_pending;
106 };
107 
108 /*
109  * VDC_VMM_ARCH:
110  */
111 
112 /*
113  * Version 1 identifiers:
114  */
115 
116 /*
117  * VM-wide:
118  */
119 
120 /* Is the VM currently in the "paused" state? (0 or 1) */
121 #define	VAI_VM_IS_PAUSED	4
122 
123 /*
124  * per-vCPU:
125  *
126  * Note: While these are currently defined with values disjoint from those in
127  * the VM-wide category, it is not required that they be.  The VM-wide and
128  * per-vCPU identifiers are distinguished by vm_data_xfer`vdx_vcpuid.
129  */
130 
131 /* NMI pending injection for vCPU (0 or 1) */
132 #define	VAI_PEND_NMI		10
133 /* extint pending injection for vCPU (0 or 1) */
134 #define	VAI_PEND_EXTINT		11
135 /* HW exception pending injection for vCPU */
136 #define	VAI_PEND_EXCP		12
137 /* exception/interrupt pending injection for vCPU */
138 #define	VAI_PEND_INTINFO	13
139 
140 /* VDC_IOAPIC: */
141 
142 struct vdi_ioapic_v1 {
143 	uint64_t	vi_pin_reg[32];
144 	uint32_t	vi_pin_level[32];
145 	uint32_t	vi_id;
146 	uint32_t	vi_reg_sel;
147 };
148 
149 /* VDC_ATPIT: */
150 
151 struct vdi_atpit_channel_v1 {
152 	uint16_t	vac_initial;
153 	uint16_t	vac_reg_cr;
154 	uint16_t	vac_reg_ol;
155 	uint8_t		vac_reg_status;
156 	uint8_t		vac_mode;
157 	/*
158 	 * vac_status bits:
159 	 * - 0b00001 status latched
160 	 * - 0b00010 output latched
161 	 * - 0b00100 control register sel
162 	 * - 0b01000 output latch sel
163 	 * - 0b10000 free-running timer
164 	 */
165 	uint8_t		vac_status;
166 
167 	int64_t		vac_time_target;
168 };
169 
170 struct vdi_atpit_v1 {
171 	struct vdi_atpit_channel_v1 va_channel[3];
172 };
173 
174 /* VDC_ATPIC: */
175 
176 struct vdi_atpic_chip_v1 {
177 	uint8_t		vac_icw_state;
178 	/*
179 	 * vac_status bits:
180 	 * - 0b00000001 ready
181 	 * - 0b00000010 auto EOI
182 	 * - 0b00000100 poll
183 	 * - 0b00001000 rotate
184 	 * - 0b00010000 special full nested
185 	 * - 0b00100000 read isr next
186 	 * - 0b01000000 intr raised
187 	 * - 0b10000000 special mask mode
188 	 */
189 	uint8_t		vac_status;
190 	uint8_t		vac_reg_irr;
191 	uint8_t		vac_reg_isr;
192 	uint8_t		vac_reg_imr;
193 	uint8_t		vac_irq_base;
194 	uint8_t		vac_lowprio;
195 	uint8_t		vac_elc;
196 	uint32_t	vac_level[8];
197 };
198 
199 struct vdi_atpic_v1 {
200 	struct vdi_atpic_chip_v1 va_chip[2];
201 };
202 
203 /* VDC_HPET: */
204 
205 struct vdi_hpet_timer_v1 {
206 	uint64_t	vht_config;
207 	uint64_t	vht_msi;
208 	uint32_t	vht_comp_val;
209 	uint32_t	vht_comp_rate;
210 	int64_t		vht_time_target;
211 };
212 
213 struct vdi_hpet_v1 {
214 	uint64_t	vh_config;
215 	uint64_t	vh_isr;
216 	uint32_t	vh_count_base;
217 	int64_t		vh_time_base;
218 
219 	struct vdi_hpet_timer_v1	vh_timers[8];
220 };
221 
222 /* VDC_PM_TIMER: */
223 
224 struct vdi_pm_timer_v1 {
225 	int64_t		vpt_time_base;
226 	/*
227 	 * Since the PM-timer IO port registration can be set by a dedicated
228 	 * ioctl today, it is considered a read-only field in the vmm data
229 	 * interface and its contents will be ignored when writing state data to
230 	 * the timer.
231 	 */
232 	uint16_t	vpt_ioport;
233 };
234 
235 /* VDC_RTC: */
236 
237 struct vdi_rtc_v2 {
238 	int64_t		vr_base_clock;
239 	int64_t		vr_last_period;
240 	uint8_t		vr_content[128];
241 	uint8_t		vr_addr;
242 };
243 
244 /* VDC_VMM_TIME: */
245 
246 /*
247  * Interface for modifying time-related data of a guest, allowing the guest's
248  * TSC and device timers to continue working across inter-machine live
249  * migrations.
250  *
251  * Reads of this data will populate all fields, including:
252  * - current guest TSC (a calculated value)
253  * - guest TSC frequency
254  * - guest boot_time, which tracks the offset of the guest boot based on host
255  *   hrtime
256  * - current host hrtime and wall clock time (hrestime) at the time of read
257  *
258  * Callers writing this data may want to make adjustments to the guest TSC based
259  * on the time between read and write, such as in the case of a migration.
260  * For migrations between machines, the boot_hrtime must also be updated based
261  * on the hrtime of the target system. Callers should populate the host time
262  * fields for the host the write is performed on. These fields are used by the
263  * write interface to make additional adjustments to the guest fields to account
264  * for latency between the userspace adjustment and kernel receipt of those
265  * values.
266  */
267 struct vdi_time_info_v1 {
268 	/* guest-related fields */
269 	uint64_t	vt_guest_freq;	/* guest TSC frequency (hz) */
270 	uint64_t	vt_guest_tsc;	/* current guest TSC */
271 	int64_t		vt_boot_hrtime; /* guest boot_hrtime */
272 
273 	/* host time fields */
274 	int64_t		vt_hrtime;	/* host hrtime (ns) */
275 	uint64_t	vt_hres_sec;	/* host hrestime (sec) */
276 	uint64_t	vt_hres_ns;	/* host hrestime (ns) */
277 };
278 
279 #endif /* _VMM_DATA_H_ */
280