Emilio G. Cota | 54cb65d | 2017-08-30 18:39:53 -0400 | [diff] [blame] | 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 | |
Markus Armbruster | 52581c7 | 2022-05-06 15:49:08 +0200 | [diff] [blame] | 12 | #ifndef PLUGIN_H |
| 13 | #define PLUGIN_H |
Emilio G. Cota | 54cb65d | 2017-08-30 18:39:53 -0400 | [diff] [blame] | 14 | |
| 15 | #include <gmodule.h> |
Philippe Mathieu-Daudé | 824f4ba | 2021-05-24 19:04:52 +0200 | [diff] [blame] | 16 | #include "qemu/qht.h" |
Emilio G. Cota | 54cb65d | 2017-08-30 18:39:53 -0400 | [diff] [blame] | 17 | |
Alex Bennée | 3fb356c | 2019-11-04 13:18:36 +0000 | [diff] [blame] | 18 | #define QEMU_PLUGIN_MIN_VERSION 0 |
| 19 | |
Emilio G. Cota | 54cb65d | 2017-08-30 18:39:53 -0400 | [diff] [blame] | 20 | /* global state */ |
| 21 | struct qemu_plugin_state { |
| 22 | QTAILQ_HEAD(, qemu_plugin_ctx) ctxs; |
| 23 | QLIST_HEAD(, qemu_plugin_cb) cb_lists[QEMU_PLUGIN_EV_MAX]; |
| 24 | /* |
| 25 | * Use the HT as a hash map by inserting k == v, which saves memory as |
| 26 | * documented by GLib. The parent struct is obtained with container_of(). |
| 27 | */ |
| 28 | GHashTable *id_ht; |
| 29 | /* |
| 30 | * Use the HT as a hash map. Note that we could use a list here, |
| 31 | * but with the HT we avoid adding a field to CPUState. |
| 32 | */ |
| 33 | GHashTable *cpu_ht; |
| 34 | DECLARE_BITMAP(mask, QEMU_PLUGIN_EV_MAX); |
| 35 | /* |
| 36 | * @lock protects the struct as well as ctx->uninstalling. |
| 37 | * The lock must be acquired by all API ops. |
| 38 | * The lock is recursive, which greatly simplifies things, e.g. |
| 39 | * callback registration from qemu_plugin_vcpu_for_each(). |
| 40 | */ |
| 41 | QemuRecMutex lock; |
| 42 | /* |
| 43 | * HT of callbacks invoked from helpers. All entries are freed when |
| 44 | * the code cache is flushed. |
| 45 | */ |
| 46 | struct qht dyn_cb_arr_ht; |
| 47 | }; |
| 48 | |
| 49 | |
| 50 | struct qemu_plugin_ctx { |
| 51 | GModule *handle; |
| 52 | qemu_plugin_id_t id; |
| 53 | struct qemu_plugin_cb *callbacks[QEMU_PLUGIN_EV_MAX]; |
| 54 | QTAILQ_ENTRY(qemu_plugin_ctx) entry; |
| 55 | /* |
| 56 | * keep a reference to @desc until uninstall, so that plugins do not have |
| 57 | * to strdup plugin args. |
| 58 | */ |
| 59 | struct qemu_plugin_desc *desc; |
| 60 | bool installing; |
| 61 | bool uninstalling; |
| 62 | bool resetting; |
| 63 | }; |
| 64 | |
| 65 | struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id); |
| 66 | |
| 67 | void plugin_register_inline_op(GArray **arr, |
| 68 | enum qemu_plugin_mem_rw rw, |
| 69 | enum qemu_plugin_op op, void *ptr, |
| 70 | uint64_t imm); |
| 71 | |
| 72 | void plugin_reset_uninstall(qemu_plugin_id_t id, |
| 73 | qemu_plugin_simple_cb_t cb, |
| 74 | bool reset); |
| 75 | |
| 76 | void plugin_register_cb(qemu_plugin_id_t id, enum qemu_plugin_event ev, |
| 77 | void *func); |
| 78 | |
| 79 | void plugin_unregister_cb__locked(struct qemu_plugin_ctx *ctx, |
| 80 | enum qemu_plugin_event ev); |
| 81 | |
| 82 | void |
| 83 | plugin_register_cb_udata(qemu_plugin_id_t id, enum qemu_plugin_event ev, |
| 84 | void *func, void *udata); |
| 85 | |
| 86 | void |
| 87 | plugin_register_dyn_cb__udata(GArray **arr, |
| 88 | qemu_plugin_vcpu_udata_cb_t cb, |
| 89 | enum qemu_plugin_cb_flags flags, void *udata); |
| 90 | |
| 91 | |
| 92 | void plugin_register_vcpu_mem_cb(GArray **arr, |
| 93 | void *cb, |
| 94 | enum qemu_plugin_cb_flags flags, |
| 95 | enum qemu_plugin_mem_rw rw, |
| 96 | void *udata); |
| 97 | |
| 98 | void exec_inline_op(struct qemu_plugin_dyn_cb *cb); |
| 99 | |
Markus Armbruster | 52581c7 | 2022-05-06 15:49:08 +0200 | [diff] [blame] | 100 | #endif /* PLUGIN_H */ |