1use libipt_sys::{
2 pt_event, pt_event_type_ptev_async_branch, pt_event_type_ptev_async_disabled,
3 pt_event_type_ptev_async_paging, pt_event_type_ptev_async_vmcs, pt_event_type_ptev_cbr,
4 pt_event_type_ptev_disabled, pt_event_type_ptev_enabled, pt_event_type_ptev_exec_mode,
5 pt_event_type_ptev_exstop, pt_event_type_ptev_mnt, pt_event_type_ptev_mwait,
6 pt_event_type_ptev_overflow, pt_event_type_ptev_paging, pt_event_type_ptev_ptwrite,
7 pt_event_type_ptev_pwre, pt_event_type_ptev_pwrx, pt_event_type_ptev_stop,
8 pt_event_type_ptev_tick, pt_event_type_ptev_tsx, pt_event_type_ptev_vmcs,
9};
10use std::fmt::{Debug, Formatter};
11
12mod enabled;
13pub use enabled::*;
14mod disabled;
15pub use disabled::*;
16mod branch;
17pub use branch::*;
18mod paging;
19pub use paging::*;
20mod overflow;
21pub use overflow::*;
22mod exec_mode;
23pub use exec_mode::*;
24mod tsx;
25pub use tsx::*;
26mod vmcs;
27pub use vmcs::*;
28mod exstop;
29pub use exstop::*;
30mod mwait;
31pub use mwait::*;
32mod pwre;
33pub use pwre::*;
34mod pwrx;
35pub use pwrx::*;
36mod ptwrite;
37pub use ptwrite::*;
38mod tick;
39pub use tick::*;
40mod mnt;
41pub use mnt::*;
42mod cbr;
43pub use cbr::*;
44mod stop;
45pub use stop::*;
46
47mod qry;
48pub use qry::*;
49
50#[derive(Debug, Clone)]
51pub enum EventType {
52 Enabled(Enabled),
53 Disabled(Disabled),
54 AsnycDisabled(AsyncDisabled),
55 AsyncBranch(AsyncBranch),
56 Paging(Paging),
57 AsyncPaging(AsyncPaging),
58 Overflow(Overflow),
59 ExecMode(ExecMode),
60 Tsx(Tsx),
61 Vmcs(Vmcs),
62 AsyncVmcs(AsyncVmcs),
63 Exstop(Exstop),
64 Mwait(Mwait),
65 Pwre(Pwre),
66 Pwrx(Pwrx),
67 Ptwrite(Ptwrite),
68 Tick(Tick),
69 Mnt(Mnt),
70 Cbr(Cbr),
71 Stop(Stop),
72}
73
74impl From<Event> for EventType {
75 fn from(event: Event) -> EventType {
76 event.event_type()
77 }
78}
79
80#[derive(Clone, Copy)]
81#[repr(transparent)]
82pub struct Event(pub(crate) pt_event);
83
84impl Event {
85 #[must_use]
87 pub fn ip_suppressed(&self) -> bool {
88 self.0.ip_suppressed() > 0
89 }
90
91 #[must_use]
93 pub fn status_update(&self) -> bool {
94 self.0.status_update() > 0
95 }
96
97 #[must_use]
101 pub fn tsc(&self) -> Option<u64> {
102 if self.0.has_tsc() > 0 {
103 Some(self.0.tsc)
104 } else {
105 None
106 }
107 }
108
109 #[must_use]
114 pub const fn lost_mtc(&self) -> u32 {
115 self.0.lost_mtc
116 }
117
118 #[must_use]
123 pub const fn lost_cyc(&self) -> u32 {
124 self.0.lost_cyc
125 }
126
127 #[must_use]
129 #[allow(non_upper_case_globals)]
130 pub const fn event_type(self) -> EventType {
131 match self.0.type_ {
132 pt_event_type_ptev_async_branch => EventType::AsyncBranch(AsyncBranch { event: self }),
133 pt_event_type_ptev_async_disabled => {
134 EventType::AsnycDisabled(AsyncDisabled { event: self })
135 }
136 pt_event_type_ptev_async_paging => EventType::AsyncPaging(AsyncPaging { event: self }),
137 pt_event_type_ptev_async_vmcs => EventType::AsyncVmcs(AsyncVmcs { event: self }),
138 pt_event_type_ptev_cbr => EventType::Cbr(Cbr { event: self }),
139 pt_event_type_ptev_disabled => EventType::Disabled(Disabled { event: self }),
140 pt_event_type_ptev_enabled => EventType::Enabled(Enabled { event: self }),
141 pt_event_type_ptev_exec_mode => EventType::ExecMode(ExecMode { event: self }),
142 pt_event_type_ptev_exstop => EventType::Exstop(Exstop { event: self }),
143 pt_event_type_ptev_mnt => EventType::Mnt(Mnt { event: self }),
144 pt_event_type_ptev_mwait => EventType::Mwait(Mwait { event: self }),
145 pt_event_type_ptev_overflow => EventType::Overflow(Overflow { event: self }),
146 pt_event_type_ptev_paging => EventType::Paging(Paging { event: self }),
147 pt_event_type_ptev_ptwrite => EventType::Ptwrite(Ptwrite { event: self }),
148 pt_event_type_ptev_pwre => EventType::Pwre(Pwre { event: self }),
149 pt_event_type_ptev_pwrx => EventType::Pwrx(Pwrx { event: self }),
150 pt_event_type_ptev_tick => EventType::Tick(Tick { event: self }),
151 pt_event_type_ptev_tsx => EventType::Tsx(Tsx { event: self }),
152 pt_event_type_ptev_vmcs => EventType::Vmcs(Vmcs { event: self }),
153 pt_event_type_ptev_stop => EventType::Stop(Stop { event: self }),
154 _ => unreachable!(),
155 }
156 }
157
158 pub(crate) fn fmt_common_fields(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
159 write!(
160 f,
161 "ip_suppressed : {:?}, status_update: {:?}, tsc: {:?}, lost_mtc: {:?}, lost_cyc: {:?},",
162 self.ip_suppressed(),
163 self.status_update(),
164 self.tsc(),
165 self.lost_mtc(),
166 self.lost_cyc(),
167 )
168 }
169}
170
171impl Debug for Event {
172 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
173 self.event_type().fmt(f)
174 }
175}
176
177#[cfg(test)]
178mod test {
179 use super::*;
180 use libipt_sys::pt_event_type_ptev_stop;
181 use std::mem;
182
183 #[test]
184 fn test_create_event() {
185 let evt = pt_event {
186 type_: pt_event_type_ptev_stop,
187 tsc: 1,
188 lost_mtc: 2,
189 lost_cyc: 3,
190 _bitfield_1: pt_event::new_bitfield_1(1, 0, 1),
191 variant: unsafe { mem::zeroed() },
192 reserved: [0; 2],
193 _bitfield_align_1: [],
194 };
195
196 let evt = Event(evt);
197 assert!(evt.ip_suppressed());
198 assert!(!evt.status_update());
199
200 assert_eq!(evt.tsc(), Some(1));
201 assert_eq!(evt.lost_mtc(), 2);
202 assert_eq!(evt.lost_cyc(), 3);
203
204 assert!(matches!(EventType::from(evt), EventType::Stop(Stop { .. })));
205 }
206}