xen/ctrl/monitor/
mod.rs

1mod ring;
2use xen_sys::{
3    vm_event_back_ring, xc_monitor_cpuid, xc_monitor_debug_exceptions,
4    xc_monitor_descriptor_access, xc_monitor_disable, xc_monitor_emul_unimplemented,
5    xc_monitor_emulate_each_rep, xc_monitor_enable, xc_monitor_get_capabilities,
6    xc_monitor_guest_request, xc_monitor_inguest_pagefault, xc_monitor_io, xc_monitor_mov_to_msr,
7    xc_monitor_privileged_call, xc_monitor_resume, xc_monitor_singlestep,
8    xc_monitor_software_breakpoint, xc_monitor_vmexit, xc_monitor_write_ctrlreg,
9};
10
11pub use self::ring::VmEventRing;
12use crate::{
13    BACK_RING_INIT, SHARED_RING_INIT, XenDomainId,
14    consts::PAGE_SIZE,
15    ctrl::{VmEventCtrlReg, XenInterface},
16    error::{XcError, XenError},
17    evtchn::XenEventChannelPort,
18    xc_check_error,
19};
20
21pub struct XenMonitor {
22    interface: XenInterface,
23    domain_id: XenDomainId,
24    port: u32,
25}
26
27impl XenMonitor {
28    pub(crate) fn new(
29        interface: XenInterface,
30        domain_id: XenDomainId,
31    ) -> Result<(Self, VmEventRing), XenError> {
32        let mut port: u32 = 0;
33        let ring_page = unsafe { xc_monitor_enable(interface.handle.0, domain_id.0, &mut port) };
34
35        if ring_page.is_null() {
36            return Err(XcError::new(-1, 0, "Failed to enable monitor").into());
37        }
38
39        SHARED_RING_INIT!(ring_page);
40
41        let mut back_ring = unsafe { std::mem::zeroed::<vm_event_back_ring>() };
42        BACK_RING_INIT!(back_ring, ring_page, PAGE_SIZE);
43
44        Ok((
45            Self {
46                interface,
47                domain_id,
48                port,
49            },
50            VmEventRing::new(ring_page, back_ring),
51        ))
52    }
53
54    pub fn channel(&self) -> Result<XenEventChannelPort, XenError> {
55        XenEventChannelPort::bind_interdomain(self.domain_id, self.port)
56    }
57
58    pub fn port(&self) -> u32 {
59        self.port
60    }
61
62    pub fn resume(&self) -> Result<(), XenError> {
63        let rc = unsafe { xc_monitor_resume(self.interface.handle.0, self.domain_id.0) };
64        xc_check_error!(self.interface.handle.0, rc);
65        Ok(())
66    }
67
68    pub fn get_capabilities(&self) -> Result<u32, XenError> {
69        let mut capabilities = 0;
70        let rc = unsafe {
71            xc_monitor_get_capabilities(
72                self.interface.handle.0,
73                self.domain_id.0,
74                &mut capabilities,
75            )
76        };
77        xc_check_error!(self.interface.handle.0, rc);
78        Ok(capabilities)
79    }
80
81    pub fn write_ctrlreg(
82        &self,
83        index: VmEventCtrlReg,
84        enable: bool,
85        sync: bool,
86        bitmask: u64,
87        onchangeonly: bool,
88    ) -> Result<(), XenError> {
89        let rc = unsafe {
90            xc_monitor_write_ctrlreg(
91                self.interface.handle.0,
92                self.domain_id.0,
93                index as u16,
94                enable,
95                sync,
96                bitmask,
97                onchangeonly,
98            )
99        };
100        xc_check_error!(self.interface.handle.0, rc);
101        Ok(())
102    }
103
104    pub fn mov_to_msr(&self, msr: u32, enable: bool, onchangeonly: bool) -> Result<(), XenError> {
105        let rc = unsafe {
106            xc_monitor_mov_to_msr(
107                self.interface.handle.0,
108                self.domain_id.0,
109                msr,
110                enable,
111                onchangeonly,
112            )
113        };
114        xc_check_error!(self.interface.handle.0, rc);
115        Ok(())
116    }
117
118    pub fn singlestep(&self, singlestep: bool) -> Result<(), XenError> {
119        let rc =
120            unsafe { xc_monitor_singlestep(self.interface.handle.0, self.domain_id.0, singlestep) };
121        xc_check_error!(self.interface.handle.0, rc);
122        Ok(())
123    }
124
125    pub fn software_breakpoint(&self, enable: bool) -> Result<(), XenError> {
126        let rc = unsafe {
127            xc_monitor_software_breakpoint(self.interface.handle.0, self.domain_id.0, enable)
128        };
129        xc_check_error!(self.interface.handle.0, rc);
130        Ok(())
131    }
132
133    pub fn descriptor_access(&self, enable: bool) -> Result<(), XenError> {
134        let rc = unsafe {
135            xc_monitor_descriptor_access(self.interface.handle.0, self.domain_id.0, enable)
136        };
137        xc_check_error!(self.interface.handle.0, rc);
138        Ok(())
139    }
140
141    pub fn guest_request(
142        &self,
143        enable: bool,
144        sync: bool,
145        allow_userspace: bool,
146    ) -> Result<(), XenError> {
147        let rc = unsafe {
148            xc_monitor_guest_request(
149                self.interface.handle.0,
150                self.domain_id.0,
151                enable,
152                sync,
153                allow_userspace,
154            )
155        };
156        xc_check_error!(self.interface.handle.0, rc);
157        Ok(())
158    }
159
160    pub fn inguest_pagefault(&self, disable: bool) -> Result<(), XenError> {
161        let rc = unsafe {
162            xc_monitor_inguest_pagefault(self.interface.handle.0, self.domain_id.0, disable)
163        };
164        xc_check_error!(self.interface.handle.0, rc);
165        Ok(())
166    }
167
168    pub fn debug_exceptions(&self, enable: bool, sync: bool) -> Result<(), XenError> {
169        let rc = unsafe {
170            xc_monitor_debug_exceptions(self.interface.handle.0, self.domain_id.0, enable, sync)
171        };
172        xc_check_error!(self.interface.handle.0, rc);
173        Ok(())
174    }
175
176    pub fn cpuid(&self, enable: bool) -> Result<(), XenError> {
177        let rc = unsafe { xc_monitor_cpuid(self.interface.handle.0, self.domain_id.0, enable) };
178        xc_check_error!(self.interface.handle.0, rc);
179        Ok(())
180    }
181
182    pub fn privileged_call(&self, enable: bool) -> Result<(), XenError> {
183        let rc = unsafe {
184            xc_monitor_privileged_call(self.interface.handle.0, self.domain_id.0, enable)
185        };
186        xc_check_error!(self.interface.handle.0, rc);
187        Ok(())
188    }
189
190    pub fn emul_unimplemented(&self, enable: bool) -> Result<(), XenError> {
191        let rc = unsafe {
192            xc_monitor_emul_unimplemented(self.interface.handle.0, self.domain_id.0, enable)
193        };
194        xc_check_error!(self.interface.handle.0, rc);
195        Ok(())
196    }
197
198    pub fn vmexit(&self, enable: bool, sync: bool) -> Result<(), XenError> {
199        let rc =
200            unsafe { xc_monitor_vmexit(self.interface.handle.0, self.domain_id.0, enable, sync) };
201        xc_check_error!(self.interface.handle.0, rc);
202        Ok(())
203    }
204
205    pub fn io(&self, enable: bool) -> Result<(), XenError> {
206        let rc = unsafe { xc_monitor_io(self.interface.handle.0, self.domain_id.0, enable) };
207        xc_check_error!(self.interface.handle.0, rc);
208        Ok(())
209    }
210
211    pub fn emulate_each_rep(&self, enable: bool) -> Result<(), XenError> {
212        let rc = unsafe {
213            xc_monitor_emulate_each_rep(self.interface.handle.0, self.domain_id.0, enable)
214        };
215        xc_check_error!(self.interface.handle.0, rc);
216        Ok(())
217    }
218}
219
220impl Drop for XenMonitor {
221    fn drop(&mut self) {
222        tracing::trace!(?self.domain_id, "disabling monitor");
223        unsafe {
224            xc_monitor_disable(self.interface.handle.0, self.domain_id.0);
225        }
226    }
227}