plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
/*
|
|
|
|
* plugin-gen.c - TCG-related bits of plugin infrastructure
|
|
|
|
*
|
|
|
|
* Copyright (C) 2018, Emilio G. Cota <cota@braap.org>
|
|
|
|
* License: GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
|
|
|
*
|
|
|
|
* We support instrumentation at an instruction granularity. That is,
|
|
|
|
* if a plugin wants to instrument the memory accesses performed by a
|
|
|
|
* particular instruction, it can just do that instead of instrumenting
|
|
|
|
* all memory accesses. Thus, in order to do this we first have to
|
|
|
|
* translate a TB, so that plugins can decide what/where to instrument.
|
|
|
|
*
|
|
|
|
* Injecting the desired instrumentation could be done with a second
|
|
|
|
* translation pass that combined the instrumentation requests, but that
|
|
|
|
* would be ugly and inefficient since we would decode the guest code twice.
|
2024-03-15 08:47:31 +03:00
|
|
|
* Instead, during TB translation we add "plugin_cb" marker opcodes
|
|
|
|
* for all possible instrumentation events, and then once we collect the
|
|
|
|
* instrumentation requests from plugins, we generate code for those markers
|
|
|
|
* or remove them if they have no requests.
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
2024-02-27 17:43:28 +03:00
|
|
|
#include "qemu/plugin.h"
|
2024-03-15 23:33:49 +03:00
|
|
|
#include "qemu/log.h"
|
2023-04-02 07:22:06 +03:00
|
|
|
#include "cpu.h"
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
#include "tcg/tcg.h"
|
2023-02-25 11:45:43 +03:00
|
|
|
#include "tcg/tcg-temp-internal.h"
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
#include "tcg/tcg-op.h"
|
|
|
|
#include "exec/exec-all.h"
|
|
|
|
#include "exec/plugin-gen.h"
|
|
|
|
#include "exec/translator.h"
|
|
|
|
|
|
|
|
enum plugin_gen_from {
|
|
|
|
PLUGIN_GEN_FROM_TB,
|
|
|
|
PLUGIN_GEN_FROM_INSN,
|
|
|
|
PLUGIN_GEN_AFTER_INSN,
|
2024-03-15 12:47:07 +03:00
|
|
|
PLUGIN_GEN_AFTER_TB,
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/* called before finishing a TB with exit_tb, goto_tb or goto_ptr */
|
|
|
|
void plugin_gen_disable_mem_helpers(void)
|
|
|
|
{
|
2024-03-15 12:47:07 +03:00
|
|
|
if (tcg_ctx->plugin_insn) {
|
|
|
|
tcg_gen_plugin_cb(PLUGIN_GEN_AFTER_TB);
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-15 00:27:35 +03:00
|
|
|
static void gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
|
|
|
|
struct qemu_plugin_insn *insn)
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
{
|
2024-03-15 00:27:35 +03:00
|
|
|
GArray *arr;
|
2024-03-15 05:02:19 +03:00
|
|
|
size_t len;
|
2024-03-15 00:27:35 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Tracking memory accesses performed from helpers requires extra work.
|
|
|
|
* If an instruction is emulated with helpers, we do two things:
|
|
|
|
* (1) copy the CB descriptors, and keep track of it so that they can be
|
2024-01-10 01:38:04 +03:00
|
|
|
* freed later on, and (2) point CPUState.neg.plugin_mem_cbs to the
|
2024-03-15 00:27:35 +03:00
|
|
|
* descriptors, so that we can read them at run-time
|
|
|
|
* (i.e. when the helper executes).
|
|
|
|
* This run-time access is performed from qemu_plugin_vcpu_mem_cb.
|
|
|
|
*
|
|
|
|
* Note that plugin_gen_disable_mem_helpers undoes (2). Since it
|
|
|
|
* is possible that the code we generate after the instruction is
|
|
|
|
* dead, we also add checks before generating tb_exit etc.
|
|
|
|
*/
|
|
|
|
if (!insn->calls_helpers) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-15 05:02:19 +03:00
|
|
|
if (!insn->mem_cbs || !insn->mem_cbs->len) {
|
2024-03-15 00:27:35 +03:00
|
|
|
insn->mem_helper = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
insn->mem_helper = true;
|
|
|
|
ptb->mem_helper = true;
|
|
|
|
|
2024-03-15 05:02:19 +03:00
|
|
|
/*
|
|
|
|
* TODO: It seems like we should be able to use ref/unref
|
|
|
|
* to avoid needing to actually copy this array.
|
|
|
|
* Alternately, perhaps we could allocate new memory adjacent
|
|
|
|
* to the TranslationBlock itself, so that we do not have to
|
|
|
|
* actively manage the lifetime after this.
|
|
|
|
*/
|
|
|
|
len = insn->mem_cbs->len;
|
2024-03-15 00:27:35 +03:00
|
|
|
arr = g_array_sized_new(false, false,
|
2024-03-15 05:02:19 +03:00
|
|
|
sizeof(struct qemu_plugin_dyn_cb), len);
|
|
|
|
memcpy(arr->data, insn->mem_cbs->data,
|
|
|
|
len * sizeof(struct qemu_plugin_dyn_cb));
|
2024-03-15 00:27:35 +03:00
|
|
|
qemu_plugin_add_dyn_cb_arr(arr);
|
|
|
|
|
|
|
|
tcg_gen_st_ptr(tcg_constant_ptr((intptr_t)arr), tcg_env,
|
2024-01-10 01:38:04 +03:00
|
|
|
offsetof(CPUState, neg.plugin_mem_cbs) -
|
2024-03-15 00:27:35 +03:00
|
|
|
offsetof(ArchCPU, env));
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
|
|
|
|
2024-03-15 12:47:07 +03:00
|
|
|
static void gen_disable_mem_helper(void)
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
{
|
2024-03-15 12:47:07 +03:00
|
|
|
tcg_gen_st_ptr(tcg_constant_ptr(0), tcg_env,
|
2024-01-10 01:38:04 +03:00
|
|
|
offsetof(CPUState, neg.plugin_mem_cbs) -
|
2024-03-15 12:47:07 +03:00
|
|
|
offsetof(ArchCPU, env));
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
|
|
|
|
2024-05-14 20:42:52 +03:00
|
|
|
static TCGv_i32 gen_cpu_index(void)
|
2024-03-14 23:18:00 +03:00
|
|
|
{
|
|
|
|
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
|
|
|
|
tcg_gen_ld_i32(cpu_index, tcg_env,
|
|
|
|
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
|
2024-05-14 20:42:52 +03:00
|
|
|
return cpu_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gen_udata_cb(struct qemu_plugin_regular_cb *cb)
|
|
|
|
{
|
|
|
|
TCGv_i32 cpu_index = gen_cpu_index();
|
2024-05-14 20:42:51 +03:00
|
|
|
tcg_gen_call2(cb->f.vcpu_udata, cb->info, NULL,
|
2024-03-14 23:18:00 +03:00
|
|
|
tcgv_i32_temp(cpu_index),
|
|
|
|
tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
|
|
|
|
tcg_temp_free_i32(cpu_index);
|
|
|
|
}
|
|
|
|
|
2024-05-14 20:42:46 +03:00
|
|
|
static TCGv_ptr gen_plugin_u64_ptr(qemu_plugin_u64 entry)
|
2024-03-14 23:18:00 +03:00
|
|
|
{
|
|
|
|
TCGv_ptr ptr = tcg_temp_ebb_new_ptr();
|
|
|
|
|
2024-05-14 20:42:46 +03:00
|
|
|
GArray *arr = entry.score->data;
|
|
|
|
char *base_ptr = arr->data + entry.offset;
|
|
|
|
size_t entry_size = g_array_get_element_size(arr);
|
|
|
|
|
2024-05-14 20:42:52 +03:00
|
|
|
TCGv_i32 cpu_index = gen_cpu_index();
|
2024-05-14 20:42:46 +03:00
|
|
|
tcg_gen_muli_i32(cpu_index, cpu_index, entry_size);
|
2024-03-14 23:18:00 +03:00
|
|
|
tcg_gen_ext_i32_ptr(ptr, cpu_index);
|
|
|
|
tcg_temp_free_i32(cpu_index);
|
2024-05-14 20:42:46 +03:00
|
|
|
tcg_gen_addi_ptr(ptr, ptr, (intptr_t) base_ptr);
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2024-05-14 20:42:49 +03:00
|
|
|
static TCGCond plugin_cond_to_tcgcond(enum qemu_plugin_cond cond)
|
|
|
|
{
|
|
|
|
switch (cond) {
|
|
|
|
case QEMU_PLUGIN_COND_EQ:
|
|
|
|
return TCG_COND_EQ;
|
|
|
|
case QEMU_PLUGIN_COND_NE:
|
|
|
|
return TCG_COND_NE;
|
|
|
|
case QEMU_PLUGIN_COND_LT:
|
|
|
|
return TCG_COND_LTU;
|
|
|
|
case QEMU_PLUGIN_COND_LE:
|
|
|
|
return TCG_COND_LEU;
|
|
|
|
case QEMU_PLUGIN_COND_GT:
|
|
|
|
return TCG_COND_GTU;
|
|
|
|
case QEMU_PLUGIN_COND_GE:
|
|
|
|
return TCG_COND_GEU;
|
|
|
|
default:
|
|
|
|
/* ALWAYS and NEVER conditions should never reach */
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-14 20:42:51 +03:00
|
|
|
static void gen_udata_cond_cb(struct qemu_plugin_conditional_cb *cb)
|
2024-05-14 20:42:49 +03:00
|
|
|
{
|
2024-05-14 20:42:51 +03:00
|
|
|
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->entry);
|
2024-05-14 20:42:49 +03:00
|
|
|
TCGv_i64 val = tcg_temp_ebb_new_i64();
|
|
|
|
TCGLabel *after_cb = gen_new_label();
|
|
|
|
|
|
|
|
/* Condition should be negated, as calling the cb is the "else" path */
|
2024-05-14 20:42:51 +03:00
|
|
|
TCGCond cond = tcg_invert_cond(plugin_cond_to_tcgcond(cb->cond));
|
2024-05-14 20:42:49 +03:00
|
|
|
|
|
|
|
tcg_gen_ld_i64(val, ptr, 0);
|
2024-05-14 20:42:51 +03:00
|
|
|
tcg_gen_brcondi_i64(cond, val, cb->imm, after_cb);
|
2024-05-14 20:42:52 +03:00
|
|
|
TCGv_i32 cpu_index = gen_cpu_index();
|
2024-05-14 20:42:51 +03:00
|
|
|
tcg_gen_call2(cb->f.vcpu_udata, cb->info, NULL,
|
2024-05-14 20:42:49 +03:00
|
|
|
tcgv_i32_temp(cpu_index),
|
|
|
|
tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
|
2024-05-14 20:42:52 +03:00
|
|
|
tcg_temp_free_i32(cpu_index);
|
2024-05-14 20:42:49 +03:00
|
|
|
gen_set_label(after_cb);
|
|
|
|
|
|
|
|
tcg_temp_free_i64(val);
|
|
|
|
tcg_temp_free_ptr(ptr);
|
|
|
|
}
|
|
|
|
|
2024-05-14 20:42:51 +03:00
|
|
|
static void gen_inline_add_u64_cb(struct qemu_plugin_inline_cb *cb)
|
2024-05-14 20:42:46 +03:00
|
|
|
{
|
2024-05-14 20:42:51 +03:00
|
|
|
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->entry);
|
2024-05-14 20:42:46 +03:00
|
|
|
TCGv_i64 val = tcg_temp_ebb_new_i64();
|
2024-03-14 23:18:00 +03:00
|
|
|
|
2024-05-14 20:42:46 +03:00
|
|
|
tcg_gen_ld_i64(val, ptr, 0);
|
2024-05-14 20:42:51 +03:00
|
|
|
tcg_gen_addi_i64(val, val, cb->imm);
|
2024-05-14 20:42:46 +03:00
|
|
|
tcg_gen_st_i64(val, ptr, 0);
|
2024-03-14 23:18:00 +03:00
|
|
|
|
|
|
|
tcg_temp_free_i64(val);
|
|
|
|
tcg_temp_free_ptr(ptr);
|
|
|
|
}
|
|
|
|
|
2024-05-14 20:42:51 +03:00
|
|
|
static void gen_inline_store_u64_cb(struct qemu_plugin_inline_cb *cb)
|
2024-05-14 20:42:47 +03:00
|
|
|
{
|
2024-05-14 20:42:51 +03:00
|
|
|
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->entry);
|
|
|
|
TCGv_i64 val = tcg_constant_i64(cb->imm);
|
2024-05-14 20:42:47 +03:00
|
|
|
|
|
|
|
tcg_gen_st_i64(val, ptr, 0);
|
|
|
|
|
|
|
|
tcg_temp_free_ptr(ptr);
|
|
|
|
}
|
|
|
|
|
2024-05-14 20:42:51 +03:00
|
|
|
static void gen_mem_cb(struct qemu_plugin_regular_cb *cb,
|
2024-03-15 02:02:32 +03:00
|
|
|
qemu_plugin_meminfo_t meminfo, TCGv_i64 addr)
|
|
|
|
{
|
2024-05-14 20:42:52 +03:00
|
|
|
TCGv_i32 cpu_index = gen_cpu_index();
|
2024-05-14 20:42:51 +03:00
|
|
|
tcg_gen_call4(cb->f.vcpu_mem, cb->info, NULL,
|
2024-03-15 02:02:32 +03:00
|
|
|
tcgv_i32_temp(cpu_index),
|
|
|
|
tcgv_i32_temp(tcg_constant_i32(meminfo)),
|
|
|
|
tcgv_i64_temp(addr),
|
|
|
|
tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
|
|
|
|
tcg_temp_free_i32(cpu_index);
|
|
|
|
}
|
|
|
|
|
2024-03-16 00:06:57 +03:00
|
|
|
static void inject_cb(struct qemu_plugin_dyn_cb *cb)
|
|
|
|
|
|
|
|
{
|
|
|
|
switch (cb->type) {
|
|
|
|
case PLUGIN_CB_REGULAR:
|
2024-05-14 20:42:51 +03:00
|
|
|
gen_udata_cb(&cb->regular);
|
2024-03-16 00:06:57 +03:00
|
|
|
break;
|
2024-05-14 20:42:49 +03:00
|
|
|
case PLUGIN_CB_COND:
|
2024-05-14 20:42:51 +03:00
|
|
|
gen_udata_cond_cb(&cb->cond);
|
2024-05-14 20:42:49 +03:00
|
|
|
break;
|
2024-05-14 20:42:45 +03:00
|
|
|
case PLUGIN_CB_INLINE_ADD_U64:
|
2024-05-14 20:42:51 +03:00
|
|
|
gen_inline_add_u64_cb(&cb->inline_insn);
|
2024-03-16 00:06:57 +03:00
|
|
|
break;
|
2024-05-14 20:42:47 +03:00
|
|
|
case PLUGIN_CB_INLINE_STORE_U64:
|
2024-05-14 20:42:51 +03:00
|
|
|
gen_inline_store_u64_cb(&cb->inline_insn);
|
2024-05-14 20:42:47 +03:00
|
|
|
break;
|
2024-03-16 00:06:57 +03:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void inject_mem_cb(struct qemu_plugin_dyn_cb *cb,
|
|
|
|
enum qemu_plugin_mem_rw rw,
|
|
|
|
qemu_plugin_meminfo_t meminfo, TCGv_i64 addr)
|
|
|
|
{
|
2024-05-14 20:42:51 +03:00
|
|
|
switch (cb->type) {
|
|
|
|
case PLUGIN_CB_MEM_REGULAR:
|
|
|
|
if (rw && cb->regular.rw) {
|
|
|
|
gen_mem_cb(&cb->regular, meminfo, addr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PLUGIN_CB_INLINE_ADD_U64:
|
|
|
|
case PLUGIN_CB_INLINE_STORE_U64:
|
|
|
|
if (rw && cb->inline_insn.rw) {
|
2024-03-16 00:06:57 +03:00
|
|
|
inject_cb(cb);
|
|
|
|
}
|
2024-05-14 20:42:51 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
break;
|
2024-03-16 00:06:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-24 21:01:23 +03:00
|
|
|
static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
{
|
2024-03-14 20:09:57 +03:00
|
|
|
TCGOp *op, *next;
|
2021-09-17 19:23:32 +03:00
|
|
|
int insn_idx = -1;
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
|
2024-03-15 23:33:49 +03:00
|
|
|
if (unlikely(qemu_loglevel_mask(LOG_TB_OP_PLUGIN)
|
2024-04-03 22:59:18 +03:00
|
|
|
&& qemu_log_in_addr_range(tcg_ctx->plugin_db->pc_first))) {
|
2024-03-15 23:33:49 +03:00
|
|
|
FILE *logfile = qemu_log_trylock();
|
|
|
|
if (logfile) {
|
|
|
|
fprintf(logfile, "OP before plugin injection:\n");
|
|
|
|
tcg_dump_ops(tcg_ctx, logfile, false);
|
|
|
|
fprintf(logfile, "\n");
|
|
|
|
qemu_log_unlock(logfile);
|
|
|
|
}
|
|
|
|
}
|
2021-09-17 19:23:32 +03:00
|
|
|
|
2024-03-14 20:09:57 +03:00
|
|
|
/*
|
|
|
|
* While injecting code, we cannot afford to reuse any ebb temps
|
|
|
|
* that might be live within the existing opcode stream.
|
|
|
|
* The simplest solution is to release them all and create new.
|
|
|
|
*/
|
|
|
|
memset(tcg_ctx->free_temps, 0, sizeof(tcg_ctx->free_temps));
|
|
|
|
|
|
|
|
QTAILQ_FOREACH_SAFE(op, &tcg_ctx->ops, link, next) {
|
2021-09-17 19:23:32 +03:00
|
|
|
switch (op->opc) {
|
|
|
|
case INDEX_op_insn_start:
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
insn_idx++;
|
2021-09-17 19:23:32 +03:00
|
|
|
break;
|
2024-03-14 20:09:57 +03:00
|
|
|
|
|
|
|
case INDEX_op_plugin_cb:
|
|
|
|
{
|
|
|
|
enum plugin_gen_from from = op->args[0];
|
|
|
|
struct qemu_plugin_insn *insn = NULL;
|
2024-03-14 23:18:00 +03:00
|
|
|
const GArray *cbs;
|
|
|
|
int i, n;
|
2024-03-14 20:09:57 +03:00
|
|
|
|
|
|
|
if (insn_idx >= 0) {
|
|
|
|
insn = g_ptr_array_index(plugin_tb->insns, insn_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
tcg_ctx->emit_before_op = op;
|
|
|
|
|
|
|
|
switch (from) {
|
2024-03-15 12:47:07 +03:00
|
|
|
case PLUGIN_GEN_AFTER_TB:
|
|
|
|
if (plugin_tb->mem_helper) {
|
|
|
|
gen_disable_mem_helper();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-03-14 20:09:57 +03:00
|
|
|
case PLUGIN_GEN_AFTER_INSN:
|
|
|
|
assert(insn != NULL);
|
2024-03-15 12:47:07 +03:00
|
|
|
if (insn->mem_helper) {
|
|
|
|
gen_disable_mem_helper();
|
|
|
|
}
|
2024-03-14 20:09:57 +03:00
|
|
|
break;
|
2024-03-14 23:18:00 +03:00
|
|
|
|
|
|
|
case PLUGIN_GEN_FROM_TB:
|
|
|
|
assert(insn == NULL);
|
|
|
|
|
2024-03-15 05:02:19 +03:00
|
|
|
cbs = plugin_tb->cbs;
|
2024-03-14 23:18:00 +03:00
|
|
|
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
|
2024-03-16 00:06:57 +03:00
|
|
|
inject_cb(
|
|
|
|
&g_array_index(cbs, struct qemu_plugin_dyn_cb, i));
|
2024-03-14 23:18:00 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-03-15 00:27:35 +03:00
|
|
|
case PLUGIN_GEN_FROM_INSN:
|
|
|
|
assert(insn != NULL);
|
|
|
|
|
|
|
|
gen_enable_mem_helper(plugin_tb, insn);
|
|
|
|
|
2024-03-15 05:02:19 +03:00
|
|
|
cbs = insn->insn_cbs;
|
2024-03-15 00:27:35 +03:00
|
|
|
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
|
2024-03-16 00:06:57 +03:00
|
|
|
inject_cb(
|
|
|
|
&g_array_index(cbs, struct qemu_plugin_dyn_cb, i));
|
2024-03-15 00:27:35 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-03-14 20:09:57 +03:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
tcg_ctx->emit_before_op = NULL;
|
|
|
|
tcg_op_remove(tcg_ctx, op);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-03-15 02:02:32 +03:00
|
|
|
case INDEX_op_plugin_mem_cb:
|
2021-09-17 19:23:32 +03:00
|
|
|
{
|
2024-03-15 02:02:32 +03:00
|
|
|
TCGv_i64 addr = temp_tcgv_i64(arg_temp(op->args[0]));
|
|
|
|
qemu_plugin_meminfo_t meminfo = op->args[1];
|
2024-03-16 00:06:57 +03:00
|
|
|
enum qemu_plugin_mem_rw rw =
|
|
|
|
(qemu_plugin_mem_is_store(meminfo)
|
|
|
|
? QEMU_PLUGIN_MEM_W : QEMU_PLUGIN_MEM_R);
|
2024-03-15 02:02:32 +03:00
|
|
|
struct qemu_plugin_insn *insn;
|
|
|
|
const GArray *cbs;
|
2024-03-16 00:06:57 +03:00
|
|
|
int i, n;
|
2021-09-17 19:23:32 +03:00
|
|
|
|
2024-03-15 02:02:32 +03:00
|
|
|
assert(insn_idx >= 0);
|
|
|
|
insn = g_ptr_array_index(plugin_tb->insns, insn_idx);
|
2021-09-17 19:23:32 +03:00
|
|
|
|
2024-03-15 02:02:32 +03:00
|
|
|
tcg_ctx->emit_before_op = op;
|
|
|
|
|
2024-03-15 05:02:19 +03:00
|
|
|
cbs = insn->mem_cbs;
|
2024-03-15 02:02:32 +03:00
|
|
|
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
|
2024-03-16 00:06:57 +03:00
|
|
|
inject_mem_cb(&g_array_index(cbs, struct qemu_plugin_dyn_cb, i),
|
|
|
|
rw, meminfo, addr);
|
2021-09-17 19:23:32 +03:00
|
|
|
}
|
2024-03-15 02:02:32 +03:00
|
|
|
|
|
|
|
tcg_ctx->emit_before_op = NULL;
|
|
|
|
tcg_op_remove(tcg_ctx, op);
|
2021-09-17 19:23:32 +03:00
|
|
|
break;
|
|
|
|
}
|
2024-03-15 02:02:32 +03:00
|
|
|
|
2021-09-17 19:23:32 +03:00
|
|
|
default:
|
|
|
|
/* plugins don't care about any other ops */
|
|
|
|
break;
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-03 22:31:49 +03:00
|
|
|
bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db)
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
{
|
2024-04-05 02:35:43 +03:00
|
|
|
struct qemu_plugin_tb *ptb;
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
|
2024-04-05 02:35:43 +03:00
|
|
|
if (!test_bit(QEMU_PLUGIN_EV_VCPU_TB_TRANS,
|
|
|
|
cpu->plugin_state->event_mask)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
tcg_ctx->plugin_db = db;
|
|
|
|
tcg_ctx->plugin_insn = NULL;
|
|
|
|
ptb = tcg_ctx->plugin_tb;
|
2022-02-04 23:43:35 +03:00
|
|
|
|
2024-04-05 02:35:43 +03:00
|
|
|
if (ptb) {
|
|
|
|
/* Reset callbacks */
|
2024-03-15 05:02:19 +03:00
|
|
|
if (ptb->cbs) {
|
|
|
|
g_array_set_size(ptb->cbs, 0);
|
2022-02-04 23:43:35 +03:00
|
|
|
}
|
|
|
|
ptb->n = 0;
|
2023-01-24 21:01:23 +03:00
|
|
|
ptb->mem_helper = false;
|
2024-04-05 02:35:43 +03:00
|
|
|
} else {
|
|
|
|
ptb = g_new0(struct qemu_plugin_tb, 1);
|
|
|
|
tcg_ctx->plugin_tb = ptb;
|
|
|
|
ptb->insns = g_ptr_array_new();
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
2022-02-04 23:43:35 +03:00
|
|
|
|
2024-04-05 02:35:43 +03:00
|
|
|
tcg_gen_plugin_cb(PLUGIN_GEN_FROM_TB);
|
|
|
|
return true;
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
|
|
|
|
{
|
|
|
|
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
2024-03-15 08:27:28 +03:00
|
|
|
struct qemu_plugin_insn *insn;
|
|
|
|
size_t n = db->num_insns;
|
|
|
|
vaddr pc;
|
|
|
|
|
|
|
|
assert(n >= 1);
|
|
|
|
ptb->n = n;
|
|
|
|
if (n <= ptb->insns->len) {
|
|
|
|
insn = g_ptr_array_index(ptb->insns, n - 1);
|
|
|
|
} else {
|
|
|
|
assert(n - 1 == ptb->insns->len);
|
|
|
|
insn = g_new0(struct qemu_plugin_insn, 1);
|
|
|
|
g_ptr_array_add(ptb->insns, insn);
|
|
|
|
}
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
|
2024-03-15 08:27:28 +03:00
|
|
|
tcg_ctx->plugin_insn = insn;
|
|
|
|
insn->calls_helpers = false;
|
|
|
|
insn->mem_helper = false;
|
|
|
|
if (insn->insn_cbs) {
|
|
|
|
g_array_set_size(insn->insn_cbs, 0);
|
|
|
|
}
|
|
|
|
if (insn->mem_cbs) {
|
|
|
|
g_array_set_size(insn->mem_cbs, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pc = db->pc_next;
|
|
|
|
insn->vaddr = pc;
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
|
2024-03-15 08:41:40 +03:00
|
|
|
tcg_gen_plugin_cb(PLUGIN_GEN_FROM_INSN);
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void plugin_gen_insn_end(void)
|
|
|
|
{
|
2024-04-03 22:20:06 +03:00
|
|
|
const DisasContextBase *db = tcg_ctx->plugin_db;
|
|
|
|
struct qemu_plugin_insn *pinsn = tcg_ctx->plugin_insn;
|
|
|
|
|
|
|
|
pinsn->len = db->fake_insn ? db->record_len : db->pc_next - pinsn->vaddr;
|
|
|
|
|
2024-03-15 08:41:40 +03:00
|
|
|
tcg_gen_plugin_cb(PLUGIN_GEN_AFTER_INSN);
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
}
|
|
|
|
|
2022-02-04 23:43:35 +03:00
|
|
|
/*
|
|
|
|
* There are cases where we never get to finalise a translation - for
|
|
|
|
* example a page fault during translation. As a result we shouldn't
|
|
|
|
* do any clean-up here and make sure things are reset in
|
|
|
|
* plugin_gen_tb_start.
|
|
|
|
*/
|
2023-10-09 19:41:01 +03:00
|
|
|
void plugin_gen_tb_end(CPUState *cpu, size_t num_insns)
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
{
|
|
|
|
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
|
|
|
|
2023-10-09 19:41:01 +03:00
|
|
|
/* translator may have removed instructions, update final count */
|
|
|
|
g_assert(num_insns <= ptb->n);
|
|
|
|
ptb->n = num_insns;
|
|
|
|
|
plugin-gen: add module for TCG-related code
We first inject empty instrumentation from translator_loop.
After translation, we go through the plugins to see what
they want to register for, filling in the empty instrumentation.
If if turns out that some instrumentation remains unused, we
remove it.
This approach supports the following features:
- Inlining TCG code for simple operations. Note that we do not
export TCG ops to plugins. Instead, we give them a C API to
insert inlined ops. So far we only support adding an immediate
to a u64, e.g. to count events.
- "Direct" callbacks. These are callbacks that do not go via
a helper. Instead, the helper is defined at run-time, so that
the plugin code is directly called from TCG. This makes direct
callbacks as efficient as possible; they are therefore used
for very frequent events, e.g. memory callbacks.
- Passing the host address to memory callbacks. Most of this
is implemented in a later patch though.
- Instrumentation of memory accesses performed from helpers.
See the corresponding comment, as well as a later patch.
Signed-off-by: Emilio G. Cota <cota@braap.org>
[AJB: add alloc_tcg_plugin_context, use glib, rm hwaddr]
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2018-12-07 23:33:56 +03:00
|
|
|
/* collect instrumentation requests */
|
|
|
|
qemu_plugin_tb_trans_cb(cpu, ptb);
|
|
|
|
|
|
|
|
/* inject the instrumentation at the appropriate places */
|
|
|
|
plugin_gen_inject(ptb);
|
|
|
|
}
|