vmotherboard/lib.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! A declarative builder API to init and wire-up virtual devices onto a
5//! "virtual motherboard".
6//!
7//! At a high level: Given a [`BaseChipsetBuilder`] + a list of
8//! [`BaseChipsetDevices`](options::BaseChipsetDevices), return [`Chipset`].
9
10#![forbid(unsafe_code)]
11
12mod base_chipset;
13mod chipset;
14
15pub use self::base_chipset::BaseChipsetBuilder;
16pub use self::base_chipset::BaseChipsetBuilderError;
17pub use self::base_chipset::BaseChipsetBuilderOutput;
18pub use self::base_chipset::BaseChipsetDeviceInterfaces;
19pub use self::base_chipset::options;
20pub use self::chipset::Chipset;
21pub use self::chipset::ChipsetDevices;
22pub use self::chipset::DynamicDeviceUnit;
23
24// API wart: future changes should avoid exposing the `ChipsetBuilder`, and move
25// _all_ device instantiation into `vmotherboard` itself.
26pub use self::chipset::ChipsetBuilder;
27pub use self::chipset::backing::arc_mutex::device::ArcMutexChipsetDeviceBuilder;
28
29use chipset_device::ChipsetDevice;
30use inspect::InspectMut;
31use mesh::MeshPayload;
32use std::marker::PhantomData;
33use std::sync::Arc;
34use vm_resource::Resource;
35use vm_resource::kind::ChipsetDeviceHandleKind;
36use vmcore::device_state::ChangeDeviceState;
37use vmcore::save_restore::ProtobufSaveRestore;
38
39/// A supertrait of `ChipsetDevice` that requires devices to also support
40/// InspectMut and SaveRestore.
41///
42/// We don't want to put these bounds on `ChipsetDevice` directly, as that would
43/// tightly couple `ChipsetDevice` devices with OpenVMM-specific infrastructure,
44/// making it difficult to share device implementations across VMMs.
45pub trait VmmChipsetDevice:
46 ChipsetDevice + InspectMut + ProtobufSaveRestore + ChangeDeviceState
47{
48}
49
50impl<T> VmmChipsetDevice for T where
51 T: ChipsetDevice + InspectMut + ProtobufSaveRestore + ChangeDeviceState
52{
53}
54
55/// A device-triggered power event.
56pub enum PowerEvent {
57 /// Initiate Power Off
58 PowerOff,
59 /// Initiate Reset
60 Reset,
61 /// Initiate Hibernate
62 Hibernate,
63}
64
65/// Handler for device-triggered power events.
66pub trait PowerEventHandler: Send + Sync {
67 /// Called when there is a device-triggered power event.
68 fn on_power_event(&self, evt: PowerEvent);
69}
70
71/// Handler for device-triggered debug events.
72pub trait DebugEventHandler: Send + Sync {
73 /// Called when a device has requested a debug break.
74 fn on_debug_break(&self, vp: Option<u32>);
75}
76
77/// Generic Bus Identifier. Used to describe VM bus topologies.
78#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
79pub struct BusId<T> {
80 name: Arc<str>,
81 _kind: PhantomData<T>,
82}
83
84impl<T> BusId<T> {
85 /// Create a new `BusId` with the given `name`.
86 pub fn new(name: &str) -> Self {
87 BusId {
88 name: name.into(),
89 _kind: PhantomData,
90 }
91 }
92}
93
94#[doc(hidden)]
95pub mod bus_kind {
96 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
97 pub enum Pci {}
98 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
99 pub enum PcieEnumerator {}
100 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
101 pub enum PcieDownstreamPort {}
102}
103
104/// Type-safe PCI bus ID.
105pub type BusIdPci = BusId<bus_kind::Pci>;
106
107/// Type-safe ID for the internal "bus" of a PCIe root
108/// complex or switch.
109pub type BusIdPcieEnumerator = BusId<bus_kind::PcieEnumerator>;
110
111/// Type-safe ID for a downstream PCIe port.
112pub type BusIdPcieDownstreamPort = BusId<bus_kind::PcieDownstreamPort>;
113
114/// A handle to instantiate a chipset device.
115#[derive(MeshPayload, Debug)]
116pub struct ChipsetDeviceHandle {
117 /// The name of the device.
118 pub name: String,
119 /// The device resource handle.
120 pub resource: Resource<ChipsetDeviceHandleKind>,
121}
122
123/// A handle to instantiate a legacy PCI chipset device with explicit placement.
124///
125/// # Legacy Chipset Only
126///
127/// This handle type is **exclusively for legacy Gen1 PCI chipset devices** that require
128/// historically-fixed PCI bus/device/function placement. Examples include ISA bridge,
129/// PIIX4 IDE, USB UHCI, and similar integrated chipset functions.
130///
131/// **New devices must not use this type.** Externally-facing devices (e.g. passthrough,
132/// Gen2 emulated devices) should use [`ChipsetDeviceHandle`] and implement dynamic PCI
133/// enumeration or appropriate driver recognition patterns.
134///
135/// This type exists to preserve the explicit wiring of legacy Gen1 chipset components
136/// into fixed PCI locations, which guests expect and depend upon for compatibility.
137#[derive(MeshPayload, Debug)]
138pub struct LegacyPciChipsetDeviceHandle {
139 /// The name of the device.
140 pub name: String,
141 /// The device resource handle.
142 pub resource: Resource<ChipsetDeviceHandleKind>,
143 /// The PCI bus name to attach the device to.
144 /// **Must be specified explicitly; derived from chipset architecture, not device discovery.**
145 pub pci_bus_name: String,
146 /// The explicit static PCI bus/device/function tuple.
147 /// **This is part of the legacy chipset's fixed contract; do not make this negotiable.**
148 pub bdf: (u8, u8, u8),
149}