vmm_core/
vmotherboard_adapter.rs1use crate::partition_unit::Halt;
8use crate::synic::SynicPorts;
9use hvdef::Vtl;
10use std::sync::Arc;
11use virt::VpIndex;
12use virt::io::CpuIo;
13use vmm_core_defs::HaltReason;
14use vmotherboard::Chipset;
15
16#[expect(missing_docs)]
17#[derive(Clone)]
18pub struct ChipsetPlusSynic {
19 pub synic_ports: Arc<SynicPorts>,
20 pub chipset: Arc<Chipset>,
21 fatal_policy: FatalErrorPolicy,
22}
23
24#[derive(Clone)]
25pub enum FatalErrorPolicy {
26 Panic(Arc<dyn Fn() + Send + Sync>),
28 DebugBreak(mesh::Sender<Box<dyn std::error::Error + Send + Sync>>),
31}
32
33impl ChipsetPlusSynic {
34 #[expect(missing_docs)]
35 pub fn new(
36 synic_ports: Arc<SynicPorts>,
37 chipset: Arc<Chipset>,
38 fatal_policy: FatalErrorPolicy,
39 ) -> Self {
40 Self {
41 synic_ports,
42 chipset,
43 fatal_policy,
44 }
45 }
46}
47
48impl CpuIo for ChipsetPlusSynic {
49 fn is_mmio(&self, address: u64) -> bool {
50 self.chipset.is_mmio(address)
51 }
52
53 fn acknowledge_pic_interrupt(&self) -> Option<u8> {
54 self.chipset.acknowledge_pic_interrupt()
55 }
56
57 fn handle_eoi(&self, irq: u32) {
58 self.chipset.handle_eoi(irq)
59 }
60
61 fn signal_synic_event(&self, vtl: Vtl, connection_id: u32, flag: u16) -> hvdef::HvResult<()> {
62 self.synic_ports.on_signal_event(vtl, connection_id, flag)
63 }
64
65 fn post_synic_message(
66 &self,
67 vtl: Vtl,
68 connection_id: u32,
69 secure: bool,
70 message: &[u8],
71 ) -> hvdef::HvResult<()> {
72 self.synic_ports
73 .on_post_message(vtl, connection_id, secure, message)
74 }
75
76 fn read_mmio(&self, vp: VpIndex, address: u64, data: &mut [u8]) -> impl Future<Output = ()> {
77 self.chipset.mmio_read(vp.index(), address, data)
78 }
79
80 fn write_mmio(&self, vp: VpIndex, address: u64, data: &[u8]) -> impl Future<Output = ()> {
81 self.chipset.mmio_write(vp.index(), address, data)
82 }
83
84 fn read_io(&self, vp: VpIndex, port: u16, data: &mut [u8]) -> impl Future<Output = ()> {
85 self.chipset.io_read(vp.index(), port, data)
86 }
87
88 fn write_io(&self, vp: VpIndex, port: u16, data: &[u8]) -> impl Future<Output = ()> {
89 self.chipset.io_write(vp.index(), port, data)
90 }
91
92 #[track_caller]
93 fn fatal_error(&self, error: Box<dyn std::error::Error + Send + Sync>) -> virt::VpHaltReason {
94 tracing::error!(
95 err = error.as_ref() as &dyn std::error::Error,
96 "fatal error"
97 );
98 match &self.fatal_policy {
99 FatalErrorPolicy::Panic(prep) => {
100 prep();
101 panic!("fatal error: {}", error)
102 }
103 FatalErrorPolicy::DebugBreak(channel) => {
104 channel.send(error);
105 virt::VpHaltReason::SingleStep
106 }
107 }
108 }
109}
110
111impl vmotherboard::PowerEventHandler for Halt {
112 fn on_power_event(&self, evt: vmotherboard::PowerEvent) {
113 let reason = match evt {
114 vmotherboard::PowerEvent::PowerOff => HaltReason::PowerOff,
115 vmotherboard::PowerEvent::Reset => HaltReason::Reset,
116 vmotherboard::PowerEvent::Hibernate => HaltReason::Hibernate,
117 };
118 self.halt(reason)
119 }
120}
121
122impl vmotherboard::DebugEventHandler for Halt {
123 fn on_debug_break(&self, vp: Option<u32>) {
124 self.halt(HaltReason::DebugBreak { vp })
125 }
126}