xref: /openbmc/qemu/plugins/api.c (revision b2580720)
1 /*
2  * QEMU Plugin API
3  *
4  * This provides the API that is available to the plugins to interact
5  * with QEMU. We have to be careful not to expose internal details of
6  * how QEMU works so we abstract out things like translation and
7  * instructions to anonymous data types:
8  *
9  *  qemu_plugin_tb
10  *  qemu_plugin_insn
11  *  qemu_plugin_register
12  *
13  * Which can then be passed back into the API to do additional things.
14  * As such all the public functions in here are exported in
15  * qemu-plugin.h.
16  *
17  * The general life-cycle of a plugin is:
18  *
19  *  - plugin is loaded, public qemu_plugin_install called
20  *    - the install func registers callbacks for events
21  *    - usually an atexit_cb is registered to dump info at the end
22  *  - when a registered event occurs the plugin is called
23  *     - some events pass additional info
24  *     - during translation the plugin can decide to instrument any
25  *       instruction
26  *  - when QEMU exits all the registered atexit callbacks are called
27  *
28  * Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
29  * Copyright (C) 2019, Linaro
30  *
31  * License: GNU GPL, version 2 or later.
32  *   See the COPYING file in the top-level directory.
33  *
34  * SPDX-License-Identifier: GPL-2.0-or-later
35  *
36  */
37 
38 #include "qemu/osdep.h"
39 #include "qemu/main-loop.h"
40 #include "qemu/plugin.h"
41 #include "qemu/log.h"
42 #include "tcg/tcg.h"
43 #include "exec/exec-all.h"
44 #include "exec/gdbstub.h"
45 #include "exec/translator.h"
46 #include "disas/disas.h"
47 #include "plugin.h"
48 #ifndef CONFIG_USER_ONLY
49 #include "exec/ram_addr.h"
50 #include "qemu/plugin-memory.h"
51 #include "hw/boards.h"
52 #else
53 #include "qemu.h"
54 #ifdef CONFIG_LINUX
55 #include "loader.h"
56 #endif
57 #endif
58 
59 /* Uninstall and Reset handlers */
60 
61 void qemu_plugin_uninstall(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb)
62 {
63     plugin_reset_uninstall(id, cb, false);
64 }
65 
66 void qemu_plugin_reset(qemu_plugin_id_t id, qemu_plugin_simple_cb_t cb)
67 {
68     plugin_reset_uninstall(id, cb, true);
69 }
70 
71 /*
72  * Plugin Register Functions
73  *
74  * This allows the plugin to register callbacks for various events
75  * during the translation.
76  */
77 
78 void qemu_plugin_register_vcpu_init_cb(qemu_plugin_id_t id,
79                                        qemu_plugin_vcpu_simple_cb_t cb)
80 {
81     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_INIT, cb);
82 }
83 
84 void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id,
85                                        qemu_plugin_vcpu_simple_cb_t cb)
86 {
87     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXIT, cb);
88 }
89 
90 static bool tb_is_mem_only(void)
91 {
92     return tb_cflags(tcg_ctx->gen_tb) & CF_MEMI_ONLY;
93 }
94 
95 void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,
96                                           qemu_plugin_vcpu_udata_cb_t cb,
97                                           enum qemu_plugin_cb_flags flags,
98                                           void *udata)
99 {
100     if (!tb_is_mem_only()) {
101         plugin_register_dyn_cb__udata(&tb->cbs, cb, flags, udata);
102     }
103 }
104 
105 void qemu_plugin_register_vcpu_tb_exec_cond_cb(struct qemu_plugin_tb *tb,
106                                                qemu_plugin_vcpu_udata_cb_t cb,
107                                                enum qemu_plugin_cb_flags flags,
108                                                enum qemu_plugin_cond cond,
109                                                qemu_plugin_u64 entry,
110                                                uint64_t imm,
111                                                void *udata)
112 {
113     if (cond == QEMU_PLUGIN_COND_NEVER || tb_is_mem_only()) {
114         return;
115     }
116     if (cond == QEMU_PLUGIN_COND_ALWAYS) {
117         qemu_plugin_register_vcpu_tb_exec_cb(tb, cb, flags, udata);
118         return;
119     }
120     plugin_register_dyn_cond_cb__udata(&tb->cbs, cb, flags,
121                                        cond, entry, imm, udata);
122 }
123 
124 void qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu(
125     struct qemu_plugin_tb *tb,
126     enum qemu_plugin_op op,
127     qemu_plugin_u64 entry,
128     uint64_t imm)
129 {
130     if (!tb_is_mem_only()) {
131         plugin_register_inline_op_on_entry(&tb->cbs, 0, op, entry, imm);
132     }
133 }
134 
135 void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,
136                                             qemu_plugin_vcpu_udata_cb_t cb,
137                                             enum qemu_plugin_cb_flags flags,
138                                             void *udata)
139 {
140     if (!tb_is_mem_only()) {
141         plugin_register_dyn_cb__udata(&insn->insn_cbs, cb, flags, udata);
142     }
143 }
144 
145 void qemu_plugin_register_vcpu_insn_exec_cond_cb(
146     struct qemu_plugin_insn *insn,
147     qemu_plugin_vcpu_udata_cb_t cb,
148     enum qemu_plugin_cb_flags flags,
149     enum qemu_plugin_cond cond,
150     qemu_plugin_u64 entry,
151     uint64_t imm,
152     void *udata)
153 {
154     if (cond == QEMU_PLUGIN_COND_NEVER || tb_is_mem_only()) {
155         return;
156     }
157     if (cond == QEMU_PLUGIN_COND_ALWAYS) {
158         qemu_plugin_register_vcpu_insn_exec_cb(insn, cb, flags, udata);
159         return;
160     }
161     plugin_register_dyn_cond_cb__udata(&insn->insn_cbs, cb, flags,
162                                        cond, entry, imm, udata);
163 }
164 
165 void qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
166     struct qemu_plugin_insn *insn,
167     enum qemu_plugin_op op,
168     qemu_plugin_u64 entry,
169     uint64_t imm)
170 {
171     if (!tb_is_mem_only()) {
172         plugin_register_inline_op_on_entry(&insn->insn_cbs, 0, op, entry, imm);
173     }
174 }
175 
176 
177 /*
178  * We always plant memory instrumentation because they don't finalise until
179  * after the operation has complete.
180  */
181 void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn,
182                                       qemu_plugin_vcpu_mem_cb_t cb,
183                                       enum qemu_plugin_cb_flags flags,
184                                       enum qemu_plugin_mem_rw rw,
185                                       void *udata)
186 {
187     plugin_register_vcpu_mem_cb(&insn->mem_cbs, cb, flags, rw, udata);
188 }
189 
190 void qemu_plugin_register_vcpu_mem_inline_per_vcpu(
191     struct qemu_plugin_insn *insn,
192     enum qemu_plugin_mem_rw rw,
193     enum qemu_plugin_op op,
194     qemu_plugin_u64 entry,
195     uint64_t imm)
196 {
197     plugin_register_inline_op_on_entry(&insn->mem_cbs, rw, op, entry, imm);
198 }
199 
200 void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id,
201                                            qemu_plugin_vcpu_tb_trans_cb_t cb)
202 {
203     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_TB_TRANS, cb);
204 }
205 
206 void qemu_plugin_register_vcpu_syscall_cb(qemu_plugin_id_t id,
207                                           qemu_plugin_vcpu_syscall_cb_t cb)
208 {
209     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL, cb);
210 }
211 
212 void
213 qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id,
214                                          qemu_plugin_vcpu_syscall_ret_cb_t cb)
215 {
216     plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_SYSCALL_RET, cb);
217 }
218 
219 /*
220  * Plugin Queries
221  *
222  * These are queries that the plugin can make to gauge information
223  * from our opaque data types. We do not want to leak internal details
224  * here just information useful to the plugin.
225  */
226 
227 /*
228  * Translation block information:
229  *
230  * A plugin can query the virtual address of the start of the block
231  * and the number of instructions in it. It can also get access to
232  * each translated instruction.
233  */
234 
235 size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb)
236 {
237     return tb->n;
238 }
239 
240 uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb)
241 {
242     const DisasContextBase *db = tcg_ctx->plugin_db;
243     return db->pc_first;
244 }
245 
246 struct qemu_plugin_insn *
247 qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx)
248 {
249     struct qemu_plugin_insn *insn;
250     if (unlikely(idx >= tb->n)) {
251         return NULL;
252     }
253     insn = g_ptr_array_index(tb->insns, idx);
254     return insn;
255 }
256 
257 /*
258  * Instruction information
259  *
260  * These queries allow the plugin to retrieve information about each
261  * instruction being translated.
262  */
263 
264 size_t qemu_plugin_insn_data(const struct qemu_plugin_insn *insn,
265                              void *dest, size_t len)
266 {
267     const DisasContextBase *db = tcg_ctx->plugin_db;
268 
269     len = MIN(len, insn->len);
270     return translator_st(db, dest, insn->vaddr, len) ? len : 0;
271 }
272 
273 size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn)
274 {
275     return insn->len;
276 }
277 
278 uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn)
279 {
280     return insn->vaddr;
281 }
282 
283 void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn)
284 {
285     const DisasContextBase *db = tcg_ctx->plugin_db;
286     vaddr page0_last = db->pc_first | ~TARGET_PAGE_MASK;
287 
288     if (db->fake_insn) {
289         return NULL;
290     }
291 
292     /*
293      * ??? The return value is not intended for use of host memory,
294      * but as a proxy for address space and physical address.
295      * Thus we are only interested in the first byte and do not
296      * care about spanning pages.
297      */
298     if (insn->vaddr <= page0_last) {
299         if (db->host_addr[0] == NULL) {
300             return NULL;
301         }
302         return db->host_addr[0] + insn->vaddr - db->pc_first;
303     } else {
304         if (db->host_addr[1] == NULL) {
305             return NULL;
306         }
307         return db->host_addr[1] + insn->vaddr - (page0_last + 1);
308     }
309 }
310 
311 char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn)
312 {
313     return plugin_disas(tcg_ctx->cpu, tcg_ctx->plugin_db,
314                         insn->vaddr, insn->len);
315 }
316 
317 const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn)
318 {
319     const char *sym = lookup_symbol(insn->vaddr);
320     return sym[0] != 0 ? sym : NULL;
321 }
322 
323 /*
324  * The memory queries allow the plugin to query information about a
325  * memory access.
326  */
327 
328 unsigned qemu_plugin_mem_size_shift(qemu_plugin_meminfo_t info)
329 {
330     MemOp op = get_memop(info);
331     return op & MO_SIZE;
332 }
333 
334 bool qemu_plugin_mem_is_sign_extended(qemu_plugin_meminfo_t info)
335 {
336     MemOp op = get_memop(info);
337     return op & MO_SIGN;
338 }
339 
340 bool qemu_plugin_mem_is_big_endian(qemu_plugin_meminfo_t info)
341 {
342     MemOp op = get_memop(info);
343     return (op & MO_BSWAP) == MO_BE;
344 }
345 
346 bool qemu_plugin_mem_is_store(qemu_plugin_meminfo_t info)
347 {
348     return get_plugin_meminfo_rw(info) & QEMU_PLUGIN_MEM_W;
349 }
350 
351 /*
352  * Virtual Memory queries
353  */
354 
355 #ifdef CONFIG_SOFTMMU
356 static __thread struct qemu_plugin_hwaddr hwaddr_info;
357 #endif
358 
359 struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info,
360                                                   uint64_t vaddr)
361 {
362 #ifdef CONFIG_SOFTMMU
363     CPUState *cpu = current_cpu;
364     unsigned int mmu_idx = get_mmuidx(info);
365     enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
366     hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0;
367 
368     assert(mmu_idx < NB_MMU_MODES);
369 
370     if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx,
371                            hwaddr_info.is_store, &hwaddr_info)) {
372         error_report("invalid use of qemu_plugin_get_hwaddr");
373         return NULL;
374     }
375 
376     return &hwaddr_info;
377 #else
378     return NULL;
379 #endif
380 }
381 
382 bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
383 {
384 #ifdef CONFIG_SOFTMMU
385     return haddr->is_io;
386 #else
387     return false;
388 #endif
389 }
390 
391 uint64_t qemu_plugin_hwaddr_phys_addr(const struct qemu_plugin_hwaddr *haddr)
392 {
393 #ifdef CONFIG_SOFTMMU
394     if (haddr) {
395         return haddr->phys_addr;
396     }
397 #endif
398     return 0;
399 }
400 
401 const char *qemu_plugin_hwaddr_device_name(const struct qemu_plugin_hwaddr *h)
402 {
403 #ifdef CONFIG_SOFTMMU
404     if (h && h->is_io) {
405         MemoryRegion *mr = h->mr;
406         if (!mr->name) {
407             unsigned maddr = (uintptr_t)mr;
408             g_autofree char *temp = g_strdup_printf("anon%08x", maddr);
409             return g_intern_string(temp);
410         } else {
411             return g_intern_string(mr->name);
412         }
413     } else {
414         return g_intern_static_string("RAM");
415     }
416 #else
417     return g_intern_static_string("Invalid");
418 #endif
419 }
420 
421 int qemu_plugin_num_vcpus(void)
422 {
423     return plugin_num_vcpus();
424 }
425 
426 /*
427  * Plugin output
428  */
429 void qemu_plugin_outs(const char *string)
430 {
431     qemu_log_mask(CPU_LOG_PLUGIN, "%s", string);
432 }
433 
434 bool qemu_plugin_bool_parse(const char *name, const char *value, bool *ret)
435 {
436     return name && value && qapi_bool_parse(name, value, ret, NULL);
437 }
438 
439 /*
440  * Binary path, start and end locations
441  */
442 const char *qemu_plugin_path_to_binary(void)
443 {
444     char *path = NULL;
445 #ifdef CONFIG_USER_ONLY
446     TaskState *ts = get_task_state(current_cpu);
447     path = g_strdup(ts->bprm->filename);
448 #endif
449     return path;
450 }
451 
452 uint64_t qemu_plugin_start_code(void)
453 {
454     uint64_t start = 0;
455 #ifdef CONFIG_USER_ONLY
456     TaskState *ts = get_task_state(current_cpu);
457     start = ts->info->start_code;
458 #endif
459     return start;
460 }
461 
462 uint64_t qemu_plugin_end_code(void)
463 {
464     uint64_t end = 0;
465 #ifdef CONFIG_USER_ONLY
466     TaskState *ts = get_task_state(current_cpu);
467     end = ts->info->end_code;
468 #endif
469     return end;
470 }
471 
472 uint64_t qemu_plugin_entry_code(void)
473 {
474     uint64_t entry = 0;
475 #ifdef CONFIG_USER_ONLY
476     TaskState *ts = get_task_state(current_cpu);
477     entry = ts->info->entry;
478 #endif
479     return entry;
480 }
481 
482 /*
483  * Create register handles.
484  *
485  * We need to create a handle for each register so the plugin
486  * infrastructure can call gdbstub to read a register. They are
487  * currently just a pointer encapsulation of the gdb_reg but in
488  * future may hold internal plugin state so its important plugin
489  * authors are not tempted to treat them as numbers.
490  *
491  * We also construct a result array with those handles and some
492  * ancillary data the plugin might find useful.
493  */
494 
495 static GArray *create_register_handles(GArray *gdbstub_regs)
496 {
497     GArray *find_data = g_array_new(true, true,
498                                     sizeof(qemu_plugin_reg_descriptor));
499 
500     for (int i = 0; i < gdbstub_regs->len; i++) {
501         GDBRegDesc *grd = &g_array_index(gdbstub_regs, GDBRegDesc, i);
502         qemu_plugin_reg_descriptor desc;
503 
504         /* skip "un-named" regs */
505         if (!grd->name) {
506             continue;
507         }
508 
509         /* Create a record for the plugin */
510         desc.handle = GINT_TO_POINTER(grd->gdb_reg);
511         desc.name = g_intern_string(grd->name);
512         desc.feature = g_intern_string(grd->feature_name);
513         g_array_append_val(find_data, desc);
514     }
515 
516     return find_data;
517 }
518 
519 GArray *qemu_plugin_get_registers(void)
520 {
521     g_assert(current_cpu);
522 
523     g_autoptr(GArray) regs = gdb_get_register_list(current_cpu);
524     return create_register_handles(regs);
525 }
526 
527 int qemu_plugin_read_register(struct qemu_plugin_register *reg, GByteArray *buf)
528 {
529     g_assert(current_cpu);
530 
531     return gdb_read_register(current_cpu, buf, GPOINTER_TO_INT(reg));
532 }
533 
534 struct qemu_plugin_scoreboard *qemu_plugin_scoreboard_new(size_t element_size)
535 {
536     return plugin_scoreboard_new(element_size);
537 }
538 
539 void qemu_plugin_scoreboard_free(struct qemu_plugin_scoreboard *score)
540 {
541     plugin_scoreboard_free(score);
542 }
543 
544 void *qemu_plugin_scoreboard_find(struct qemu_plugin_scoreboard *score,
545                                   unsigned int vcpu_index)
546 {
547     g_assert(vcpu_index < qemu_plugin_num_vcpus());
548     /* we can't use g_array_index since entry size is not statically known */
549     char *base_ptr = score->data->data;
550     return base_ptr + vcpu_index * g_array_get_element_size(score->data);
551 }
552 
553 static uint64_t *plugin_u64_address(qemu_plugin_u64 entry,
554                                     unsigned int vcpu_index)
555 {
556     char *ptr = qemu_plugin_scoreboard_find(entry.score, vcpu_index);
557     return (uint64_t *)(ptr + entry.offset);
558 }
559 
560 void qemu_plugin_u64_add(qemu_plugin_u64 entry, unsigned int vcpu_index,
561                          uint64_t added)
562 {
563     *plugin_u64_address(entry, vcpu_index) += added;
564 }
565 
566 uint64_t qemu_plugin_u64_get(qemu_plugin_u64 entry,
567                              unsigned int vcpu_index)
568 {
569     return *plugin_u64_address(entry, vcpu_index);
570 }
571 
572 void qemu_plugin_u64_set(qemu_plugin_u64 entry, unsigned int vcpu_index,
573                          uint64_t val)
574 {
575     *plugin_u64_address(entry, vcpu_index) = val;
576 }
577 
578 uint64_t qemu_plugin_u64_sum(qemu_plugin_u64 entry)
579 {
580     uint64_t total = 0;
581     for (int i = 0, n = qemu_plugin_num_vcpus(); i < n; ++i) {
582         total += qemu_plugin_u64_get(entry, i);
583     }
584     return total;
585 }
586