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/// How firmware tables are presented to the guest in Linux direct boot.
114///
115/// On x86, `DeviceTree` is not supported and will be rejected. On aarch64,
116/// this selects between a full device tree or an ACPI boot path.
117#[derive(MeshPayload, Debug, Clone, Copy, PartialEq, Eq)]
118pub enum LinuxDirectBootMode {
119 /// Full device tree with all devices described in DT nodes (aarch64 only).
120 DeviceTree,
121 /// ACPI tables for device discovery. On aarch64, this also synthesizes
122 /// an EFI system table so the kernel enters its ACPI code path. On x86,
123 /// ACPI tables are always provided via the zero page.
124 Acpi,
125}
126
127/// Isolation-specific settings for Linux direct boot.
128#[derive(MeshPayload, Debug, Clone, Copy, PartialEq, Eq)]
129pub enum LinuxIsolationConfig {
130 /// No isolation-specific loader configuration.
131 None,
132 /// AMD SEV-SNP loader configuration.
133 Snp {
134 /// Enables restricted interrupt injection in the SNP VMSA.
135 restricted_injection: bool,
136 },
137}
138
139#[derive(MeshPayload, Debug)]
140pub enum LoadMode {
141 Linux {
142 kernel: File,
143 initrd: Option<File>,
144 cmdline: String,
145 enable_serial: bool,
146 isolation: LinuxIsolationConfig,
147 boot_mode: LinuxDirectBootMode,
148 // Boxed to keep the `Linux` variant from dominating `LoadMode`'s size.
149 smbios: Box<SmbiosConfig>,
150 },
151 Uefi {
152 firmware: File,
153 enable_debugging: bool,
154 enable_memory_protections: bool,
155 disable_frontpage: bool,
156 tpm_version: Option<TpmVersion>,
157 enable_battery: bool,
158 enable_serial: bool,
159 enable_vpci_boot: bool,
160 uefi_console_mode: Option<UefiConsoleMode>,
161 default_boot_always_attempt: bool,
162 // Boxed to keep the `Uefi` variant from dominating `LoadMode`'s size.
163 // The VM's BIOS GUID is sourced from `smbios.system.uuid`, so UEFI and
164 // Linux direct boot share a single UUID origin.
165 smbios: Box<SmbiosConfig>,
166 enable_vmbus: bool,
167 force_dma_bounce: bool,
168 enable_hv: bool,
169 /// Whether the guest firmware should enable hibernation (S4) support.
170 hibernation_enabled: bool,
171 force_firmware_version: bool,
172 },
173 Pcat {
174 firmware: RomFileLocation,
175 boot_order: [PcatBootDevice; 4],
176 /// Whether the guest firmware should enable hibernation (S4) support.
177 hibernation_enabled: bool,
178 // Boxed to keep the `Pcat` variant from dominating `LoadMode`'s size.
179 // Only the system UUID and serial number are honored; the PCAT BIOS ROM
180 // self-describes everything else, so other overrides are rejected.
181 smbios: Box<SmbiosConfig>,
182 },
183 Igvm {
184 file: File,
185 cmdline: String,
186 vtl2_base_address: Vtl2BaseAddressType,
187 com_serial: Option<UartId>,
188 personality: IgvmPersonality,
189 },
190 None,
191}
192
193/// The firmware that an IGVM file contains.
194#[derive(Debug, Clone, Copy, PartialEq, Eq, MeshPayload)]
195pub enum IgvmPersonality {
196 /// The OpenHCL paravisor, hosted in VTL2.
197 Openhcl,
198 /// UEFI firmware.
199 Uefi,
200 /// A Linux kernel.
201 LinuxDirect,
202}
203
204/// Different types to specify the base address for the VTL2 region of the IGVM
205/// file.
206#[derive(Debug, Clone, Copy, MeshPayload)]
207pub enum Vtl2BaseAddressType {
208 /// Use the addresses specified in the file. The IGVM file does not need to
209 /// support relocations.
210 File,
211 /// Put VTL2 at the specified address. The IGVM file must support
212 /// relocations.
213 Absolute(u64),
214 /// Use the specified range in the supplied MemoryLayout, as the caller has
215 /// created a specific range for VTL2. The IGVM file must support
216 /// relocations.
217 ///
218 /// An optional size may be specified to override the size describing VTL2
219 /// provided in the IGVM file. It must be larger than the IGVM file provided
220 /// size.
221 MemoryLayout { size: Option<u64> },
222 /// Tell VTL2 to allocate out it's own memory. This will load the file at
223 /// the base address specified in the file, and the host will tell VTL2 the
224 /// size of memory to allocate for itself.
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 Vtl2Allocate { size: Option<u64> },
230}
231
232/// Specifies a PCIe MMIO BAR window, either by size (the resolver allocates) or
233/// by a fixed location. Fixed locations exist for assigned-device, IOMMU, and
234/// physical-topology compatibility.
235#[derive(Debug, MeshPayload)]
236pub enum PcieMmioRangeConfig {
237 /// Dynamically allocate a range of the given size.
238 Dynamic {
239 /// Size of the range in bytes.
240 size: u64,
241 },
242 /// Use the specified fixed memory range.
243 Fixed(MemoryRange),
244}
245
246#[derive(Debug, MeshPayload)]
247pub struct RootComplexCxlConfig {
248 /// HDM window size in bytes for this CXL root complex.
249 pub hdm_size: u64,
250 /// CFMWS HDM window restrictions bitmask.
251 pub hdm_window_restrictions: u16,
252}
253
254#[derive(Debug, MeshPayload)]
255pub struct PcieRootComplexConfig {
256 pub index: u32,
257 pub name: String,
258 pub segment: u16,
259 pub start_bus: u8,
260 pub end_bus: u8,
261 pub low_mmio: PcieMmioRangeConfig,
262 pub high_mmio: PcieMmioRangeConfig,
263 pub ports: Vec<PciePortConfig>,
264 /// Optional CXL configuration for root-complex CXL mode.
265 pub cxl: Option<RootComplexCxlConfig>,
266 /// Optional IOMMU for this root complex.
267 pub iommu: Option<PcieIommuConfig>,
268 /// NUMA node affinity for this root complex. Used to generate `_PXM` in
269 /// the ACPI SSDT so the guest OS sees correct NUMA locality for devices
270 /// under this root complex.
271 pub vnode: Option<u32>,
272 /// When true, treat non-zero BAR values found during probing as pinned
273 /// addresses. Used for P2P DMA with GPA = HPA.
274 pub preserve_bars: bool,
275}
276
277/// Configuration for a single PCIe port — either a root-complex root port or a
278/// switch downstream port.
279#[derive(Debug, MeshPayload)]
280pub struct PciePortConfig {
281 /// Port name used for topology wiring and lookup.
282 pub name: String,
283 /// The device/function (`device << 3 | function`) to place this port at on
284 /// its bus.
285 ///
286 /// When `None`, the port is assigned the lowest available devfn. Ports are
287 /// assigned in order, so an explicit devfn that collides with a
288 /// previously-assigned port (including one assigned automatically) is an
289 /// error. Honored for both root-complex root ports and switch downstream
290 /// ports.
291 pub devfn: Option<u8>,
292 /// Enables PCIe hotplug capabilities for this port.
293 pub hotplug: bool,
294 /// Optional ACS capability bitmask to expose on this port.
295 pub acs_capabilities_supported: Option<u16>,
296 /// Marks this port as CXL-capable.
297 ///
298 /// Runtime port construction derives required BAR/subregion layout from
299 /// this flag (currently CXL component registers for BAR0).
300 pub cxl: bool,
301 /// Enables PASID support for functions downstream of this port.
302 pub pasid: bool,
303}
304
305#[derive(Debug, MeshPayload)]
306pub struct PcieSwitchConfig {
307 pub name: String,
308 pub parent_port: String,
309 /// The downstream ports of this switch.
310 pub ports: Vec<PciePortConfig>,
311}
312
313/// Declares that the device directly behind a named PCIe port (a root port or
314/// a switch downstream port) is a generic initiator (GI) for the given NUMA
315/// node. Used to generate an SRAT Generic Initiator Affinity structure so the
316/// guest attaches the device's memory to that (typically CPU-less) proximity
317/// domain.
318///
319/// The port is resolved against the live topology by port name after switch
320/// downstream ports have been enumerated, so it can target devices that sit
321/// behind a switch.
322#[derive(Debug, MeshPayload)]
323pub struct PcieGenericInitiatorConfig {
324 /// Name of the PCIe port (root port or switch downstream port) behind
325 /// which the generic-initiator device resides.
326 pub port_name: String,
327 /// NUMA node the device is a generic initiator for.
328 pub node: u32,
329}
330
331#[derive(Debug, MeshPayload)]
332pub struct PcieDeviceConfig {
333 pub port_name: String,
334 pub resource: Resource<PciDeviceHandleKind>,
335}
336
337#[derive(Debug, MeshPayload)]
338pub struct VpciDeviceConfig {
339 pub vtl: DeviceVtl,
340 /// The ID of the device. Vpci devices are identified by a portion of `data2` and `data3` of the
341 /// instance ID, which is used to generate the guest-visible device ID.
342 pub instance_id: Guid,
343 pub resource: Resource<PciDeviceHandleKind>,
344 /// NUMA node affinity for this VPCI device.
345 pub vnode: Option<u32>,
346}
347
348#[derive(Debug, Protobuf)]
349pub struct ProcessorTopologyConfig {
350 pub proc_count: u32,
351 pub vps_per_socket: Option<u32>,
352 pub enable_smt: Option<bool>,
353 pub arch: Option<ArchTopologyConfig>,
354}
355
356#[derive(Debug, Protobuf, Default, Clone)]
357pub struct X86TopologyConfig {
358 pub apic_id_offset: u32,
359 pub x2apic: X2ApicConfig,
360}
361
362#[derive(Debug, Default, Copy, Clone, Protobuf)]
363pub enum X2ApicConfig {
364 #[default]
365 /// Support the X2APIC if recommended by the hypervisor or if needed by the
366 /// topology configuration.
367 Auto,
368 /// Support the X2APIC, and automatically enable it if needed to address all
369 /// processors.
370 Supported,
371 /// Do not support the X2APIC.
372 Unsupported,
373 /// Support and enable the X2APIC.
374 Enabled,
375}
376
377#[derive(Debug, Protobuf, Default, Clone)]
378pub enum PmuGsivConfig {
379 #[default]
380 /// Use the hypervisor's platform GSIV value for the PMU.
381 Platform,
382 /// Use the specified GSIV value for the PMU.
383 Gsiv(u32),
384 /// Disable the PMU.
385 Disabled,
386}
387
388/// MSI controller selection for aarch64 PCIe interrupt delivery.
389#[derive(Debug, Protobuf, Default, Clone)]
390pub enum GicMsiConfig {
391 /// Automatically select the best available MSI controller:
392 /// ITS when the hypervisor supports it, otherwise GICv2m.
393 #[default]
394 Auto,
395 /// Force GICv3 ITS for MSI delivery via LPIs.
396 Its,
397 /// Force GICv2m for MSI delivery via SPIs.
398 V2m {
399 /// Number of SPIs to reserve for PCIe MSIs. Defaults to a
400 /// platform-specific value when `None`.
401 spi_count: Option<u32>,
402 },
403}
404
405/// IOMMU configuration for a single PCIe root complex.
406#[derive(Debug, MeshPayload, Clone)]
407pub enum PcieIommuConfig {
408 /// AMD IOMMU (AMD-Vi) for x86_64 guests.
409 AmdVi,
410 /// Arm SMMUv3 for aarch64 guests.
411 Smmu {
412 /// Enable HW-accelerated nested translation (iommufd). Requires VFIO
413 /// devices with `iommu=` behind this SMMU.
414 accel: bool,
415 /// Output address size (OAS) resolution policy.
416 oas: SmmuOas,
417 },
418 /// Intel VT-d for x86_64 guests.
419 IntelVtd,
420}
421
422/// Output address size (OAS) policy for an emulated SMMUv3.
423#[derive(Debug, MeshPayload, Clone, Copy)]
424pub enum SmmuOas {
425 /// Advertise a fixed default OAS. See `DEFAULT_AUTO_OAS_BITS` for the
426 /// sizing policy and its limits.
427 Auto,
428 /// Use a fixed OAS in bits (one of 32, 36, 40, 42, 44, 48, 52).
429 Fixed(u8),
430}
431
432#[derive(Debug, Protobuf, Default, Clone)]
433pub struct Aarch64TopologyConfig {
434 pub gic_config: Option<GicConfig>,
435 pub pmu_gsiv: PmuGsivConfig,
436 pub gic_msi: GicMsiConfig,
437}
438
439/// GIC configuration for the virtual machine.
440///
441/// The variant selects the GIC version. `None` inner config means use
442/// defaults for that version's addresses.
443#[derive(Debug, Protobuf, Clone)]
444pub enum GicConfig {
445 /// GICv2 with optional address overrides.
446 V2(Option<GicV2Config>),
447 /// GICv3 with optional address overrides.
448 V3(Option<GicV3Config>),
449}
450
451/// GICv2-specific address configuration.
452#[derive(Debug, Protobuf, Clone)]
453pub struct GicV2Config {
454 pub gic_distributor_base: u64,
455 pub cpu_interface_base: u64,
456}
457
458/// GICv3-specific address configuration.
459#[derive(Debug, Protobuf, Clone)]
460pub struct GicV3Config {
461 pub gic_distributor_base: u64,
462 pub gic_redistributors_base: u64,
463}
464
465#[derive(Debug, Protobuf, Clone)]
466pub enum ArchTopologyConfig {
467 X86(X86TopologyConfig),
468 Aarch64(Aarch64TopologyConfig),
469}
470
471/// Per-node memory allocation configuration.
472#[derive(Debug, Clone, Copy, MeshPayload)]
473pub struct MemoryConfig {
474 pub mem_size: u64,
475 pub prefetch_memory: bool,
476 pub private_memory: bool,
477 pub transparent_hugepages: bool,
478 pub hugepages: bool,
479 pub hugepage_size: Option<u64>,
480 /// Host physical NUMA node to bind this allocation to (Linux:
481 /// `mbind(MPOL_BIND)`). `None` means OS default placement.
482 pub host_numa_node: Option<u32>,
483}
484
485/// Virtual NUMA topology for the VM.
486#[derive(Debug, MeshPayload)]
487pub struct NumaTopology {
488 /// NUMA nodes. The vnode ID is the index into this vector.
489 pub nodes: Vec<NumaNode>,
490 /// Inter-node distances for the SLIT. If empty, defaults are used
491 /// (10 for self, 20 for cross-node).
492 pub distances: Vec<NumaDistance>,
493}
494
495/// A single virtual NUMA node.
496#[derive(Debug, MeshPayload)]
497pub struct NumaNode {
498 /// Memory allocation for this node. `None` means a CPU-only or
499 /// device-only node.
500 pub mem: Option<MemoryConfig>,
501 /// VP assignment for this node.
502 pub vps: VpAssignment,
503}
504
505/// How VPs are assigned to a NUMA node.
506#[derive(Debug, MeshPayload)]
507pub enum VpAssignment {
508 /// Assign VPs to nodes by round-robining sockets over the CPU-bearing
509 /// nodes only: a VP with socket ID `vp_index / vps_per_socket` belongs to
510 /// the `(vp_index / vps_per_socket) % num_cpu_nodes`-th `FromTopology`
511 /// node. `vps_per_socket` comes from `ProcessorTopologyConfig`;
512 /// `num_cpu_nodes` is the number of `FromTopology` nodes, so `Empty`
513 /// (CPU-less) nodes are skipped and do not affect the distribution.
514 FromTopology,
515 /// Explicit VP indices assigned to this node.
516 Explicit(Vec<u32>),
517 /// A CPU-less node: no VPs are assigned to it. Unlike `Explicit`, this
518 /// may be combined with `FromTopology` nodes, so a memory- or
519 /// device-only node can be declared without forcing every other node to
520 /// spell out its VP set.
521 Empty,
522}
523
524/// An inter-node distance entry for the ACPI SLIT.
525#[derive(Debug, MeshPayload)]
526pub struct NumaDistance {
527 /// Source node index.
528 pub src: u32,
529 /// Destination node index.
530 pub dst: u32,
531 /// Distance value (10 = local, 20 = default cross-node, 255 = unreachable).
532 pub distance: u8,
533}
534
535#[derive(Debug, MeshPayload, Default)]
536pub struct VmbusConfig {
537 pub vsock_listener: Option<unix_socket::UnixListener>,
538 pub vsock_path: Option<String>,
539 pub vmbus_max_version: Option<u32>,
540 #[cfg(windows)]
541 pub vmbusproxy_handle: Option<vmbus_proxy::ProxyHandle>,
542 pub vtl2_redirect: bool,
543}
544
545#[derive(Debug, MeshPayload, Default)]
546pub struct HypervisorConfig {
547 pub with_hv: bool,
548 pub with_vtl2: Option<Vtl2Config>,
549 pub with_isolation: Option<IsolationType>,
550 /// Expose hardware virtualization (VMX/SVM) to the guest so that it can run
551 /// its own hypervisor. A backend that does not recognize this request
552 /// rejects it rather than silently ignoring it (see
553 /// `virt::Hypervisor::recognizes_nested_virt`).
554 pub nested_virt: bool,
555}
556
557#[derive(Debug, MeshPayload)]
558pub struct KernelVmNicConfig {
559 pub instance_id: Guid,
560 pub mac_address: MacAddress,
561 pub switch_port_id: SwitchPortId,
562}
563
564#[derive(Clone, Debug, MeshPayload)]
565pub struct SwitchPortId {
566 pub switch: Guid,
567 pub port: Guid,
568}
569
570pub const DEFAULT_PCAT_BOOT_ORDER: [PcatBootDevice; 4] = [
571 PcatBootDevice::Optical,
572 PcatBootDevice::HardDrive,
573 PcatBootDevice::Network,
574 PcatBootDevice::Floppy,
575];
576
577#[derive(MeshPayload, Debug, Clone, Copy, PartialEq)]
578pub enum PcatBootDevice {
579 Floppy,
580 HardDrive,
581 Optical,
582 Network,
583}
584
585#[derive(Eq, PartialEq, Debug, Copy, Clone, MeshPayload)]
586pub enum VirtioBus {
587 Mmio,
588 Pci,
589}
590
591/// Policy for the partition when mapping VTL0 memory late.
592#[derive(Eq, PartialEq, Debug, Copy, Clone, MeshPayload)]
593pub enum LateMapVtl0MemoryPolicy {
594 /// Halt execution of the VP if VTL0 memory is accessed.
595 Halt,
596 /// Log the error but emulate the access with the instruction emulator.
597 Log,
598 /// Inject an exception into the guest.
599 InjectException,
600}
601
602impl From<LateMapVtl0MemoryPolicy> for virt::LateMapVtl0MemoryPolicy {
603 fn from(value: LateMapVtl0MemoryPolicy) -> Self {
604 match value {
605 LateMapVtl0MemoryPolicy::Halt => virt::LateMapVtl0MemoryPolicy::Halt,
606 LateMapVtl0MemoryPolicy::Log => virt::LateMapVtl0MemoryPolicy::Log,
607 LateMapVtl0MemoryPolicy::InjectException => {
608 virt::LateMapVtl0MemoryPolicy::InjectException
609 }
610 }
611 }
612}
613
614/// Configuration for VTL2.
615///
616/// NOTE: This is distinct from `virt::Vtl2Config` to keep an abstraction
617/// between the virt crate and this crate. Users should not be specifying
618/// virt crate configuration directly.
619#[derive(Debug, Clone, MeshPayload)]
620pub struct Vtl2Config {
621 /// Enable the VTL0 alias map. This maps VTL0's view of memory in VTL2 at
622 /// the highest legal physical address bit.
623 pub vtl0_alias_map: bool,
624 /// If set, map VTL0 memory late after VTL2 has started. The current
625 /// heuristic is to defer mapping VTL0 memory until the first
626 /// `HvModifyVtlProtectionMask` hypercall is made.
627 pub late_map_vtl0_memory: Option<LateMapVtl0MemoryPolicy>,
628}
629
630// Isolation type for a partition.
631#[derive(Eq, PartialEq, Debug, Copy, Clone, MeshPayload)]
632pub enum IsolationType {
633 Vbs,
634 Snp {
635 /// Optional host-provided data included in SNP launch finish.
636 host_data: Option<[u8; 32]>,
637 },
638 Cca,
639}
640
641impl From<IsolationType> for virt::IsolationType {
642 fn from(value: IsolationType) -> Self {
643 match value {
644 IsolationType::Vbs => Self::Vbs,
645 IsolationType::Snp { .. } => Self::Snp,
646 IsolationType::Cca => Self::Cca,
647 }
648 }
649}
650
651/// Which VTL to assign a particular device to.
652#[derive(Copy, Clone, Debug, PartialEq, Eq, MeshPayload)]
653pub enum DeviceVtl {
654 Vtl0,
655 Vtl1,
656 Vtl2,
657}
658
659#[derive(Copy, Clone, Debug, MeshPayload)]
660pub enum UefiConsoleMode {
661 Default,
662 Com1,
663 Com2,
664 None,
665}