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