#![warn(missing_docs)]
#![forbid(unsafe_code)]
use async_trait::async_trait;
use chipset_device::ChipsetDevice;
use guestmem::GuestMemory;
use inspect::InspectMut;
use std::ops::RangeInclusive;
use vm_resource::kind::ChipsetDeviceHandleKind;
use vm_resource::CanResolveTo;
use vmcore::device_state::ChangeDeviceState;
use vmcore::line_interrupt::LineInterrupt;
use vmcore::save_restore::ProtobufSaveRestore;
use vmcore::vm_task::VmTaskDriverSource;
use vmcore::vmtime::VmTimeSource;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LineSetId(&'static str);
impl LineSetId {
pub fn name(&self) -> &str {
self.0
}
}
pub const IRQ_LINE_SET: LineSetId = LineSetId("irq");
pub const GPE0_LINE_SET: LineSetId = LineSetId("gpe0");
pub const BSP_LINT_LINE_SET: LineSetId = LineSetId("bsp_lint");
impl CanResolveTo<ResolvedChipsetDevice> for ChipsetDeviceHandleKind {
type Input<'a> = ResolveChipsetDeviceHandleParams<'a>;
}
pub struct ResolveChipsetDeviceHandleParams<'a> {
pub device_name: &'a str,
pub guest_memory: &'a GuestMemory,
pub encrypted_guest_memory: &'a GuestMemory,
pub vmtime: &'a VmTimeSource,
pub is_restoring: bool,
pub configure: &'a mut dyn ConfigureChipsetDevice,
pub task_driver_source: &'a VmTaskDriverSource,
pub register_mmio: &'a mut (dyn chipset_device::mmio::RegisterMmioIntercept + Send),
pub register_pio: &'a mut (dyn chipset_device::pio::RegisterPortIoIntercept + Send),
}
pub trait ConfigureChipsetDevice: Send {
fn new_line(&mut self, id: LineSetId, name: &str, vector: u32) -> LineInterrupt;
fn add_line_target(
&mut self,
id: LineSetId,
source_range: RangeInclusive<u32>,
target_start: u32,
);
fn omit_saved_state(&mut self);
}
#[async_trait]
trait DynChipsetDevice: ChipsetDevice + ProtobufSaveRestore + InspectMut {
fn start(&mut self);
async fn stop(&mut self);
async fn reset(&mut self);
}
#[async_trait]
impl<T: ChangeDeviceState + ChipsetDevice + ProtobufSaveRestore + InspectMut> DynChipsetDevice
for T
{
fn start(&mut self) {
self.start()
}
async fn stop(&mut self) {
self.stop().await
}
async fn reset(&mut self) {
self.reset().await
}
}
pub struct ResolvedChipsetDevice(pub ErasedChipsetDevice);
#[derive(InspectMut)]
#[inspect(transparent(mut))]
pub struct ErasedChipsetDevice(Box<dyn DynChipsetDevice>);
impl<T: ChangeDeviceState + ChipsetDevice + ProtobufSaveRestore + InspectMut> From<T>
for ResolvedChipsetDevice
{
fn from(value: T) -> Self {
Self(ErasedChipsetDevice(Box::new(value)))
}
}
impl ChangeDeviceState for ErasedChipsetDevice {
fn start(&mut self) {
self.0.start()
}
async fn stop(&mut self) {
self.0.stop().await
}
async fn reset(&mut self) {
self.0.reset().await
}
}
impl ChipsetDevice for ErasedChipsetDevice {
fn supports_pio(&mut self) -> Option<&mut dyn chipset_device::pio::PortIoIntercept> {
self.0.supports_pio()
}
fn supports_mmio(&mut self) -> Option<&mut dyn chipset_device::mmio::MmioIntercept> {
self.0.supports_mmio()
}
fn supports_pci(&mut self) -> Option<&mut dyn chipset_device::pci::PciConfigSpace> {
self.0.supports_pci()
}
fn supports_poll_device(&mut self) -> Option<&mut dyn chipset_device::poll_device::PollDevice> {
self.0.supports_poll_device()
}
fn supports_line_interrupt_target(
&mut self,
) -> Option<&mut dyn chipset_device::interrupt::LineInterruptTarget> {
self.0.supports_line_interrupt_target()
}
fn supports_handle_eoi(&mut self) -> Option<&mut dyn chipset_device::interrupt::HandleEoi> {
self.0.supports_handle_eoi()
}
fn supports_acknowledge_pic_interrupt(
&mut self,
) -> Option<&mut dyn chipset_device::interrupt::AcknowledgePicInterrupt> {
self.0.supports_acknowledge_pic_interrupt()
}
}
impl ProtobufSaveRestore for ErasedChipsetDevice {
fn save(
&mut self,
) -> Result<vmcore::save_restore::SavedStateBlob, vmcore::save_restore::SaveError> {
self.0.save()
}
fn restore(
&mut self,
state: vmcore::save_restore::SavedStateBlob,
) -> Result<(), vmcore::save_restore::RestoreError> {
self.0.restore(state)
}
}