Skip to main content

openvmm_defs/
config.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Configuration for the VM worker.
5
6pub use serial_uart_resources::UartId;
7pub use smbios_defs::SmbiosBiosOverrides;
8pub use smbios_defs::SmbiosConfig;
9pub use smbios_defs::SmbiosSystemOverrides;
10
11use guid::Guid;
12use input_core::InputData;
13use memory_range::MemoryRange;
14use mesh::MeshPayload;
15use mesh::payload::Protobuf;
16use net_backend_resources::mac_address::MacAddress;
17use openvmm_pcat_locator::RomFileLocation;
18use std::fs::File;
19use tpm_resources::TpmVersion;
20use vm_resource::Resource;
21use vm_resource::kind::PciDeviceHandleKind;
22use vm_resource::kind::VirtioDeviceHandle;
23use vm_resource::kind::VmbusDeviceHandleKind;
24use vmgs_resources::VmgsResource;
25use vmotherboard::ChipsetDeviceHandle;
26use vmotherboard::LegacyPciChipsetDeviceHandle;
27use vmotherboard::options::BaseChipsetManifest;
28use vmotherboard::options::VmChipsetCapabilities;
29
30#[derive(MeshPayload, Debug)]
31pub struct Config {
32    pub load_mode: LoadMode,
33    pub floppy_disks: Vec<floppy_resources::FloppyDiskConfig>,
34    pub ide_disks: Vec<ide_resources::IdeDeviceConfig>,
35    pub pcie_root_complexes: Vec<PcieRootComplexConfig>,
36    pub pcie_ecam_below_4gb: bool,
37    pub pcie_devices: Vec<PcieDeviceConfig>,
38    pub pcie_switches: Vec<PcieSwitchConfig>,
39    pub pcie_generic_initiators: Vec<PcieGenericInitiatorConfig>,
40    pub vpci_devices: Vec<VpciDeviceConfig>,
41    pub numa: NumaTopology,
42    pub processor_topology: ProcessorTopologyConfig,
43    pub hypervisor: HypervisorConfig,
44    pub chipset: BaseChipsetManifest,
45    pub vmbus: Option<VmbusConfig>,
46    pub vtl2_vmbus: Option<VmbusConfig>,
47    #[cfg(windows)]
48    pub kernel_vmnics: Vec<KernelVmNicConfig>,
49    pub input: mesh::Receiver<InputData>,
50    pub framebuffer: Option<framebuffer::Framebuffer>,
51    pub vga_firmware: Option<RomFileLocation>,
52    pub vtl2_gfx: bool,
53    pub virtio_devices: Vec<(VirtioBus, Resource<VirtioDeviceHandle>)>,
54    #[cfg(windows)]
55    pub vpci_resources: Vec<virt_whp::device::DeviceHandle>,
56    pub vmgs: Option<VmgsResource>,
57    // TODO: move FirmwareEvent somewhere not GED-specific.
58    pub firmware_event_send: Option<mesh::Sender<get_resources::ged::FirmwareEvent>>,
59    pub debugger_rpc: Option<mesh::Receiver<vmm_core_defs::debug_rpc::DebugRequest>>,
60    pub vmbus_devices: Vec<(DeviceVtl, Resource<VmbusDeviceHandleKind>)>,
61    pub chipset_devices: Vec<ChipsetDeviceHandle>,
62    pub pci_chipset_devices: Vec<LegacyPciChipsetDeviceHandle>,
63    pub isa_dma_controller: Option<Resource<vm_resource::kind::IsaDmaControllerHandleKind>>,
64    pub chipset_capabilities: VmChipsetCapabilities,
65    /// Memory layout sizing for the layout engine. Determines chipset MMIO
66    /// range sizes; addresses are allocated dynamically by the resolver.
67    pub layout: vmm_core_defs::LayoutConfig,
68    // This is used for testing. TODO: resourcify, and also store this in VMGS.
69    pub rtc_delta_milliseconds: i64,
70}
71
72pub const DEFAULT_GIC_DISTRIBUTOR_BASE: u64 = 0xFFFF_0000;
73// The KVM in-kernel vGICv3 requires the distributor and redistributor bases be 64KiB aligned.
74pub const DEFAULT_GIC_REDISTRIBUTORS_BASE: u64 = if cfg!(target_os = "linux") {
75    0xEFFF_0000
76} else {
77    0xEFFE_E000
78};
79
80/// Base address of the guest-visible GIC v2m MSI frame (exposed via the MADT
81/// and used by the software v2m SETSPI decoder for emulated devices). This is
82/// OpenVMM-emulated MMIO (one 4 KiB page), not shadowed by the hypervisor, so
83/// it stays at the conventional address.
84pub const DEFAULT_GIC_V2M_MSI_FRAME_BASE: u64 = 0xEFFE_8000;
85/// Size of the v2m MSI frame (one 4KB page is the architectural minimum).
86pub const GIC_V2M_MSI_FRAME_SIZE: u64 = 0x1000;
87
88/// Default device-assignment MSI IOVA reservation for a physical SMMU
89/// implementation that lets the VMM select the range. The base follows the
90/// Hyper-V convention; 1 MiB matches Linux's Arm SMMU reservation size.
91pub const DEFAULT_DEVICE_ASSIGNMENT_MSI_IOVA_RANGE: MemoryRange =
92    MemoryRange::new(0xEFF6_8000..0xF006_8000);
93
94/// Base address of the GICv3 ITS MMIO region. Must be 64 KiB aligned,
95/// below the v2m frame address, and not overlap other devices.
96/// The region extends from this base to base + GIC_ITS_SIZE (128 KiB).
97pub const DEFAULT_GIC_ITS_BASE: u64 = 0xEFFC_0000;
98/// Size of the ITS MMIO region (control frame + translation frame, 2×64 KiB).
99pub const GIC_ITS_SIZE: u64 = 0x2_0000;
100
101/// Default virtual timer PPI (GIC INTID). PPI 4 = INTID 16 + 4 = 20.
102/// This is the EL1 virtual timer interrupt used across Hyper-V, KVM, and HVF.
103pub const DEFAULT_VIRT_TIMER_PPI: u32 = 20;
104
105/// Default total number of GIC interrupts (SGIs + PPIs + SPIs).
106/// Must satisfy KVM constraints: 64 <= n <= 1023, multiple of 32.
107/// 992 = 31 × 32 is the largest valid value.
108pub const DEFAULT_GIC_NR_IRQS: u32 = 992;
109
110/// Default VMBus PPI (GIC INTID). PPI 2 = INTID 16 + 2 = 18.
111pub const DEFAULT_VMBUS_PPI: u32 = 18;
112
113/// Default IOAPIC interrupt for the ACPI power button on x86_64.
114pub const DEFAULT_ACPI_POWER_BUTTON_IRQ_X64: u32 = 10;
115/// Default GIC SPI index (INTID 39) for the ACPI power button on AArch64.
116///
117/// Firmware reserves INTIDs 35-38 for generation ID, battery, PMEM, and
118/// processor-idle events.
119pub const DEFAULT_ACPI_POWER_BUTTON_SPI_AARCH64: u32 = 7;
120
121/// How firmware tables are presented to the guest in Linux direct boot.
122///
123/// On x86, `DeviceTree` is not supported and will be rejected. On aarch64,
124/// this selects between a full device tree or an ACPI boot path.
125#[derive(MeshPayload, Debug, Clone, Copy, PartialEq, Eq)]
126pub enum LinuxDirectBootMode {
127    /// Full device tree with all devices described in DT nodes (aarch64 only).
128    DeviceTree,
129    /// ACPI tables for device discovery. On aarch64, this also synthesizes
130    /// an EFI system table so the kernel enters its ACPI code path. On x86,
131    /// ACPI tables are always provided via the zero page.
132    Acpi,
133}
134
135/// Isolation-specific settings for Linux direct boot.
136#[derive(MeshPayload, Debug, Clone, Copy, PartialEq, Eq)]
137pub enum LinuxIsolationConfig {
138    /// No isolation-specific loader configuration.
139    None,
140    /// AMD SEV-SNP loader configuration.
141    Snp {
142        /// Enables restricted interrupt injection in the SNP VMSA.
143        restricted_injection: bool,
144    },
145}
146
147#[derive(MeshPayload, Debug)]
148pub enum LoadMode {
149    Linux {
150        kernel: File,
151        initrd: Option<File>,
152        cmdline: String,
153        enable_serial: bool,
154        isolation: LinuxIsolationConfig,
155        boot_mode: LinuxDirectBootMode,
156        // Boxed to keep the `Linux` variant from dominating `LoadMode`'s size.
157        smbios: Box<SmbiosConfig>,
158    },
159    Uefi {
160        firmware: File,
161        enable_debugging: bool,
162        enable_memory_protections: bool,
163        disable_frontpage: bool,
164        tpm_version: Option<TpmVersion>,
165        enable_battery: bool,
166        enable_serial: bool,
167        enable_vpci_boot: bool,
168        uefi_console_mode: Option<UefiConsoleMode>,
169        default_boot_always_attempt: bool,
170        // Boxed to keep the `Uefi` variant from dominating `LoadMode`'s size.
171        // The VM's BIOS GUID is sourced from `smbios.system.uuid`, so UEFI and
172        // Linux direct boot share a single UUID origin.
173        smbios: Box<SmbiosConfig>,
174        enable_vmbus: bool,
175        force_dma_bounce: bool,
176        enable_hv: bool,
177        /// Whether the guest firmware should enable hibernation (S4) support.
178        hibernation_enabled: bool,
179        force_firmware_version: bool,
180    },
181    Pcat {
182        firmware: RomFileLocation,
183        boot_order: [PcatBootDevice; 4],
184        /// Whether the guest firmware should enable hibernation (S4) support.
185        hibernation_enabled: bool,
186        // Boxed to keep the `Pcat` variant from dominating `LoadMode`'s size.
187        // Only the system UUID and serial number are honored; the PCAT BIOS ROM
188        // self-describes everything else, so other overrides are rejected.
189        smbios: Box<SmbiosConfig>,
190    },
191    Igvm {
192        file: File,
193        cmdline: String,
194        vtl2_base_address: Vtl2BaseAddressType,
195        com_serial: Option<UartId>,
196        personality: IgvmPersonality,
197    },
198    None,
199}
200
201/// The firmware that an IGVM file contains.
202#[derive(Debug, Clone, Copy, PartialEq, Eq, MeshPayload)]
203pub enum IgvmPersonality {
204    /// The OpenHCL paravisor, hosted in VTL2.
205    Openhcl,
206    /// UEFI firmware.
207    Uefi,
208    /// A Linux kernel.
209    LinuxDirect,
210}
211
212/// Different types to specify the base address for the VTL2 region of the IGVM
213/// file.
214#[derive(Debug, Clone, Copy, MeshPayload)]
215pub enum Vtl2BaseAddressType {
216    /// Use the addresses specified in the file. The IGVM file does not need to
217    /// support relocations.
218    File,
219    /// Put VTL2 at the specified address. The IGVM file must support
220    /// relocations.
221    Absolute(u64),
222    /// Use the specified range in the supplied MemoryLayout, as the caller has
223    /// created a specific range for VTL2. The IGVM file must support
224    /// relocations.
225    ///
226    /// An optional size may be specified to override the size describing VTL2
227    /// provided in the IGVM file. It must be larger than the IGVM file provided
228    /// size.
229    MemoryLayout { size: Option<u64> },
230    /// Tell VTL2 to allocate out it's own memory. This will load the file at
231    /// the base address specified in the file, and the host will tell VTL2 the
232    /// size of memory to allocate for itself.
233    ///
234    /// An optional size may be specified to override the size describing VTL2
235    /// provided in the IGVM file. It must be larger than the IGVM file provided
236    /// size.
237    Vtl2Allocate { size: Option<u64> },
238}
239
240/// Specifies a PCIe MMIO BAR window, either by size (the resolver allocates) or
241/// by a fixed location. Fixed locations exist for assigned-device, IOMMU, and
242/// physical-topology compatibility.
243#[derive(Debug, MeshPayload)]
244pub enum PcieMmioRangeConfig {
245    /// Dynamically allocate a range of the given size.
246    Dynamic {
247        /// Size of the range in bytes.
248        size: u64,
249    },
250    /// Use the specified fixed memory range.
251    Fixed(MemoryRange),
252}
253
254#[derive(Debug, MeshPayload)]
255pub struct RootComplexCxlConfig {
256    /// HDM window size in bytes for this CXL root complex.
257    pub hdm_size: u64,
258    /// CFMWS HDM window restrictions bitmask.
259    pub hdm_window_restrictions: u16,
260}
261
262#[derive(Debug, MeshPayload)]
263pub struct PcieRootComplexConfig {
264    pub index: u32,
265    pub name: String,
266    pub segment: u16,
267    pub start_bus: u8,
268    pub end_bus: u8,
269    /// Whether this root complex owns legacy PCI configuration I/O ports.
270    pub legacy_pci_config_io: bool,
271    pub low_mmio: PcieMmioRangeConfig,
272    pub high_mmio: PcieMmioRangeConfig,
273    pub ports: Vec<PciePortConfig>,
274    /// Optional CXL configuration for root-complex CXL mode.
275    pub cxl: Option<RootComplexCxlConfig>,
276    /// Optional IOMMU for this root complex.
277    pub iommu: Option<PcieIommuConfig>,
278    /// NUMA node affinity for this root complex. Used to generate `_PXM` in
279    /// the ACPI SSDT so the guest OS sees correct NUMA locality for devices
280    /// under this root complex.
281    pub vnode: Option<u32>,
282    /// When true, treat non-zero BAR values found during probing as pinned
283    /// addresses. Used for P2P DMA with GPA = HPA.
284    pub preserve_bars: bool,
285}
286
287/// Configuration for a single PCIe port — either a root-complex root port or a
288/// switch downstream port.
289#[derive(Debug, MeshPayload)]
290pub struct PciePortConfig {
291    /// Port name used for topology wiring and lookup.
292    pub name: String,
293    /// The device/function (`device << 3 | function`) to place this port at on
294    /// its bus.
295    ///
296    /// When `None`, the port is assigned the lowest available devfn. Ports are
297    /// assigned in order, so an explicit devfn that collides with a
298    /// previously-assigned port (including one assigned automatically) is an
299    /// error. Honored for both root-complex root ports and switch downstream
300    /// ports.
301    pub devfn: Option<u8>,
302    /// Enables PCIe hotplug capabilities for this port.
303    pub hotplug: bool,
304    /// Optional ACS capability bitmask to expose on this port.
305    pub acs_capabilities_supported: Option<u16>,
306    /// Marks this port as CXL-capable.
307    ///
308    /// Runtime port construction derives required BAR/subregion layout from
309    /// this flag (currently CXL component registers for BAR0).
310    pub cxl: bool,
311    /// Enables PASID support for functions downstream of this port.
312    pub pasid: bool,
313}
314
315#[derive(Debug, MeshPayload)]
316pub struct PcieSwitchConfig {
317    pub name: String,
318    pub parent_port: String,
319    /// The downstream ports of this switch.
320    pub ports: Vec<PciePortConfig>,
321}
322
323/// Declares that the device directly behind a named PCIe port (a root port or
324/// a switch downstream port) is a generic initiator (GI) for the given NUMA
325/// node. Used to generate an SRAT Generic Initiator Affinity structure so the
326/// guest attaches the device's memory to that (typically CPU-less) proximity
327/// domain.
328///
329/// The port is resolved against the live topology by port name after switch
330/// downstream ports have been enumerated, so it can target devices that sit
331/// behind a switch.
332#[derive(Debug, MeshPayload)]
333pub struct PcieGenericInitiatorConfig {
334    /// Name of the PCIe port (root port or switch downstream port) behind
335    /// which the generic-initiator device resides.
336    pub port_name: String,
337    /// NUMA node the device is a generic initiator for.
338    pub node: u32,
339}
340
341#[derive(Debug, MeshPayload)]
342pub struct PcieDeviceConfig {
343    pub port_name: String,
344    pub resource: Resource<PciDeviceHandleKind>,
345}
346
347#[derive(Debug, MeshPayload)]
348pub struct VpciDeviceConfig {
349    pub vtl: DeviceVtl,
350    /// The ID of the device. Vpci devices are identified by a portion of `data2` and `data3` of the
351    /// instance ID, which is used to generate the guest-visible device ID.
352    pub instance_id: Guid,
353    pub resource: Resource<PciDeviceHandleKind>,
354    /// NUMA node affinity for this VPCI device.
355    pub vnode: Option<u32>,
356}
357
358#[derive(Debug, Protobuf)]
359pub struct ProcessorTopologyConfig {
360    pub proc_count: u32,
361    pub vps_per_socket: Option<u32>,
362    pub enable_smt: Option<bool>,
363    pub arch: Option<ArchTopologyConfig>,
364}
365
366#[derive(Debug, Protobuf, Default, Clone)]
367pub struct X86TopologyConfig {
368    pub apic_id_offset: u32,
369    pub x2apic: X2ApicConfig,
370}
371
372#[derive(Debug, Default, Copy, Clone, Protobuf)]
373pub enum X2ApicConfig {
374    #[default]
375    /// Support the X2APIC if recommended by the hypervisor or if needed by the
376    /// topology configuration.
377    Auto,
378    /// Support the X2APIC, and automatically enable it if needed to address all
379    /// processors.
380    Supported,
381    /// Do not support the X2APIC.
382    Unsupported,
383    /// Support and enable the X2APIC.
384    Enabled,
385}
386
387#[derive(Debug, Protobuf, Default, Clone)]
388pub enum PmuGsivConfig {
389    #[default]
390    /// Use the hypervisor's platform GSIV value for the PMU.
391    Platform,
392    /// Use the specified GSIV value for the PMU.
393    Gsiv(u32),
394    /// Disable the PMU.
395    Disabled,
396}
397
398/// MSI controller selection for aarch64 PCIe interrupt delivery.
399#[derive(Debug, Protobuf, Default, Clone)]
400pub enum GicMsiConfig {
401    /// Automatically select the best available MSI controller:
402    /// ITS when the hypervisor supports it, otherwise GICv2m.
403    #[default]
404    Auto,
405    /// Force GICv3 ITS for MSI delivery via LPIs.
406    Its,
407    /// Force GICv2m for MSI delivery via SPIs.
408    V2m {
409        /// Number of SPIs to reserve for PCIe MSIs. Defaults to a
410        /// platform-specific value when `None`.
411        spi_count: Option<u32>,
412    },
413}
414
415/// IOMMU configuration for a single PCIe root complex.
416#[derive(Debug, MeshPayload, Clone)]
417pub enum PcieIommuConfig {
418    /// AMD IOMMU (AMD-Vi) for x86_64 guests.
419    AmdVi,
420    /// Arm SMMUv3 for aarch64 guests.
421    Smmu {
422        /// Enable HW-accelerated nested translation (iommufd). Requires VFIO
423        /// devices with `iommu=` behind this SMMU.
424        accel: bool,
425        /// Output address size (OAS) resolution policy.
426        oas: SmmuOas,
427        /// SubstreamID width (SSIDSIZE) resolution policy.
428        ssidsize: SmmuSsidSize,
429    },
430    /// Intel VT-d for x86_64 guests.
431    IntelVtd,
432}
433
434/// Output address size (OAS) policy for an emulated SMMUv3.
435#[derive(Debug, MeshPayload, Clone, Copy)]
436pub enum SmmuOas {
437    /// Advertise a fixed default OAS. See `DEFAULT_AUTO_OAS_BITS` for the
438    /// sizing policy and its limits.
439    Auto,
440    /// Use a fixed OAS in bits (one of 32, 36, 40, 42, 44, 48, 52).
441    Fixed(u8),
442}
443
444/// SubstreamID width (SSIDSIZE) policy for an emulated SMMUv3.
445#[derive(Debug, MeshPayload, Clone, Copy)]
446pub enum SmmuSsidSize {
447    /// Disable substreams in software mode; under acceleration, adopt the
448    /// host's width before device start freezes the capabilities.
449    Auto,
450    /// Use a fixed width in bits (0..=20). Zero disables substreams.
451    /// Under acceleration, this cannot exceed the host's width.
452    Fixed(u8),
453}
454
455#[derive(Debug, Protobuf, Default, Clone)]
456pub struct Aarch64TopologyConfig {
457    pub gic_config: Option<GicConfig>,
458    pub pmu_gsiv: PmuGsivConfig,
459    pub gic_msi: GicMsiConfig,
460}
461
462/// GIC configuration for the virtual machine.
463///
464/// The variant selects the GIC version. `None` inner config means use
465/// defaults for that version's addresses.
466#[derive(Debug, Protobuf, Clone)]
467pub enum GicConfig {
468    /// GICv2 with optional address overrides.
469    V2(Option<GicV2Config>),
470    /// GICv3 with optional address overrides.
471    V3(Option<GicV3Config>),
472}
473
474/// GICv2-specific address configuration.
475#[derive(Debug, Protobuf, Clone)]
476pub struct GicV2Config {
477    pub gic_distributor_base: u64,
478    pub cpu_interface_base: u64,
479}
480
481/// GICv3-specific address configuration.
482#[derive(Debug, Protobuf, Clone)]
483pub struct GicV3Config {
484    pub gic_distributor_base: u64,
485    pub gic_redistributors_base: u64,
486}
487
488#[derive(Debug, Protobuf, Clone)]
489pub enum ArchTopologyConfig {
490    X86(X86TopologyConfig),
491    Aarch64(Aarch64TopologyConfig),
492}
493
494/// Per-node memory allocation configuration.
495#[derive(Debug, Clone, Copy, MeshPayload)]
496pub struct MemoryConfig {
497    pub mem_size: u64,
498    pub prefetch_memory: bool,
499    pub private_memory: bool,
500    pub transparent_hugepages: bool,
501    pub hugepages: bool,
502    pub hugepage_size: Option<u64>,
503    /// Host physical NUMA node to bind this allocation to (Linux:
504    /// `mbind(MPOL_BIND)`). `None` means OS default placement.
505    pub host_numa_node: Option<u32>,
506}
507
508/// Virtual NUMA topology for the VM.
509#[derive(Debug, MeshPayload)]
510pub struct NumaTopology {
511    /// NUMA nodes. The vnode ID is the index into this vector.
512    pub nodes: Vec<NumaNode>,
513    /// Inter-node distances for the SLIT. If empty, defaults are used
514    /// (10 for self, 20 for cross-node).
515    pub distances: Vec<NumaDistance>,
516}
517
518/// A single virtual NUMA node.
519#[derive(Debug, MeshPayload)]
520pub struct NumaNode {
521    /// Memory allocation for this node. `None` means a CPU-only or
522    /// device-only node.
523    pub mem: Option<MemoryConfig>,
524    /// VP assignment for this node.
525    pub vps: VpAssignment,
526}
527
528/// How VPs are assigned to a NUMA node.
529#[derive(Debug, MeshPayload)]
530pub enum VpAssignment {
531    /// Assign VPs to nodes by round-robining sockets over the CPU-bearing
532    /// nodes only: a VP with socket ID `vp_index / vps_per_socket` belongs to
533    /// the `(vp_index / vps_per_socket) % num_cpu_nodes`-th `FromTopology`
534    /// node. `vps_per_socket` comes from `ProcessorTopologyConfig`;
535    /// `num_cpu_nodes` is the number of `FromTopology` nodes, so `Empty`
536    /// (CPU-less) nodes are skipped and do not affect the distribution.
537    FromTopology,
538    /// Explicit VP indices assigned to this node.
539    Explicit(Vec<u32>),
540    /// A CPU-less node: no VPs are assigned to it. Unlike `Explicit`, this
541    /// may be combined with `FromTopology` nodes, so a memory- or
542    /// device-only node can be declared without forcing every other node to
543    /// spell out its VP set.
544    Empty,
545}
546
547/// An inter-node distance entry for the ACPI SLIT.
548#[derive(Debug, MeshPayload)]
549pub struct NumaDistance {
550    /// Source node index.
551    pub src: u32,
552    /// Destination node index.
553    pub dst: u32,
554    /// Distance value (10 = local, 20 = default cross-node, 255 = unreachable).
555    pub distance: u8,
556}
557
558#[derive(Debug, MeshPayload, Default)]
559pub struct VmbusConfig {
560    pub vsock_listener: Option<unix_socket::UnixListener>,
561    pub vsock_path: Option<String>,
562    pub vmbus_max_version: Option<u32>,
563    #[cfg(windows)]
564    pub vmbusproxy_handle: Option<vmbus_proxy::ProxyHandle>,
565    pub vtl2_redirect: bool,
566}
567
568#[derive(Debug, MeshPayload, Default)]
569pub struct HypervisorConfig {
570    pub with_hv: bool,
571    pub with_vtl2: Option<Vtl2Config>,
572    pub with_isolation: Option<IsolationType>,
573    /// Expose hardware virtualization (VMX/SVM) to the guest so that it can run
574    /// its own hypervisor. A backend that does not recognize this request
575    /// rejects it rather than silently ignoring it (see
576    /// `virt::Hypervisor::recognizes_nested_virt`).
577    pub nested_virt: bool,
578}
579
580#[derive(Debug, MeshPayload)]
581pub struct KernelVmNicConfig {
582    pub instance_id: Guid,
583    pub mac_address: MacAddress,
584    pub switch_port_id: SwitchPortId,
585}
586
587#[derive(Clone, Debug, MeshPayload)]
588pub struct SwitchPortId {
589    pub switch: Guid,
590    pub port: Guid,
591}
592
593pub const DEFAULT_PCAT_BOOT_ORDER: [PcatBootDevice; 4] = [
594    PcatBootDevice::Optical,
595    PcatBootDevice::HardDrive,
596    PcatBootDevice::Network,
597    PcatBootDevice::Floppy,
598];
599
600#[derive(MeshPayload, Debug, Clone, Copy, PartialEq)]
601pub enum PcatBootDevice {
602    Floppy,
603    HardDrive,
604    Optical,
605    Network,
606}
607
608#[derive(Eq, PartialEq, Debug, Copy, Clone, MeshPayload)]
609pub enum VirtioBus {
610    Mmio,
611    Pci,
612}
613
614/// Policy for the partition when mapping VTL0 memory late.
615#[derive(Eq, PartialEq, Debug, Copy, Clone, MeshPayload)]
616pub enum LateMapVtl0MemoryPolicy {
617    /// Halt execution of the VP if VTL0 memory is accessed.
618    Halt,
619    /// Log the error but emulate the access with the instruction emulator.
620    Log,
621    /// Inject an exception into the guest.
622    InjectException,
623}
624
625impl From<LateMapVtl0MemoryPolicy> for virt::LateMapVtl0MemoryPolicy {
626    fn from(value: LateMapVtl0MemoryPolicy) -> Self {
627        match value {
628            LateMapVtl0MemoryPolicy::Halt => virt::LateMapVtl0MemoryPolicy::Halt,
629            LateMapVtl0MemoryPolicy::Log => virt::LateMapVtl0MemoryPolicy::Log,
630            LateMapVtl0MemoryPolicy::InjectException => {
631                virt::LateMapVtl0MemoryPolicy::InjectException
632            }
633        }
634    }
635}
636
637/// Configuration for VTL2.
638///
639/// NOTE: This is distinct from `virt::Vtl2Config` to keep an abstraction
640/// between the virt crate and this crate. Users should not be specifying
641/// virt crate configuration directly.
642#[derive(Debug, Clone, MeshPayload)]
643pub struct Vtl2Config {
644    /// Enable the VTL0 alias map. This maps VTL0's view of memory in VTL2 at
645    /// the highest legal physical address bit.
646    pub vtl0_alias_map: bool,
647    /// If set, map VTL0 memory late after VTL2 has started. The current
648    /// heuristic is to defer mapping VTL0 memory until the first
649    /// `HvModifyVtlProtectionMask` hypercall is made.
650    pub late_map_vtl0_memory: Option<LateMapVtl0MemoryPolicy>,
651}
652
653// Isolation type for a partition.
654#[derive(Eq, PartialEq, Debug, Copy, Clone, MeshPayload)]
655pub enum IsolationType {
656    Vbs,
657    Snp {
658        /// Optional host-provided data included in SNP launch finish.
659        host_data: Option<[u8; 32]>,
660    },
661    Cca,
662}
663
664impl From<IsolationType> for virt::IsolationType {
665    fn from(value: IsolationType) -> Self {
666        match value {
667            IsolationType::Vbs => Self::Vbs,
668            IsolationType::Snp { .. } => Self::Snp,
669            IsolationType::Cca => Self::Cca,
670        }
671    }
672}
673
674/// Which VTL to assign a particular device to.
675#[derive(Copy, Clone, Debug, PartialEq, Eq, MeshPayload)]
676pub enum DeviceVtl {
677    Vtl0,
678    Vtl1,
679    Vtl2,
680}
681
682#[derive(Copy, Clone, Debug, MeshPayload)]
683pub enum UefiConsoleMode {
684    Default,
685    Com1,
686    Com2,
687    None,
688}