vmi_arch_amd64/event.rs
1use vmi_core::{Gfn, MemoryAccess, Pa, Va};
2
3use crate::{ControlRegister, ExceptionVector, Interrupt, Msr};
4
5bitflags::bitflags! {
6 /// Flags describing a memory access event.
7 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
8 pub struct MemoryAccessFlags: u8 {
9 /// The [`EventMemoryAccess::va`] field holds a guest VA associated with the event.
10 const GLA_VALID = (1 << 3);
11
12 /// The `MemoryAccess` event was triggered by accessing a guest linear address.
13 const FAULT_WITH_GLA = (1 << 4);
14
15 /// The `MemoryAccess` event was triggered during translating a guest linear address.
16 const FAULT_IN_GPT = (1 << 5);
17 }
18}
19
20/// Event generated when monitored memory is accessed.
21#[derive(Debug, Clone, Copy)]
22pub struct EventMemoryAccess {
23 /// Physical address that was accessed.
24 pub pa: Pa,
25
26 /// Virtual address that was accessed.
27 pub va: Va,
28
29 /// Type of access that occurred (read/write/execute).
30 pub access: MemoryAccess,
31
32 /// Additional flags describing the access.
33 pub flags: MemoryAccessFlags,
34}
35
36/// Event generated when a control register is written to.
37#[derive(Debug, Clone, Copy)]
38pub struct EventWriteCr {
39 /// The control register that was written to (CR0, CR3, CR4 or XCR0).
40 pub register: ControlRegister,
41
42 /// New value of the control register.
43 pub new_value: u64,
44
45 /// Old value of the control register.
46 pub old_value: u64,
47}
48
49/// Event generated when a model-specific register (MSR) is written to.
50#[derive(Debug, Clone, Copy)]
51pub struct EventWriteMsr {
52 /// The MSR that was written to.
53 pub register: u32,
54
55 /// New value of the MSR.
56 pub new_value: u64,
57
58 /// Old value of the MSR.
59 pub old_value: u64,
60}
61
62/// Event generated when an interrupt or exception occurs.
63#[derive(Debug, Clone, Copy)]
64pub struct EventInterrupt {
65 /// GFN of the instruction that caused the interrupt.
66 /// Effectively, this is GFN of the current instruction pointer.
67 pub gfn: Gfn,
68
69 /// Information about the interrupt/exception.
70 pub interrupt: Interrupt,
71}
72
73/// Event generated when a singlestep event occurs.
74#[derive(Debug, Clone, Copy)]
75pub struct EventSinglestep {
76 /// GFN of the instruction that caused the singlestep.
77 pub gfn: Gfn,
78}
79
80/// Event generated when a VMCALL instruction is executed.
81#[derive(Debug, Clone, Copy)]
82pub struct EventHypercall {
83 /// Length of the VMCALL instruction.
84 pub instruction_length: u8,
85}
86
87/// Event generated when a CPUID instruction is executed.
88#[derive(Debug, Clone, Copy)]
89pub struct EventCpuId {
90 /// CPUID leaf (EAX).
91 pub leaf: u32,
92
93 /// CPUID subleaf (ECX).
94 pub subleaf: u32,
95
96 /// Length of the CPUID instruction.
97 pub instruction_length: u8,
98}
99
100/// Direction of the I/O port access.
101#[derive(Debug, Clone, Copy)]
102pub enum EventIoDirection {
103 /// I/O port read.
104 In,
105
106 /// I/O port write.
107 Out,
108}
109
110/// Event generated when an I/O port is accessed.
111#[derive(Debug, Clone, Copy)]
112pub struct EventIo {
113 /// I/O port that was accessed.
114 pub port: u16,
115
116 /// Number of bytes transferred.
117 pub length: u32,
118
119 /// Direction of transfer (in/out).
120 pub direction: EventIoDirection,
121
122 /// True for string I/O instructions (INS/OUTS).
123 pub string: bool,
124}
125
126/// Reason for an event.
127#[derive(Debug, Clone, Copy)]
128pub enum EventReason {
129 /// Memory access event (read/write/execute).
130 MemoryAccess(EventMemoryAccess),
131
132 /// Control register write event.
133 WriteCr(EventWriteCr),
134
135 /// MSR write event.
136 WriteMsr(EventWriteMsr),
137
138 /// Interrupt or exception event.
139 Interrupt(EventInterrupt),
140
141 /// Singlestep event.
142 Singlestep(EventSinglestep),
143
144 /// Hypercall event (VMCALL).
145 Hypercall(EventHypercall),
146
147 /// CPUID instruction event.
148 CpuId(EventCpuId),
149
150 /// I/O port access event.
151 Io(EventIo),
152}
153
154impl EventReason {
155 /// Returns the memory access event.
156 ///
157 /// # Panics
158 ///
159 /// Panics if the event reason is not a memory access event.
160 pub fn as_memory_access(&self) -> &EventMemoryAccess {
161 match self {
162 Self::MemoryAccess(memory_access) => memory_access,
163 _ => panic!("EventReason is not a MemoryAccess"),
164 }
165 }
166
167 /// Returns the control register write event.
168 ///
169 /// # Panics
170 ///
171 /// Panics if the event reason is not a control register write event.
172 pub fn as_write_cr(&self) -> &EventWriteCr {
173 match self {
174 Self::WriteCr(write_cr) => write_cr,
175 _ => panic!("EventReason is not a WriteCr"),
176 }
177 }
178
179 /// Returns the MSR write event.
180 ///
181 /// # Panics
182 ///
183 /// Panics if the event reason is not an MSR write event.
184 pub fn as_write_msr(&self) -> &EventWriteMsr {
185 match self {
186 Self::WriteMsr(write_msr) => write_msr,
187 _ => panic!("EventReason is not a WriteMsr"),
188 }
189 }
190
191 /// Returns the interrupt or exception event.
192 ///
193 /// # Panics
194 ///
195 /// Panics if the event reason is not an interrupt or exception event.
196 pub fn as_interrupt(&self) -> &EventInterrupt {
197 match self {
198 Self::Interrupt(interrupt) => interrupt,
199 _ => panic!("EventReason is not an Interrupt"),
200 }
201 }
202
203 /// Returns the singlestep event.
204 ///
205 /// # Panics
206 ///
207 /// Panics if the event reason is not a singlestep event.
208 pub fn as_singlestep(&self) -> &EventSinglestep {
209 match self {
210 Self::Singlestep(singlestep) => singlestep,
211 _ => panic!("EventReason is not a Singlestep"),
212 }
213 }
214
215 /// Returns the hypercall event.
216 ///
217 /// # Panics
218 ///
219 /// Panics if the event reason is not a hypercall event.
220 pub fn as_hypercall(&self) -> &EventHypercall {
221 match self {
222 Self::Hypercall(hypercall) => hypercall,
223 _ => panic!("EventReason is not a Hypercall"),
224 }
225 }
226
227 /// Returns the CPUID instruction event.
228 ///
229 /// # Panics
230 ///
231 /// Panics if the event reason is not a CPUID instruction event.
232 pub fn as_cpuid(&self) -> &EventCpuId {
233 match self {
234 Self::CpuId(cpuid) => cpuid,
235 _ => panic!("EventReason is not a CpuId"),
236 }
237 }
238
239 /// Returns the I/O port access event.
240 ///
241 /// # Panics
242 ///
243 /// Panics if the event reason is not an I/O port access event.
244 pub fn as_io(&self) -> &EventIo {
245 match self {
246 Self::Io(io) => io,
247 _ => panic!("EventReason is not an Io"),
248 }
249 }
250}
251
252/// Specifies which hardware events should be monitored.
253///
254/// This enum is used to specify which hardware events should be monitored by
255/// the VMI system.
256#[derive(Debug, Clone, Copy)]
257pub enum EventMonitor {
258 // MemoryAccess, (implicit)
259 /// Monitor writes to a specific control register.
260 ///
261 /// This method allows for setting up event triggers when certain CPU
262 /// registers are accessed or modified. The specific registers that can
263 /// be monitored are defined by the [`ControlRegister`] enum.
264 ///
265 /// When enabled, relevant events will be passed to the event callback
266 /// function.
267 Register(ControlRegister),
268
269 /// Monitor writes to a specific model-specific register (MSR).
270 ///
271 /// When enabled, this method generates an event each time the specified
272 /// MSR is written to via the WRMSR instruction. This can be useful for
273 /// detecting changes to system configuration, such as SYSCALL entry
274 /// points ([`Msr::LSTAR`]), segment base addresses ([`Msr::FS_BASE`],
275 /// [`Msr::GS_BASE`]), or extended feature settings ([`Msr::EFER`]).
276 ///
277 /// MSR write events will be passed to the event callback function when
278 /// they occur.
279 Msr(Msr),
280
281 /// Monitor specific hardware interrupts or exception vectors.
282 ///
283 /// This method sets up event triggers for specified interrupt events. The
284 /// types of interrupts that can be monitored are defined by the
285 /// [`ExceptionVector`] enum.
286 ///
287 /// When an interrupt event occurs, it will be passed to the event callback
288 /// function.
289 Interrupt(ExceptionVector),
290
291 /// Monitor singlestep execution of instructions.
292 ///
293 /// When enabled, this method causes the VMI system to generate an event
294 /// after each instruction execution in the guest. This can be useful
295 /// for detailed analysis of guest behavior, but may have a significant
296 /// performance impact.
297 ///
298 /// Single-step events will be passed to the event callback function when
299 /// they occur.
300 Singlestep,
301
302 /// Monitor execution of VMCALL instructions.
303 ///
304 /// When enabled, this method generates an event each time a VMCALL
305 /// instruction is executed in the guest. This can be useful for
306 /// implementing custom hypercalls or for implementing custom
307 /// virtual device behavior.
308 ///
309 /// VMCALL events will be passed to the event callback function when they
310 /// occur.
311 Hypercall {
312 /// Allow userspace to handle the VMCALL.
313 allow_userspace: bool,
314 },
315
316 /// Monitor execution of CPUID instructions.
317 ///
318 /// When enabled, this method generates an event each time a CPUID
319 /// instruction is executed in the guest. This can be useful for
320 /// analyzing how the guest queries CPU features or for implementing CPU
321 /// feature spoofing.
322 ///
323 /// CPUID events will be passed to the event callback function when they
324 /// occur.
325 CpuId,
326
327 /// Monitor I/O port accesses.
328 ///
329 /// When enabled, this method generates events for I/O port read and write
330 /// operations performed by the guest. This can be useful for analyzing
331 /// guest interactions with virtual hardware or for implementing custom
332 /// virtual device behavior.
333 ///
334 /// I/O port events will be passed to the event callback function when they
335 /// occur.
336 Io,
337}