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 2 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_simple_cb_t cb, 80 bool reset); 81 82 void plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, 83 void *func); 84 85 void plugin_unregister_cb__locked(struct qemu_plugin_ctx *ctx, 86 enum qemu_plugin_event ev); 87 88 void 89 plugin_register_cb_udata(qemu_plugin_id_t id, enum qemu_plugin_event ev, 90 void *func, void *udata); 91 92 void 93 plugin_register_dyn_cb__udata(GArray **arr, 94 qemu_plugin_vcpu_udata_cb_t cb, 95 enum qemu_plugin_cb_flags flags, void *udata); 96 97 void 98 plugin_register_dyn_cond_cb__udata(GArray **arr, 99 qemu_plugin_vcpu_udata_cb_t cb, 100 enum qemu_plugin_cb_flags flags, 101 enum qemu_plugin_cond cond, 102 qemu_plugin_u64 entry, 103 uint64_t imm, 104 void *udata); 105 106 void plugin_register_vcpu_mem_cb(GArray **arr, 107 void *cb, 108 enum qemu_plugin_cb_flags flags, 109 enum qemu_plugin_mem_rw rw, 110 void *udata); 111 112 void exec_inline_op(enum plugin_dyn_cb_type type, 113 struct qemu_plugin_inline_cb *cb, 114 int cpu_index); 115 116 int plugin_num_vcpus(void); 117 118 struct qemu_plugin_scoreboard *plugin_scoreboard_new(size_t element_size); 119 120 void plugin_scoreboard_free(struct qemu_plugin_scoreboard *score); 121 122 /** 123 * qemu_plugin_fillin_mode_info() - populate mode specific info 124 * info: pointer to qemu_info_t structure 125 */ 126 void qemu_plugin_fillin_mode_info(qemu_info_t *info); 127 128 #endif /* PLUGIN_H */ 129