1use std::sync::{Mutex, OnceLock};
4
5use crate::{
6 install::{Args, Info},
7 PluginId, TranslationBlock, VCPUIndex,
8};
9use crate::{
10 qemu_plugin_register_flush_cb, qemu_plugin_register_vcpu_exit_cb,
11 qemu_plugin_register_vcpu_idle_cb, qemu_plugin_register_vcpu_init_cb,
12 qemu_plugin_register_vcpu_resume_cb, qemu_plugin_register_vcpu_syscall_cb,
13 qemu_plugin_register_vcpu_syscall_ret_cb, qemu_plugin_register_vcpu_tb_trans_cb,
14};
15
16extern "C" fn handle_qemu_plugin_register_vcpu_init_cb(id: PluginId, vcpu_id: VCPUIndex) {
17 let Some(plugin) = PLUGIN.get() else {
18 panic!("Plugin not set");
19 };
20
21 let Ok(mut plugin) = plugin.lock() else {
22 panic!("Failed to lock plugin");
23 };
24
25 plugin
26 .on_vcpu_init(id, vcpu_id)
27 .expect("Failed running callback on_vcpu_init");
28}
29
30extern "C" fn handle_qemu_plugin_register_vcpu_exit_cb(id: PluginId, vcpu_id: VCPUIndex) {
31 let Some(plugin) = PLUGIN.get() else {
32 panic!("Plugin not set");
33 };
34
35 let Ok(mut plugin) = plugin.lock() else {
36 panic!("Failed to lock plugin");
37 };
38
39 plugin
40 .on_vcpu_exit(id, vcpu_id)
41 .expect("Failed running callback on_vcpu_exit");
42}
43
44extern "C" fn handle_qemu_plugin_register_vcpu_idle_cb(id: PluginId, vcpu_id: VCPUIndex) {
45 let Some(plugin) = PLUGIN.get() else {
46 panic!("Plugin not set");
47 };
48
49 let Ok(mut plugin) = plugin.lock() else {
50 panic!("Failed to lock plugin");
51 };
52
53 plugin
54 .on_vcpu_idle(id, vcpu_id)
55 .expect("Failed running callback on_vcpu_idle");
56}
57
58extern "C" fn handle_qemu_plugin_register_vcpu_resume_cb(id: PluginId, vcpu_id: VCPUIndex) {
59 let Some(plugin) = PLUGIN.get() else {
60 panic!("Plugin not set");
61 };
62
63 let Ok(mut plugin) = plugin.lock() else {
64 panic!("Failed to lock plugin");
65 };
66
67 plugin
68 .on_vcpu_resume(id, vcpu_id)
69 .expect("Failed running callback on_vcpu_resume");
70}
71
72extern "C" fn handle_qemu_plugin_register_vcpu_tb_trans_cb(
73 id: PluginId,
74 tb: *mut crate::sys::qemu_plugin_tb,
75) {
76 let Some(plugin) = PLUGIN.get() else {
77 panic!("Plugin not set");
78 };
79
80 let Ok(mut plugin) = plugin.lock() else {
81 panic!("Failed to lock plugin");
82 };
83
84 let tb = TranslationBlock::from(tb);
85
86 plugin
87 .on_translation_block_translate(id, tb)
88 .expect("Failed running callback on_translation_block_translate");
89}
90
91extern "C" fn handle_qemu_plugin_register_flush_cb(id: PluginId) {
92 let Some(plugin) = PLUGIN.get() else {
93 panic!("Plugin not set");
94 };
95
96 let Ok(mut plugin) = plugin.lock() else {
97 panic!("Failed to lock plugin");
98 };
99
100 plugin
101 .on_flush(id)
102 .expect("Failed running callback on_flush");
103}
104
105extern "C" fn handle_qemu_plugin_register_syscall_cb(
106 id: PluginId,
107 vcpu_index: VCPUIndex,
108 num: i64,
109 a1: u64,
110 a2: u64,
111 a3: u64,
112 a4: u64,
113 a5: u64,
114 a6: u64,
115 a7: u64,
116 a8: u64,
117) {
118 let Some(plugin) = PLUGIN.get() else {
119 panic!("Plugin not set");
120 };
121
122 let Ok(mut plugin) = plugin.lock() else {
123 panic!("Failed to lock plugin");
124 };
125
126 plugin
127 .on_syscall(id, vcpu_index, num, a1, a2, a3, a4, a5, a6, a7, a8)
128 .expect("Failed running callback on_syscall");
129}
130
131extern "C" fn handle_qemu_plugin_register_syscall_ret_cb(
132 id: PluginId,
133 vcpu_index: VCPUIndex,
134 num: i64,
135 ret: i64,
136) {
137 let Some(plugin) = PLUGIN.get() else {
138 panic!("Plugin not set");
139 };
140
141 let Ok(mut plugin) = plugin.lock() else {
142 panic!("Failed to lock plugin");
143 };
144
145 plugin
146 .on_syscall_return(id, vcpu_index, num, ret)
147 .expect("Failed running callback on_syscall_return");
148}
149
150pub trait Register: HasCallbacks + Send + Sync + 'static {
153 #[allow(unused)]
154 fn register_default(
158 &mut self,
159 id: PluginId,
160 args: &Args,
161 info: &Info,
162 ) -> Result<(), anyhow::Error> {
163 qemu_plugin_register_vcpu_init_cb(id, Some(handle_qemu_plugin_register_vcpu_init_cb))?;
164
165 qemu_plugin_register_vcpu_exit_cb(id, Some(handle_qemu_plugin_register_vcpu_exit_cb))?;
166
167 qemu_plugin_register_vcpu_idle_cb(id, Some(handle_qemu_plugin_register_vcpu_idle_cb))?;
168
169 qemu_plugin_register_vcpu_resume_cb(id, Some(handle_qemu_plugin_register_vcpu_resume_cb))?;
170
171 qemu_plugin_register_vcpu_tb_trans_cb(
172 id,
173 Some(handle_qemu_plugin_register_vcpu_tb_trans_cb),
174 )?;
175
176 qemu_plugin_register_flush_cb(id, Some(handle_qemu_plugin_register_flush_cb));
177
178 qemu_plugin_register_vcpu_syscall_cb(id, Some(handle_qemu_plugin_register_syscall_cb));
179
180 qemu_plugin_register_vcpu_syscall_ret_cb(
181 id,
182 Some(handle_qemu_plugin_register_syscall_ret_cb),
183 );
184
185 self.register(id, args, info)?;
186
187 Ok(())
188 }
189
190 #[allow(unused)]
191 fn register(&mut self, id: PluginId, args: &Args, info: &Info) -> Result<(), anyhow::Error> {
194 Ok(())
195 }
196}
197
198pub trait HasCallbacks: Send + Sync + 'static {
200 #[allow(unused)]
201 fn on_vcpu_init(&mut self, id: PluginId, vcpu_id: VCPUIndex) -> Result<(), anyhow::Error> {
208 Ok(())
209 }
210
211 #[allow(unused)]
212 fn on_vcpu_exit(&mut self, id: PluginId, vcpu_id: VCPUIndex) -> Result<(), anyhow::Error> {
219 Ok(())
220 }
221
222 #[allow(unused)]
223 fn on_vcpu_idle(&mut self, id: PluginId, vcpu_id: VCPUIndex) -> Result<(), anyhow::Error> {
230 Ok(())
231 }
232
233 #[allow(unused)]
234 fn on_vcpu_resume(&mut self, id: PluginId, vcpu_id: VCPUIndex) -> Result<(), anyhow::Error> {
241 Ok(())
242 }
243
244 #[allow(unused)]
245 fn on_translation_block_translate(
252 &mut self,
253 id: PluginId,
254 tb: TranslationBlock,
255 ) -> Result<(), anyhow::Error> {
256 Ok(())
257 }
258
259 #[allow(unused)]
260 fn on_flush(&mut self, id: PluginId) -> Result<(), anyhow::Error> {
266 Ok(())
267 }
268
269 #[allow(unused, clippy::too_many_arguments)]
270 fn on_syscall(
286 &mut self,
287 id: PluginId,
288 vcpu_index: VCPUIndex,
289 num: i64,
290 a1: u64,
291 a2: u64,
292 a3: u64,
293 a4: u64,
294 a5: u64,
295 a6: u64,
296 a7: u64,
297 a8: u64,
298 ) -> Result<(), anyhow::Error> {
299 Ok(())
300 }
301
302 #[allow(unused)]
303 fn on_syscall_return(
312 &mut self,
313 id: PluginId,
314 vcpu_index: VCPUIndex,
315 num: i64,
316 ret: i64,
317 ) -> Result<(), anyhow::Error> {
318 Ok(())
319 }
320}
321
322pub trait Plugin: Register + HasCallbacks {}
324
325pub static PLUGIN: OnceLock<Mutex<Box<dyn Plugin>>> = OnceLock::new();