1
2
3
4
5
6
7#ifndef QEMU_PLUGIN_H
8#define QEMU_PLUGIN_H
9
10#include "qemu/config-file.h"
11#include "qemu/qemu-plugin.h"
12#include "qemu/error-report.h"
13#include "qemu/queue.h"
14#include "qemu/option.h"
15#include "qemu/plugin-event.h"
16#include "qemu/bitmap.h"
17#include "exec/memopidx.h"
18#include "hw/core/cpu.h"
19
20
21
22
23
24struct qemu_plugin_desc;
25typedef QTAILQ_HEAD(, qemu_plugin_desc) QemuPluginList;
26
27
28
29
30static inline qemu_plugin_meminfo_t
31make_plugin_meminfo(MemOpIdx oi, enum qemu_plugin_mem_rw rw)
32{
33 return oi | (rw << 16);
34}
35
36
37
38
39
40static inline enum qemu_plugin_mem_rw
41get_plugin_meminfo_rw(qemu_plugin_meminfo_t i)
42{
43 return i >> 16;
44}
45
46#ifdef CONFIG_PLUGIN
47extern QemuOptsList qemu_plugin_opts;
48
49static inline void qemu_plugin_add_opts(void)
50{
51 qemu_add_opts(&qemu_plugin_opts);
52}
53
54void qemu_plugin_opt_parse(const char *optstr, QemuPluginList *head);
55int qemu_plugin_load_list(QemuPluginList *head, Error **errp);
56
57union qemu_plugin_cb_sig {
58 qemu_plugin_simple_cb_t simple;
59 qemu_plugin_udata_cb_t udata;
60 qemu_plugin_vcpu_simple_cb_t vcpu_simple;
61 qemu_plugin_vcpu_udata_cb_t vcpu_udata;
62 qemu_plugin_vcpu_tb_trans_cb_t vcpu_tb_trans;
63 qemu_plugin_vcpu_mem_cb_t vcpu_mem;
64 qemu_plugin_vcpu_syscall_cb_t vcpu_syscall;
65 qemu_plugin_vcpu_syscall_ret_cb_t vcpu_syscall_ret;
66 void *generic;
67};
68
69enum plugin_dyn_cb_type {
70 PLUGIN_CB_REGULAR,
71 PLUGIN_CB_COND,
72 PLUGIN_CB_MEM_REGULAR,
73 PLUGIN_CB_INLINE_ADD_U64,
74 PLUGIN_CB_INLINE_STORE_U64,
75};
76
77struct qemu_plugin_regular_cb {
78 union qemu_plugin_cb_sig f;
79 TCGHelperInfo *info;
80 void *userp;
81 enum qemu_plugin_mem_rw rw;
82};
83
84struct qemu_plugin_inline_cb {
85 qemu_plugin_u64 entry;
86 uint64_t imm;
87 enum qemu_plugin_mem_rw rw;
88};
89
90struct qemu_plugin_conditional_cb {
91 union qemu_plugin_cb_sig f;
92 TCGHelperInfo *info;
93 void *userp;
94 qemu_plugin_u64 entry;
95 enum qemu_plugin_cond cond;
96 uint64_t imm;
97};
98
99
100
101
102
103
104struct qemu_plugin_dyn_cb {
105 enum plugin_dyn_cb_type type;
106 union {
107 struct qemu_plugin_regular_cb regular;
108 struct qemu_plugin_conditional_cb cond;
109 struct qemu_plugin_inline_cb inline_insn;
110 };
111};
112
113
114struct qemu_plugin_insn {
115 uint64_t vaddr;
116 GArray *insn_cbs;
117 GArray *mem_cbs;
118 uint8_t len;
119 bool calls_helpers;
120
121
122 bool mem_helper;
123};
124
125
126struct qemu_plugin_scoreboard {
127 GArray *data;
128 QLIST_ENTRY(qemu_plugin_scoreboard) entry;
129};
130
131
132struct qemu_plugin_tb {
133 GPtrArray *insns;
134 size_t n;
135
136
137 bool mem_helper;
138
139 GArray *cbs;
140};
141
142
143
144
145
146struct CPUPluginState {
147 DECLARE_BITMAP(event_mask, QEMU_PLUGIN_EV_MAX);
148};
149
150
151
152
153
154
155
156CPUPluginState *qemu_plugin_create_vcpu_state(void);
157
158void qemu_plugin_vcpu_init_hook(CPUState *cpu);
159void qemu_plugin_vcpu_exit_hook(CPUState *cpu);
160void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb);
161void qemu_plugin_vcpu_idle_cb(CPUState *cpu);
162void qemu_plugin_vcpu_resume_cb(CPUState *cpu);
163void
164qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1,
165 uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5,
166 uint64_t a6, uint64_t a7, uint64_t a8);
167void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret);
168
169void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
170 uint64_t value_low,
171 uint64_t value_high,
172 MemOpIdx oi, enum qemu_plugin_mem_rw rw);
173
174void qemu_plugin_flush_cb(void);
175
176void qemu_plugin_atexit_cb(void);
177
178void qemu_plugin_add_dyn_cb_arr(GArray *arr);
179
180static inline void qemu_plugin_disable_mem_helpers(CPUState *cpu)
181{
182 cpu->neg.plugin_mem_cbs = NULL;
183}
184
185
186
187
188
189
190
191
192
193void qemu_plugin_user_exit(void);
194
195
196
197
198
199
200
201void qemu_plugin_user_prefork_lock(void);
202
203
204
205
206
207
208
209
210void qemu_plugin_user_postfork(bool is_child);
211
212enum qemu_plugin_cb_flags tcg_call_to_qemu_plugin_cb_flags(int flags);
213
214static inline void qemu_plugin_set_cb_flags(CPUState *cpu,
215 enum qemu_plugin_cb_flags flags)
216{
217 assert(cpu);
218 cpu->neg.plugin_cb_flags = flags;
219}
220
221static inline enum qemu_plugin_cb_flags qemu_plugin_get_cb_flags(void)
222{
223 assert(current_cpu);
224 return current_cpu->neg.plugin_cb_flags;
225}
226
227#else
228
229static inline void qemu_plugin_add_opts(void)
230{ }
231
232static inline void qemu_plugin_opt_parse(const char *optstr,
233 QemuPluginList *head)
234{
235 error_report("plugin interface not enabled in this build");
236 exit(1);
237}
238
239static inline int qemu_plugin_load_list(QemuPluginList *head, Error **errp)
240{
241 return 0;
242}
243
244static inline void qemu_plugin_vcpu_init_hook(CPUState *cpu)
245{ }
246
247static inline void qemu_plugin_vcpu_exit_hook(CPUState *cpu)
248{ }
249
250static inline void qemu_plugin_tb_trans_cb(CPUState *cpu,
251 struct qemu_plugin_tb *tb)
252{ }
253
254static inline void qemu_plugin_vcpu_idle_cb(CPUState *cpu)
255{ }
256
257static inline void qemu_plugin_vcpu_resume_cb(CPUState *cpu)
258{ }
259
260static inline void
261qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2,
262 uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6,
263 uint64_t a7, uint64_t a8)
264{ }
265
266static inline
267void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret)
268{ }
269
270static inline void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
271 uint64_t value_low,
272 uint64_t value_high,
273 MemOpIdx oi,
274 enum qemu_plugin_mem_rw rw)
275{ }
276
277static inline void qemu_plugin_flush_cb(void)
278{ }
279
280static inline void qemu_plugin_atexit_cb(void)
281{ }
282
283static inline
284void qemu_plugin_add_dyn_cb_arr(GArray *arr)
285{ }
286
287static inline void qemu_plugin_disable_mem_helpers(CPUState *cpu)
288{ }
289
290static inline void qemu_plugin_user_exit(void)
291{ }
292
293static inline void qemu_plugin_user_prefork_lock(void)
294{ }
295
296static inline void qemu_plugin_user_postfork(bool is_child)
297{ }
298
299#endif
300
301#endif
302