| 1 | /* |
| 2 | * Plugin Shared Internal Functions |
| 3 | * |
| 4 | * Copyright (C) 2019, Linaro |
| 5 | * |
| 6 | * License: GNU GPL, version 2 or later. |
| 7 | * See the COPYING file in the top-level directory. |
| 8 | * |
| 9 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 10 | */ |
| 11 | |
| 12 | #ifndef PLUGIN_H |
| 13 | #define PLUGIN_H |
| 14 | |
| 15 | #include <gmodule.h> |
| 16 | #include "qemu/queue.h" |
| 17 | #include "qemu/qht.h" |
| 18 | |
| 19 | #define QEMU_PLUGIN_MIN_VERSION 7 |
| 20 | |
| 21 | /* global state */ |
| 22 | struct qemu_plugin_state { |
| 23 | QTAILQ_HEAD(, qemu_plugin_ctx) ctxs; |
| 24 | QLIST_HEAD(, qemu_plugin_cb) cb_lists[QEMU_PLUGIN_EV_MAX]; |
| 25 | /* |
| 26 | * Use the HT as a hash map by inserting k == v, which saves memory as |
| 27 | * documented by GLib. The parent struct is obtained with container_of(). |
| 28 | */ |
| 29 | GHashTable *id_ht; |
| 30 | /* |
| 31 | * Use the HT as a hash map. Note that we could use a list here, |
| 32 | * but with the HT we avoid adding a field to CPUState. |
| 33 | */ |
| 34 | GHashTable *cpu_ht; |
| 35 | QLIST_HEAD(, qemu_plugin_scoreboard) scoreboards; |
| 36 | size_t scoreboard_alloc_size; |
| 37 | DECLARE_BITMAP(mask, QEMU_PLUGIN_EV_MAX); |
| 38 | /* |
| 39 | * @lock protects the struct as well as ctx->uninstalling. |
| 40 | * The lock must be acquired by all API ops. |
| 41 | * The lock is recursive, which greatly simplifies things, e.g. |
| 42 | * callback registration from qemu_plugin_vcpu_for_each(). |
| 43 | */ |
| 44 | QemuRecMutex lock; |
| 45 | /* |
| 46 | * HT of callbacks invoked from helpers. All entries are freed when |
| 47 | * the code cache is flushed. |
| 48 | */ |
| 49 | struct qht dyn_cb_arr_ht; |
| 50 | /* How many vcpus were started */ |
| 51 | int num_vcpus; |
| 52 | }; |
| 53 | |
| 54 | |
| 55 | struct qemu_plugin_ctx { |
| 56 | GModule *handle; |
| 57 | qemu_plugin_id_t id; |
| 58 | struct qemu_plugin_cb *callbacks[QEMU_PLUGIN_EV_MAX]; |
| 59 | QTAILQ_ENTRY(qemu_plugin_ctx) entry; |
| 60 | /* |
| 61 | * keep a reference to @desc until uninstall, so that plugins do not have |
| 62 | * to strdup plugin args. |
| 63 | */ |
| 64 | struct qemu_plugin_desc *desc; |
| 65 | bool installing; |
| 66 | bool uninstalling; |
| 67 | bool resetting; |
| 68 | }; |
| 69 | |
| 70 | struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id); |
| 71 | |
| 72 | void plugin_register_inline_op_on_entry(GArray **arr, |
| 73 | enum qemu_plugin_mem_rw rw, |
| 74 | enum qemu_plugin_op op, |
| 75 | qemu_plugin_u64 entry, |
| 76 | uint64_t imm); |
| 77 | |
| 78 | void plugin_reset_uninstall(qemu_plugin_id_t id, |
| 79 | qemu_plugin_udata_cb_t cb, |
| 80 | void *userdata, |
| 81 | bool reset); |
| 82 | |
| 83 | void plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, |
| 84 | void *func); |
| 85 | |
| 86 | void plugin_unregister_cb__locked(struct qemu_plugin_ctx *ctx, |
| 87 | enum qemu_plugin_event ev); |
| 88 | |
| 89 | void |
| 90 | plugin_register_cb_udata(qemu_plugin_id_t id, enum qemu_plugin_event ev, |
| 91 | void *func, void *udata); |
| 92 | |
| 93 | void |
| 94 | plugin_register_dyn_cb__udata(GArray **arr, |
| 95 | qemu_plugin_vcpu_udata_cb_t cb, |
| 96 | enum qemu_plugin_cb_flags flags, void *udata); |
| 97 | |
| 98 | void |
| 99 | plugin_register_dyn_cond_cb__udata(GArray **arr, |
| 100 | qemu_plugin_vcpu_udata_cb_t cb, |
| 101 | enum qemu_plugin_cb_flags flags, |
| 102 | enum qemu_plugin_cond cond, |
| 103 | qemu_plugin_u64 entry, |
| 104 | uint64_t imm, |
| 105 | void *udata); |
| 106 | |
| 107 | void plugin_register_vcpu_mem_cb(GArray **arr, |
| 108 | void *cb, |
| 109 | enum qemu_plugin_cb_flags flags, |
| 110 | enum qemu_plugin_mem_rw rw, |
| 111 | void *udata); |
| 112 | |
| 113 | void exec_inline_op(enum plugin_dyn_cb_type type, |
| 114 | struct qemu_plugin_inline_cb *cb, |
| 115 | int cpu_index); |
| 116 | |
| 117 | int plugin_num_vcpus(void); |
| 118 | |
| 119 | struct qemu_plugin_scoreboard *plugin_scoreboard_new(size_t element_size); |
| 120 | |
| 121 | void plugin_scoreboard_free(struct qemu_plugin_scoreboard *score); |
| 122 | |
| 123 | /** |
| 124 | * qemu_plugin_fillin_mode_info() - populate mode specific info |
| 125 | * info: pointer to qemu_info_t structure |
| 126 | */ |
| 127 | void qemu_plugin_fillin_mode_info(qemu_info_t *info); |
| 128 | |
| 129 | #endif /* PLUGIN_H */ |