xen/ctrl/event/
reason.rs

1use xen_sys::{
2    VM_EVENT_X86_CR0, VM_EVENT_X86_CR3, VM_EVENT_X86_CR4, VM_EVENT_X86_XCR0, vm_event_cpuid,
3    vm_event_debug, vm_event_desc_access, vm_event_fast_singlestep, vm_event_interrupt_x86,
4    vm_event_io, vm_event_mem_access, vm_event_mov_to_msr, vm_event_paging, vm_event_sharing,
5    vm_event_singlestep, vm_event_vmexit, vm_event_write_ctrlreg,
6};
7
8use crate::XenX86EventType;
9
10#[derive(Debug)]
11pub struct VmEventMemAccess {
12    pub gfn: u64,
13    pub offset: u64,
14    pub gla: u64,
15    pub flags: u32,
16}
17
18impl From<vm_event_mem_access> for VmEventMemAccess {
19    fn from(value: vm_event_mem_access) -> Self {
20        Self {
21            gfn: value.gfn,
22            offset: value.offset,
23            gla: value.gla,
24            flags: value.flags,
25        }
26    }
27}
28
29impl From<VmEventMemAccess> for vm_event_mem_access {
30    fn from(value: VmEventMemAccess) -> Self {
31        Self {
32            gfn: value.gfn,
33            offset: value.offset,
34            gla: value.gla,
35            flags: value.flags,
36            _pad: Default::default(),
37        }
38    }
39}
40
41#[derive(Debug)]
42pub struct VmEventSharing {
43    pub gfn: u64,
44    pub p2mt: u32,
45}
46
47impl From<vm_event_sharing> for VmEventSharing {
48    fn from(value: vm_event_sharing) -> Self {
49        Self {
50            gfn: value.gfn,
51            p2mt: value.p2mt,
52        }
53    }
54}
55
56impl From<VmEventSharing> for vm_event_sharing {
57    fn from(value: VmEventSharing) -> Self {
58        Self {
59            gfn: value.gfn,
60            p2mt: value.p2mt,
61            _pad: Default::default(),
62        }
63    }
64}
65
66#[derive(Debug)]
67pub struct VmEventPaging {
68    pub gfn: u64,
69    pub p2mt: u32,
70    pub flags: u32,
71}
72
73impl From<vm_event_paging> for VmEventPaging {
74    fn from(value: vm_event_paging) -> Self {
75        Self {
76            gfn: value.gfn,
77            p2mt: value.p2mt,
78            flags: value.flags,
79        }
80    }
81}
82
83impl From<VmEventPaging> for vm_event_paging {
84    fn from(value: VmEventPaging) -> Self {
85        Self {
86            gfn: value.gfn,
87            p2mt: value.p2mt,
88            flags: value.flags,
89        }
90    }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94#[repr(u32)]
95pub enum VmEventCtrlReg {
96    Cr0 = VM_EVENT_X86_CR0,
97    Cr3 = VM_EVENT_X86_CR3,
98    Cr4 = VM_EVENT_X86_CR4,
99    Xcr0 = VM_EVENT_X86_XCR0,
100}
101
102impl From<u32> for VmEventCtrlReg {
103    fn from(value: u32) -> Self {
104        match value {
105            VM_EVENT_X86_CR0 => Self::Cr0,
106            VM_EVENT_X86_CR3 => Self::Cr3,
107            VM_EVENT_X86_CR4 => Self::Cr4,
108            VM_EVENT_X86_XCR0 => Self::Xcr0,
109            _ => Self::Cr0,
110        }
111    }
112}
113
114impl From<VmEventCtrlReg> for u32 {
115    fn from(value: VmEventCtrlReg) -> Self {
116        value as u32
117    }
118}
119
120#[derive(Debug)]
121pub struct VmEventWriteCtrlReg {
122    pub index: VmEventCtrlReg,
123    pub new_value: u64,
124    pub old_value: u64,
125}
126
127impl From<vm_event_write_ctrlreg> for VmEventWriteCtrlReg {
128    fn from(value: vm_event_write_ctrlreg) -> Self {
129        Self {
130            index: value.index.into(),
131            new_value: value.new_value,
132            old_value: value.old_value,
133        }
134    }
135}
136
137impl From<VmEventWriteCtrlReg> for vm_event_write_ctrlreg {
138    fn from(value: VmEventWriteCtrlReg) -> Self {
139        Self {
140            index: value.index.into(),
141            new_value: value.new_value,
142            old_value: value.old_value,
143            _pad: Default::default(),
144        }
145    }
146}
147
148#[derive(Debug)]
149pub struct VmEventMovToMsr {
150    pub msr: u64,
151    pub new_value: u64,
152    pub old_value: u64,
153}
154
155impl From<vm_event_mov_to_msr> for VmEventMovToMsr {
156    fn from(value: vm_event_mov_to_msr) -> Self {
157        Self {
158            msr: value.msr,
159            new_value: value.new_value,
160            old_value: value.old_value,
161        }
162    }
163}
164
165impl From<VmEventMovToMsr> for vm_event_mov_to_msr {
166    fn from(value: VmEventMovToMsr) -> Self {
167        Self {
168            msr: value.msr,
169            new_value: value.new_value,
170            old_value: value.old_value,
171        }
172    }
173}
174
175#[derive(Debug)]
176pub struct VmEventDebug {
177    pub gfn: u64,
178    pub pending_dbg: u64, // Behaves like the VT-x PENDING_DBG field.
179    pub insn_length: u32,
180    pub typ: XenX86EventType,
181}
182
183impl From<vm_event_debug> for VmEventDebug {
184    fn from(value: vm_event_debug) -> Self {
185        Self {
186            gfn: value.gfn,
187            pending_dbg: value.pending_dbg,
188            insn_length: value.insn_length,
189            typ: unsafe { std::mem::transmute::<u8, XenX86EventType>(value.type_) },
190        }
191    }
192}
193
194impl From<VmEventDebug> for vm_event_debug {
195    fn from(value: VmEventDebug) -> Self {
196        Self {
197            gfn: value.gfn,
198            pending_dbg: value.pending_dbg,
199            insn_length: value.insn_length,
200            type_: value.typ as u8,
201            _pad: Default::default(),
202        }
203    }
204}
205
206#[derive(Debug)]
207pub struct VmEventSinglestep {
208    pub gfn: u64,
209}
210
211impl From<vm_event_singlestep> for VmEventSinglestep {
212    fn from(value: vm_event_singlestep) -> Self {
213        Self { gfn: value.gfn }
214    }
215}
216
217impl From<VmEventSinglestep> for vm_event_singlestep {
218    fn from(value: VmEventSinglestep) -> Self {
219        Self { gfn: value.gfn }
220    }
221}
222
223#[derive(Debug)]
224pub struct VmEventFastSinglestep {
225    pub p2midx: u16,
226}
227
228impl From<vm_event_fast_singlestep> for VmEventFastSinglestep {
229    fn from(value: vm_event_fast_singlestep) -> Self {
230        Self {
231            p2midx: value.p2midx,
232        }
233    }
234}
235
236impl From<VmEventFastSinglestep> for vm_event_fast_singlestep {
237    fn from(value: VmEventFastSinglestep) -> Self {
238        Self {
239            p2midx: value.p2midx,
240        }
241    }
242}
243
244#[derive(Debug)]
245pub struct VmEventCpuid {
246    pub insn_length: u32,
247    pub leaf: u32,
248    pub subleaf: u32,
249}
250
251impl From<vm_event_cpuid> for VmEventCpuid {
252    fn from(value: vm_event_cpuid) -> Self {
253        Self {
254            insn_length: value.insn_length,
255            leaf: value.leaf,
256            subleaf: value.subleaf,
257        }
258    }
259}
260
261impl From<VmEventCpuid> for vm_event_cpuid {
262    fn from(value: VmEventCpuid) -> Self {
263        Self {
264            insn_length: value.insn_length,
265            leaf: value.leaf,
266            subleaf: value.subleaf,
267            _pad: Default::default(),
268        }
269    }
270}
271
272#[derive(Debug)]
273pub struct VmEventInterrupt {
274    pub vector: u32,
275    pub ty: u32,
276    pub error_code: u32,
277    pub cr2: u64,
278}
279
280impl From<vm_event_interrupt_x86> for VmEventInterrupt {
281    fn from(value: vm_event_interrupt_x86) -> Self {
282        Self {
283            vector: value.vector,
284            ty: value.type_,
285            error_code: value.error_code,
286            cr2: value.cr2,
287        }
288    }
289}
290
291impl From<VmEventInterrupt> for vm_event_interrupt_x86 {
292    fn from(value: VmEventInterrupt) -> Self {
293        Self {
294            vector: value.vector,
295            type_: value.ty,
296            error_code: value.error_code,
297            cr2: value.cr2,
298            _pad: Default::default(),
299        }
300    }
301}
302
303#[derive(Debug)]
304pub struct VmEventDescriptorAccess {
305    pub instr_info: u32,         // VMX: VMCS Instruction-Information
306    pub exit_qualification: u64, // VMX: VMCS Exit Qualification
307    pub descriptor: u8,          // VM_EVENT_DESC_*
308    pub is_write: u8,
309}
310
311impl From<vm_event_desc_access> for VmEventDescriptorAccess {
312    fn from(value: vm_event_desc_access) -> Self {
313        Self {
314            instr_info: unsafe { value.arch.vmx.instr_info },
315            exit_qualification: unsafe { value.arch.vmx.exit_qualification },
316            descriptor: value.descriptor,
317            is_write: value.is_write,
318        }
319    }
320}
321
322impl From<VmEventDescriptorAccess> for vm_event_desc_access {
323    fn from(value: VmEventDescriptorAccess) -> Self {
324        let mut result = Self::default();
325        result.arch.vmx.instr_info = value.instr_info;
326        result.arch.vmx.exit_qualification = value.exit_qualification;
327        result.descriptor = value.descriptor;
328        result.is_write = value.is_write;
329        result
330    }
331}
332
333#[derive(Debug)]
334pub struct VmEventVmExit {
335    pub reason: u64,
336    pub qualification: u64,
337}
338
339impl From<vm_event_vmexit> for VmEventVmExit {
340    fn from(value: vm_event_vmexit) -> Self {
341        Self {
342            reason: value.arch.vmx.reason,
343            qualification: value.arch.vmx.qualification,
344        }
345    }
346}
347
348impl From<VmEventVmExit> for vm_event_vmexit {
349    fn from(value: VmEventVmExit) -> Self {
350        let mut result = Self::default();
351        result.arch.vmx.reason = value.reason;
352        result.arch.vmx.qualification = value.qualification;
353        result
354    }
355}
356
357#[derive(Debug)]
358pub struct VmEventIo {
359    pub bytes: u32,    // size of access
360    pub port: u16,     // port number
361    pub direction: u8, // direction (0 = OUT, 1 = IN)
362    pub str: u8,       // string instruction (0 = not string, 1 = string)
363}
364
365impl From<vm_event_io> for VmEventIo {
366    fn from(value: vm_event_io) -> Self {
367        Self {
368            bytes: value.bytes,
369            port: value.port,
370            direction: value.in_,
371            str: value.str_,
372        }
373    }
374}
375
376impl From<VmEventIo> for vm_event_io {
377    fn from(value: VmEventIo) -> Self {
378        Self {
379            bytes: value.bytes,
380            port: value.port,
381            in_: value.direction,
382            str_: value.str,
383        }
384    }
385}
386
387#[derive(Debug)]
388#[repr(u32)]
389pub enum VmEventReason {
390    /// Default case
391    Unknown,
392
393    /// Memory access violation
394    MemoryAccess(VmEventMemAccess),
395
396    /// Memory sharing event
397    MemorySharing(VmEventSharing),
398
399    /// Memory paging event
400    MemoryPaging(VmEventPaging),
401
402    /// A control register was updated
403    WriteCtrlReg(VmEventWriteCtrlReg),
404
405    /// An MSR was updated.
406    MovToMsr(VmEventMovToMsr),
407
408    /// Debug operation executed (e.g. int3)
409    SoftwareBreakpoint(VmEventDebug),
410
411    /// Single-step (e.g. MTF)
412    Singlestep(VmEventSinglestep),
413
414    /// An event has been requested via HVMOP_guest_request_vm_event.
415    GuestRequest,
416
417    /// A debug exception was caught
418    DebugException(VmEventDebug),
419
420    /// CPUID executed
421    Cpuid(VmEventCpuid),
422
423    /// Privileged call executed (e.g. SMC).
424    /// Note: event may be generated even if SMC condition check fails on some CPUs.
425    ///       As this behavior is CPU-specific, users are advised to not rely on it.
426    ///       These kinds of events will be filtered out in future versions.
427    PrivilegedCall,
428
429    /// An interrupt has been delivered.
430    Interrupt(VmEventInterrupt),
431
432    /// A descriptor table register was accessed.
433    DescriptorAccess(VmEventDescriptorAccess),
434
435    /// Current instruction is not implemented by the emulator
436    EmulUnimplemented,
437
438    /// VMEXIT
439    VmExit(VmEventVmExit),
440
441    /// IN/OUT Instruction executed
442    IoInstruction(VmEventIo),
443}