mirror of https://github.com/xemu-project/xemu.git
plugins: Rewrite plugin tcg expansion
-----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmYyUpkdHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV98VAgAoTqIWPHtPJOS800G TlFuQjkEzQCPSKAh6ZbotsAMvfNwBloPpdrUlFr/jT7mURjEl2B7UC/4LzdhuGeQ U/xZt5rXsYvyfS3VwLf8pKBIscF7XjJ1rdfYMvBg9XaNp5VV0aEIk3+6P0uYtzXG cREF0uCYfdK6uoiuifhqRAkgrNnamdwpPbbfvzDQI13wICW7SfR7dcd629clVZ1O QvD1M4bpTWyhClbZzaoHqyPs+HQEM/AY0wOTfYZNbQBu6zFZXNDZCvYhIEWonPBO AKe5KWUrQMwLJhRVejaSSZZDjMdcz3HLaGJppP89/WB+gpY09+LsiuqT7k5c12Bw ueLEhw== =mn63 -----END PGP SIGNATURE----- Merge tag 'pull-tcg-20240501' of https://gitlab.com/rth7680/qemu into staging plugins: Rewrite plugin tcg expansion # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmYyUpkdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV98VAgAoTqIWPHtPJOS800G # TlFuQjkEzQCPSKAh6ZbotsAMvfNwBloPpdrUlFr/jT7mURjEl2B7UC/4LzdhuGeQ # U/xZt5rXsYvyfS3VwLf8pKBIscF7XjJ1rdfYMvBg9XaNp5VV0aEIk3+6P0uYtzXG # cREF0uCYfdK6uoiuifhqRAkgrNnamdwpPbbfvzDQI13wICW7SfR7dcd629clVZ1O # QvD1M4bpTWyhClbZzaoHqyPs+HQEM/AY0wOTfYZNbQBu6zFZXNDZCvYhIEWonPBO # AKe5KWUrQMwLJhRVejaSSZZDjMdcz3HLaGJppP89/WB+gpY09+LsiuqT7k5c12Bw # ueLEhw== # =mn63 # -----END PGP SIGNATURE----- # gpg: Signature made Wed 01 May 2024 07:32:57 AM PDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * tag 'pull-tcg-20240501' of https://gitlab.com/rth7680/qemu: plugins: Update the documentation block for plugin-gen.c plugins: Inline plugin_gen_empty_callback plugins: Merge qemu_plugin_tb_insn_get to plugin-gen.c plugins: Split out common cb expanders plugins: Replace pr_ops with a proper debug dump flag plugins: Introduce PLUGIN_CB_MEM_REGULAR plugins: Simplify callback queues tcg: Remove INDEX_op_plugin_cb_{start,end} tcg: Remove TCG_CALL_PLUGIN plugins: Remove plugin helpers plugins: Use emit_before_op for PLUGIN_GEN_FROM_MEM plugins: Use emit_before_op for PLUGIN_GEN_FROM_INSN plugins: Add PLUGIN_GEN_AFTER_TB plugins: Use emit_before_op for PLUGIN_GEN_FROM_TB plugins: Use emit_before_op for PLUGIN_GEN_AFTER_INSN plugins: Create TCGHelperInfo for all out-of-line callbacks plugins: Move function pointer in qemu_plugin_dyn_cb plugins: Zero new qemu_plugin_dyn_cb entries tcg: Pass function pointer to tcg_gen_call* tcg: Make tcg/helper-info.h self-contained Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
4977ce198d
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +0,0 @@
|
|||
#ifdef CONFIG_PLUGIN
|
||||
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_wg, TCG_CALL_NO_WG | TCG_CALL_PLUGIN, void, i32, ptr)
|
||||
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_rwg, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, ptr)
|
||||
DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, i32, i64, ptr)
|
||||
#endif
|
|
@ -11,8 +11,4 @@
|
|||
#include "exec/helper-gen.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#define HELPER_H "accel/tcg/plugin-helpers.h"
|
||||
#include "exec/helper-gen.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#endif /* HELPER_GEN_COMMON_H */
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
|
||||
{ \
|
||||
tcg_gen_call0(&glue(helper_info_, name), dh_retvar(ret)); \
|
||||
tcg_gen_call0(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
|
||||
|
@ -22,7 +23,8 @@ extern TCGHelperInfo glue(helper_info_, name); \
|
|||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1)) \
|
||||
{ \
|
||||
tcg_gen_call1(&glue(helper_info_, name), dh_retvar(ret), \
|
||||
tcg_gen_call1(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1)); \
|
||||
}
|
||||
|
||||
|
@ -31,7 +33,8 @@ extern TCGHelperInfo glue(helper_info_, name); \
|
|||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
|
||||
{ \
|
||||
tcg_gen_call2(&glue(helper_info_, name), dh_retvar(ret), \
|
||||
tcg_gen_call2(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2)); \
|
||||
}
|
||||
|
||||
|
@ -40,7 +43,8 @@ extern TCGHelperInfo glue(helper_info_, name); \
|
|||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
|
||||
{ \
|
||||
tcg_gen_call3(&glue(helper_info_, name), dh_retvar(ret), \
|
||||
tcg_gen_call3(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3)); \
|
||||
}
|
||||
|
||||
|
@ -50,7 +54,8 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
|||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
|
||||
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
|
||||
{ \
|
||||
tcg_gen_call4(&glue(helper_info_, name), dh_retvar(ret), \
|
||||
tcg_gen_call4(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), \
|
||||
dh_arg(t3, 3), dh_arg(t4, 4)); \
|
||||
}
|
||||
|
@ -61,7 +66,8 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
|||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
|
||||
{ \
|
||||
tcg_gen_call5(&glue(helper_info_, name), dh_retvar(ret), \
|
||||
tcg_gen_call5(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||
dh_arg(t4, 4), dh_arg(t5, 5)); \
|
||||
}
|
||||
|
@ -72,7 +78,8 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
|||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
|
||||
{ \
|
||||
tcg_gen_call6(&glue(helper_info_, name), dh_retvar(ret), \
|
||||
tcg_gen_call6(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6)); \
|
||||
}
|
||||
|
@ -84,7 +91,8 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
|||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
|
||||
dh_arg_decl(t7, 7)) \
|
||||
{ \
|
||||
tcg_gen_call7(&glue(helper_info_, name), dh_retvar(ret), \
|
||||
tcg_gen_call7(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
|
||||
dh_arg(t7, 7)); \
|
||||
|
|
|
@ -13,8 +13,4 @@
|
|||
#include "exec/helper-proto.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#define HELPER_H "accel/tcg/plugin-helpers.h"
|
||||
#include "exec/helper-proto.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#endif /* HELPER_PROTO_COMMON_H */
|
||||
|
|
|
@ -25,7 +25,6 @@ void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db);
|
|||
void plugin_gen_insn_end(void);
|
||||
|
||||
void plugin_gen_disable_mem_helpers(void);
|
||||
void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info);
|
||||
|
||||
#else /* !CONFIG_PLUGIN */
|
||||
|
||||
|
@ -48,9 +47,6 @@ static inline void plugin_gen_tb_end(CPUState *cpu, size_t num_insns)
|
|||
static inline void plugin_gen_disable_mem_helpers(void)
|
||||
{ }
|
||||
|
||||
static inline void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info)
|
||||
{ }
|
||||
|
||||
#endif /* CONFIG_PLUGIN */
|
||||
|
||||
#endif /* QEMU_PLUGIN_GEN_H */
|
||||
|
|
|
@ -36,6 +36,7 @@ bool qemu_log_separate(void);
|
|||
#define LOG_STRACE (1 << 19)
|
||||
#define LOG_PER_THREAD (1 << 20)
|
||||
#define CPU_LOG_TB_VPU (1 << 21)
|
||||
#define LOG_TB_OP_PLUGIN (1 << 22)
|
||||
|
||||
/* Lock/unlock output. */
|
||||
|
||||
|
|
|
@ -67,16 +67,9 @@ union qemu_plugin_cb_sig {
|
|||
};
|
||||
|
||||
enum plugin_dyn_cb_type {
|
||||
PLUGIN_CB_INSN,
|
||||
PLUGIN_CB_MEM,
|
||||
PLUGIN_N_CB_TYPES,
|
||||
};
|
||||
|
||||
enum plugin_dyn_cb_subtype {
|
||||
PLUGIN_CB_REGULAR,
|
||||
PLUGIN_CB_REGULAR_R,
|
||||
PLUGIN_CB_MEM_REGULAR,
|
||||
PLUGIN_CB_INLINE,
|
||||
PLUGIN_N_CB_SUBTYPES,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -85,13 +78,16 @@ enum plugin_dyn_cb_subtype {
|
|||
* instance of a callback to be called upon the execution of a particular TB.
|
||||
*/
|
||||
struct qemu_plugin_dyn_cb {
|
||||
union qemu_plugin_cb_sig f;
|
||||
void *userp;
|
||||
enum plugin_dyn_cb_subtype type;
|
||||
enum plugin_dyn_cb_type type;
|
||||
/* @rw applies to mem callbacks only (both regular and inline) */
|
||||
enum qemu_plugin_mem_rw rw;
|
||||
/* fields specific to each dyn_cb type go here */
|
||||
union {
|
||||
struct {
|
||||
union qemu_plugin_cb_sig f;
|
||||
TCGHelperInfo *info;
|
||||
} regular;
|
||||
struct {
|
||||
qemu_plugin_u64 entry;
|
||||
enum qemu_plugin_op op;
|
||||
|
@ -105,7 +101,8 @@ struct qemu_plugin_insn {
|
|||
GByteArray *data;
|
||||
uint64_t vaddr;
|
||||
void *haddr;
|
||||
GArray *cbs[PLUGIN_N_CB_TYPES][PLUGIN_N_CB_SUBTYPES];
|
||||
GArray *insn_cbs;
|
||||
GArray *mem_cbs;
|
||||
bool calls_helpers;
|
||||
|
||||
/* if set, the instruction calls helpers that might access guest memory */
|
||||
|
@ -132,21 +129,6 @@ static inline void qemu_plugin_insn_cleanup_fn(gpointer data)
|
|||
g_byte_array_free(insn->data, true);
|
||||
}
|
||||
|
||||
static inline struct qemu_plugin_insn *qemu_plugin_insn_alloc(void)
|
||||
{
|
||||
int i, j;
|
||||
struct qemu_plugin_insn *insn = g_new0(struct qemu_plugin_insn, 1);
|
||||
insn->data = g_byte_array_sized_new(4);
|
||||
|
||||
for (i = 0; i < PLUGIN_N_CB_TYPES; i++) {
|
||||
for (j = 0; j < PLUGIN_N_CB_SUBTYPES; j++) {
|
||||
insn->cbs[i][j] = g_array_new(false, false,
|
||||
sizeof(struct qemu_plugin_dyn_cb));
|
||||
}
|
||||
}
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Internal context for this TranslationBlock */
|
||||
struct qemu_plugin_tb {
|
||||
GPtrArray *insns;
|
||||
|
@ -160,40 +142,9 @@ struct qemu_plugin_tb {
|
|||
/* if set, the TB calls helpers that might access guest memory */
|
||||
bool mem_helper;
|
||||
|
||||
GArray *cbs[PLUGIN_N_CB_SUBTYPES];
|
||||
GArray *cbs;
|
||||
};
|
||||
|
||||
/**
|
||||
* qemu_plugin_tb_insn_get(): get next plugin record for translation.
|
||||
* @tb: the internal tb context
|
||||
* @pc: address of instruction
|
||||
*/
|
||||
static inline
|
||||
struct qemu_plugin_insn *qemu_plugin_tb_insn_get(struct qemu_plugin_tb *tb,
|
||||
uint64_t pc)
|
||||
{
|
||||
struct qemu_plugin_insn *insn;
|
||||
int i, j;
|
||||
|
||||
if (unlikely(tb->n == tb->insns->len)) {
|
||||
struct qemu_plugin_insn *new_insn = qemu_plugin_insn_alloc();
|
||||
g_ptr_array_add(tb->insns, new_insn);
|
||||
}
|
||||
insn = g_ptr_array_index(tb->insns, tb->n++);
|
||||
g_byte_array_set_size(insn->data, 0);
|
||||
insn->calls_helpers = false;
|
||||
insn->mem_helper = false;
|
||||
insn->vaddr = pc;
|
||||
|
||||
for (i = 0; i < PLUGIN_N_CB_TYPES; i++) {
|
||||
for (j = 0; j < PLUGIN_N_CB_SUBTYPES; j++) {
|
||||
g_array_set_size(insn->cbs[i][j], 0);
|
||||
}
|
||||
}
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct CPUPluginState - per-CPU state for plugins
|
||||
* @event_mask: plugin event bitmap. Modified only via async work.
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#ifdef CONFIG_TCG_INTERPRETER
|
||||
#include <ffi.h>
|
||||
#endif
|
||||
#include "tcg-target-reg-bits.h"
|
||||
|
||||
#define MAX_CALL_IARGS 7
|
||||
|
||||
/*
|
||||
* Describe the calling convention of a given argument type.
|
||||
|
|
|
@ -74,8 +74,8 @@ void tcg_gen_goto_tb(unsigned idx);
|
|||
*/
|
||||
void tcg_gen_lookup_and_goto_ptr(void);
|
||||
|
||||
void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr);
|
||||
void tcg_gen_plugin_cb_end(void);
|
||||
void tcg_gen_plugin_cb(unsigned from);
|
||||
void tcg_gen_plugin_mem_cb(TCGv_i64 addr, unsigned meminfo);
|
||||
|
||||
/* 32 bit ops */
|
||||
|
||||
|
|
|
@ -197,8 +197,8 @@ DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
|
|||
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
|
||||
DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
|
||||
|
||||
DEF(plugin_cb_start, 0, 0, 3, TCG_OPF_NOT_PRESENT)
|
||||
DEF(plugin_cb_end, 0, 0, 0, TCG_OPF_NOT_PRESENT)
|
||||
DEF(plugin_cb, 0, 0, 1, TCG_OPF_NOT_PRESENT)
|
||||
DEF(plugin_mem_cb, 0, 1, 1, TCG_OPF_NOT_PRESENT)
|
||||
|
||||
/* Replicate ld/st ops for 32 and 64-bit guest addresses. */
|
||||
DEF(qemu_ld_a32_i32, 1, 1, 1,
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
/* XXX: make safe guess about sizes */
|
||||
#define MAX_OP_PER_INSTR 266
|
||||
|
||||
#define MAX_CALL_IARGS 7
|
||||
|
||||
#define CPU_TEMP_BUF_NLONGS 128
|
||||
#define TCG_STATIC_FRAME_SIZE (CPU_TEMP_BUF_NLONGS * sizeof(long))
|
||||
|
||||
|
@ -355,8 +353,6 @@ typedef TCGv_ptr TCGv_env;
|
|||
#define TCG_CALL_NO_SIDE_EFFECTS 0x0004
|
||||
/* Helper is G_NORETURN. */
|
||||
#define TCG_CALL_NO_RETURN 0x0008
|
||||
/* Helper is part of Plugins. */
|
||||
#define TCG_CALL_PLUGIN 0x0010
|
||||
|
||||
/* convenience version of most used call flags */
|
||||
#define TCG_CALL_NO_RWG TCG_CALL_NO_READ_GLOBALS
|
||||
|
@ -854,19 +850,22 @@ typedef struct TCGTargetOpDef {
|
|||
|
||||
bool tcg_op_supported(TCGOpcode op);
|
||||
|
||||
void tcg_gen_call0(TCGHelperInfo *, TCGTemp *ret);
|
||||
void tcg_gen_call1(TCGHelperInfo *, TCGTemp *ret, TCGTemp *);
|
||||
void tcg_gen_call2(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *);
|
||||
void tcg_gen_call3(TCGHelperInfo *, TCGTemp *ret, TCGTemp *,
|
||||
void tcg_gen_call0(void *func, TCGHelperInfo *, TCGTemp *ret);
|
||||
void tcg_gen_call1(void *func, TCGHelperInfo *, TCGTemp *ret, TCGTemp *);
|
||||
void tcg_gen_call2(void *func, TCGHelperInfo *, TCGTemp *ret,
|
||||
TCGTemp *, TCGTemp *);
|
||||
void tcg_gen_call4(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
|
||||
TCGTemp *, TCGTemp *);
|
||||
void tcg_gen_call5(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
|
||||
void tcg_gen_call3(void *func, TCGHelperInfo *, TCGTemp *ret,
|
||||
TCGTemp *, TCGTemp *, TCGTemp *);
|
||||
void tcg_gen_call6(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
|
||||
void tcg_gen_call4(void *func, TCGHelperInfo *, TCGTemp *ret,
|
||||
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *);
|
||||
void tcg_gen_call7(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
|
||||
void tcg_gen_call5(void *func, TCGHelperInfo *, TCGTemp *ret,
|
||||
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *);
|
||||
void tcg_gen_call6(void *func, TCGHelperInfo *, TCGTemp *ret,
|
||||
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *,
|
||||
TCGTemp *, TCGTemp *);
|
||||
void tcg_gen_call7(void *func, TCGHelperInfo *, TCGTemp *ret,
|
||||
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *,
|
||||
TCGTemp *, TCGTemp *, TCGTemp *);
|
||||
|
||||
TCGOp *tcg_emit_op(TCGOpcode opc, unsigned nargs);
|
||||
void tcg_op_remove(TCGContext *s, TCGOp *op);
|
||||
|
@ -1071,5 +1070,6 @@ static inline const TCGOpcode *tcg_swap_vecop_list(const TCGOpcode *n)
|
|||
}
|
||||
|
||||
bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned);
|
||||
void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs);
|
||||
|
||||
#endif /* TCG_H */
|
||||
|
|
|
@ -92,12 +92,7 @@ void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,
|
|||
void *udata)
|
||||
{
|
||||
if (!tb->mem_only) {
|
||||
int index = flags == QEMU_PLUGIN_CB_R_REGS ||
|
||||
flags == QEMU_PLUGIN_CB_RW_REGS ?
|
||||
PLUGIN_CB_REGULAR_R : PLUGIN_CB_REGULAR;
|
||||
|
||||
plugin_register_dyn_cb__udata(&tb->cbs[index],
|
||||
cb, flags, udata);
|
||||
plugin_register_dyn_cb__udata(&tb->cbs, cb, flags, udata);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,8 +103,7 @@ void qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu(
|
|||
uint64_t imm)
|
||||
{
|
||||
if (!tb->mem_only) {
|
||||
plugin_register_inline_op_on_entry(
|
||||
&tb->cbs[PLUGIN_CB_INLINE], 0, op, entry, imm);
|
||||
plugin_register_inline_op_on_entry(&tb->cbs, 0, op, entry, imm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,12 +113,7 @@ void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,
|
|||
void *udata)
|
||||
{
|
||||
if (!insn->mem_only) {
|
||||
int index = flags == QEMU_PLUGIN_CB_R_REGS ||
|
||||
flags == QEMU_PLUGIN_CB_RW_REGS ?
|
||||
PLUGIN_CB_REGULAR_R : PLUGIN_CB_REGULAR;
|
||||
|
||||
plugin_register_dyn_cb__udata(&insn->cbs[PLUGIN_CB_INSN][index],
|
||||
cb, flags, udata);
|
||||
plugin_register_dyn_cb__udata(&insn->insn_cbs, cb, flags, udata);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,8 +124,7 @@ void qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
|
|||
uint64_t imm)
|
||||
{
|
||||
if (!insn->mem_only) {
|
||||
plugin_register_inline_op_on_entry(
|
||||
&insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE], 0, op, entry, imm);
|
||||
plugin_register_inline_op_on_entry(&insn->insn_cbs, 0, op, entry, imm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,8 +139,7 @@ void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn,
|
|||
enum qemu_plugin_mem_rw rw,
|
||||
void *udata)
|
||||
{
|
||||
plugin_register_vcpu_mem_cb(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR],
|
||||
cb, flags, rw, udata);
|
||||
plugin_register_vcpu_mem_cb(&insn->mem_cbs, cb, flags, rw, udata);
|
||||
}
|
||||
|
||||
void qemu_plugin_register_vcpu_mem_inline_per_vcpu(
|
||||
|
@ -162,8 +149,7 @@ void qemu_plugin_register_vcpu_mem_inline_per_vcpu(
|
|||
qemu_plugin_u64 entry,
|
||||
uint64_t imm)
|
||||
{
|
||||
plugin_register_inline_op_on_entry(
|
||||
&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE], rw, op, entry, imm);
|
||||
plugin_register_inline_op_on_entry(&insn->mem_cbs, rw, op, entry, imm);
|
||||
}
|
||||
|
||||
void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id,
|
||||
|
|
|
@ -307,7 +307,7 @@ static struct qemu_plugin_dyn_cb *plugin_get_dyn_cb(GArray **arr)
|
|||
GArray *cbs = *arr;
|
||||
|
||||
if (!cbs) {
|
||||
cbs = g_array_sized_new(false, false,
|
||||
cbs = g_array_sized_new(false, true,
|
||||
sizeof(struct qemu_plugin_dyn_cb), 1);
|
||||
*arr = cbs;
|
||||
}
|
||||
|
@ -338,12 +338,25 @@ void plugin_register_dyn_cb__udata(GArray **arr,
|
|||
enum qemu_plugin_cb_flags flags,
|
||||
void *udata)
|
||||
{
|
||||
struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
|
||||
static TCGHelperInfo info[3] = {
|
||||
[QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG,
|
||||
[QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG,
|
||||
/*
|
||||
* Match qemu_plugin_vcpu_udata_cb_t:
|
||||
* void (*)(uint32_t, void *)
|
||||
*/
|
||||
[0 ... 2].typemask = (dh_typemask(void, 0) |
|
||||
dh_typemask(i32, 1) |
|
||||
dh_typemask(ptr, 2))
|
||||
};
|
||||
|
||||
struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
|
||||
dyn_cb->userp = udata;
|
||||
/* Note flags are discarded as unused. */
|
||||
dyn_cb->f.vcpu_udata = cb;
|
||||
dyn_cb->type = PLUGIN_CB_REGULAR;
|
||||
dyn_cb->regular.f.vcpu_udata = cb;
|
||||
|
||||
assert((unsigned)flags < ARRAY_SIZE(info));
|
||||
dyn_cb->regular.info = &info[flags];
|
||||
}
|
||||
|
||||
void plugin_register_vcpu_mem_cb(GArray **arr,
|
||||
|
@ -352,14 +365,38 @@ void plugin_register_vcpu_mem_cb(GArray **arr,
|
|||
enum qemu_plugin_mem_rw rw,
|
||||
void *udata)
|
||||
{
|
||||
struct qemu_plugin_dyn_cb *dyn_cb;
|
||||
/*
|
||||
* Expect that the underlying type for enum qemu_plugin_meminfo_t
|
||||
* is either int32_t or uint32_t, aka int or unsigned int.
|
||||
*/
|
||||
QEMU_BUILD_BUG_ON(
|
||||
!__builtin_types_compatible_p(qemu_plugin_meminfo_t, uint32_t) &&
|
||||
!__builtin_types_compatible_p(qemu_plugin_meminfo_t, int32_t));
|
||||
|
||||
dyn_cb = plugin_get_dyn_cb(arr);
|
||||
static TCGHelperInfo info[3] = {
|
||||
[QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG,
|
||||
[QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG,
|
||||
/*
|
||||
* Match qemu_plugin_vcpu_mem_cb_t:
|
||||
* void (*)(uint32_t, qemu_plugin_meminfo_t, uint64_t, void *)
|
||||
*/
|
||||
[0 ... 2].typemask =
|
||||
(dh_typemask(void, 0) |
|
||||
dh_typemask(i32, 1) |
|
||||
(__builtin_types_compatible_p(qemu_plugin_meminfo_t, uint32_t)
|
||||
? dh_typemask(i32, 2) : dh_typemask(s32, 2)) |
|
||||
dh_typemask(i64, 3) |
|
||||
dh_typemask(ptr, 4))
|
||||
};
|
||||
|
||||
struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
|
||||
dyn_cb->userp = udata;
|
||||
/* Note flags are discarded as unused. */
|
||||
dyn_cb->type = PLUGIN_CB_REGULAR;
|
||||
dyn_cb->type = PLUGIN_CB_MEM_REGULAR;
|
||||
dyn_cb->rw = rw;
|
||||
dyn_cb->f.generic = cb;
|
||||
dyn_cb->regular.f.vcpu_mem = cb;
|
||||
|
||||
assert((unsigned)flags < ARRAY_SIZE(info));
|
||||
dyn_cb->regular.info = &info[flags];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -510,9 +547,9 @@ void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
|
|||
break;
|
||||
}
|
||||
switch (cb->type) {
|
||||
case PLUGIN_CB_REGULAR:
|
||||
cb->f.vcpu_mem(cpu->cpu_index, make_plugin_meminfo(oi, rw),
|
||||
vaddr, cb->userp);
|
||||
case PLUGIN_CB_MEM_REGULAR:
|
||||
cb->regular.f.vcpu_mem(cpu->cpu_index, make_plugin_meminfo(oi, rw),
|
||||
vaddr, cb->userp);
|
||||
break;
|
||||
case PLUGIN_CB_INLINE:
|
||||
exec_inline_op(cb, cpu->cpu_index);
|
||||
|
|
|
@ -161,14 +161,14 @@ plugin_gen_mem_callbacks(TCGv_i64 copy_addr, TCGTemp *orig_addr, MemOpIdx oi,
|
|||
copy_addr = tcg_temp_ebb_new_i64();
|
||||
tcg_gen_extu_i32_i64(copy_addr, temp_tcgv_i32(orig_addr));
|
||||
}
|
||||
plugin_gen_empty_mem_callback(copy_addr, info);
|
||||
tcg_gen_plugin_mem_cb(copy_addr, info);
|
||||
tcg_temp_free_i64(copy_addr);
|
||||
} else {
|
||||
if (copy_addr) {
|
||||
plugin_gen_empty_mem_callback(copy_addr, info);
|
||||
tcg_gen_plugin_mem_cb(copy_addr, info);
|
||||
tcg_temp_free_i64(copy_addr);
|
||||
} else {
|
||||
plugin_gen_empty_mem_callback(temp_tcgv_i64(orig_addr), info);
|
||||
tcg_gen_plugin_mem_cb(temp_tcgv_i64(orig_addr), info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,14 +312,14 @@ void tcg_gen_mb(TCGBar mb_type)
|
|||
}
|
||||
}
|
||||
|
||||
void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr)
|
||||
void tcg_gen_plugin_cb(unsigned from)
|
||||
{
|
||||
tcg_gen_op3(INDEX_op_plugin_cb_start, from, type, wr);
|
||||
tcg_gen_op1(INDEX_op_plugin_cb, from);
|
||||
}
|
||||
|
||||
void tcg_gen_plugin_cb_end(void)
|
||||
void tcg_gen_plugin_mem_cb(TCGv_i64 addr, unsigned meminfo)
|
||||
{
|
||||
tcg_emit_op(INDEX_op_plugin_cb_end, 0);
|
||||
tcg_gen_op2(INDEX_op_plugin_mem_cb, tcgv_i64_arg(addr), meminfo);
|
||||
}
|
||||
|
||||
/* 32 bit ops */
|
||||
|
|
78
tcg/tcg.c
78
tcg/tcg.c
|
@ -2251,7 +2251,8 @@ bool tcg_op_supported(TCGOpcode op)
|
|||
|
||||
static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs);
|
||||
|
||||
static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
|
||||
static void tcg_gen_callN(void *func, TCGHelperInfo *info,
|
||||
TCGTemp *ret, TCGTemp **args)
|
||||
{
|
||||
TCGv_i64 extend_free[MAX_CALL_IARGS];
|
||||
int n_extend = 0;
|
||||
|
@ -2268,9 +2269,7 @@ static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
|
|||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
/* Flag helpers that may affect guest state */
|
||||
if (tcg_ctx->plugin_insn &&
|
||||
!(info->flags & TCG_CALL_PLUGIN) &&
|
||||
!(info->flags & TCG_CALL_NO_SIDE_EFFECTS)) {
|
||||
if (tcg_ctx->plugin_insn && !(info->flags & TCG_CALL_NO_SIDE_EFFECTS)) {
|
||||
tcg_ctx->plugin_insn->calls_helpers = true;
|
||||
}
|
||||
#endif
|
||||
|
@ -2329,7 +2328,7 @@ static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
|
|||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
op->args[pi++] = (uintptr_t)info->func;
|
||||
op->args[pi++] = (uintptr_t)func;
|
||||
op->args[pi++] = (uintptr_t)info;
|
||||
tcg_debug_assert(pi == total_args);
|
||||
|
||||
|
@ -2345,56 +2344,58 @@ static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
|
|||
}
|
||||
}
|
||||
|
||||
void tcg_gen_call0(TCGHelperInfo *info, TCGTemp *ret)
|
||||
void tcg_gen_call0(void *func, TCGHelperInfo *info, TCGTemp *ret)
|
||||
{
|
||||
tcg_gen_callN(info, ret, NULL);
|
||||
tcg_gen_callN(func, info, ret, NULL);
|
||||
}
|
||||
|
||||
void tcg_gen_call1(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1)
|
||||
void tcg_gen_call1(void *func, TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1)
|
||||
{
|
||||
tcg_gen_callN(info, ret, &t1);
|
||||
tcg_gen_callN(func, info, ret, &t1);
|
||||
}
|
||||
|
||||
void tcg_gen_call2(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1, TCGTemp *t2)
|
||||
void tcg_gen_call2(void *func, TCGHelperInfo *info, TCGTemp *ret,
|
||||
TCGTemp *t1, TCGTemp *t2)
|
||||
{
|
||||
TCGTemp *args[2] = { t1, t2 };
|
||||
tcg_gen_callN(info, ret, args);
|
||||
tcg_gen_callN(func, info, ret, args);
|
||||
}
|
||||
|
||||
void tcg_gen_call3(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
|
||||
TCGTemp *t2, TCGTemp *t3)
|
||||
void tcg_gen_call3(void *func, TCGHelperInfo *info, TCGTemp *ret,
|
||||
TCGTemp *t1, TCGTemp *t2, TCGTemp *t3)
|
||||
{
|
||||
TCGTemp *args[3] = { t1, t2, t3 };
|
||||
tcg_gen_callN(info, ret, args);
|
||||
tcg_gen_callN(func, info, ret, args);
|
||||
}
|
||||
|
||||
void tcg_gen_call4(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
|
||||
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4)
|
||||
void tcg_gen_call4(void *func, TCGHelperInfo *info, TCGTemp *ret,
|
||||
TCGTemp *t1, TCGTemp *t2, TCGTemp *t3, TCGTemp *t4)
|
||||
{
|
||||
TCGTemp *args[4] = { t1, t2, t3, t4 };
|
||||
tcg_gen_callN(info, ret, args);
|
||||
tcg_gen_callN(func, info, ret, args);
|
||||
}
|
||||
|
||||
void tcg_gen_call5(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
|
||||
void tcg_gen_call5(void *func, TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
|
||||
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4, TCGTemp *t5)
|
||||
{
|
||||
TCGTemp *args[5] = { t1, t2, t3, t4, t5 };
|
||||
tcg_gen_callN(info, ret, args);
|
||||
tcg_gen_callN(func, info, ret, args);
|
||||
}
|
||||
|
||||
void tcg_gen_call6(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1, TCGTemp *t2,
|
||||
TCGTemp *t3, TCGTemp *t4, TCGTemp *t5, TCGTemp *t6)
|
||||
void tcg_gen_call6(void *func, TCGHelperInfo *info, TCGTemp *ret,
|
||||
TCGTemp *t1, TCGTemp *t2, TCGTemp *t3,
|
||||
TCGTemp *t4, TCGTemp *t5, TCGTemp *t6)
|
||||
{
|
||||
TCGTemp *args[6] = { t1, t2, t3, t4, t5, t6 };
|
||||
tcg_gen_callN(info, ret, args);
|
||||
tcg_gen_callN(func, info, ret, args);
|
||||
}
|
||||
|
||||
void tcg_gen_call7(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
|
||||
void tcg_gen_call7(void *func, TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
|
||||
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4,
|
||||
TCGTemp *t5, TCGTemp *t6, TCGTemp *t7)
|
||||
{
|
||||
TCGTemp *args[7] = { t1, t2, t3, t4, t5, t6, t7 };
|
||||
tcg_gen_callN(info, ret, args);
|
||||
tcg_gen_callN(func, info, ret, args);
|
||||
}
|
||||
|
||||
static void tcg_reg_alloc_start(TCGContext *s)
|
||||
|
@ -2539,6 +2540,15 @@ static const char bswap_flag_name[][6] = {
|
|||
[TCG_BSWAP_IZ | TCG_BSWAP_OS] = "iz,os",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
static const char * const plugin_from_name[] = {
|
||||
"from-tb",
|
||||
"from-insn",
|
||||
"after-insn",
|
||||
"after-tb",
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline bool tcg_regset_single(TCGRegSet d)
|
||||
{
|
||||
return (d & (d - 1)) == 0;
|
||||
|
@ -2557,7 +2567,7 @@ static inline TCGReg tcg_regset_first(TCGRegSet d)
|
|||
#define ne_fprintf(...) \
|
||||
({ int ret_ = fprintf(__VA_ARGS__); ret_ >= 0 ? ret_ : 0; })
|
||||
|
||||
static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
|
||||
void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
|
||||
{
|
||||
char buf[128];
|
||||
TCGOp *op;
|
||||
|
@ -2713,6 +2723,24 @@ static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
|
|||
i = k = 1;
|
||||
}
|
||||
break;
|
||||
#ifdef CONFIG_PLUGIN
|
||||
case INDEX_op_plugin_cb:
|
||||
{
|
||||
TCGArg from = op->args[k++];
|
||||
const char *name = NULL;
|
||||
|
||||
if (from < ARRAY_SIZE(plugin_from_name)) {
|
||||
name = plugin_from_name[from];
|
||||
}
|
||||
if (name) {
|
||||
col += ne_fprintf(f, "%s", name);
|
||||
} else {
|
||||
col += ne_fprintf(f, "$0x%" TCG_PRIlx, from);
|
||||
}
|
||||
i = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
i = 0;
|
||||
break;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg/helper-info.h"
|
||||
#include "tcg/tcg-ldst.h"
|
||||
#include <ffi.h>
|
||||
|
||||
|
|
|
@ -466,6 +466,10 @@ const QEMULogItem qemu_log_items[] = {
|
|||
"show micro ops after optimization" },
|
||||
{ CPU_LOG_TB_OP_IND, "op_ind",
|
||||
"show micro ops before indirect lowering" },
|
||||
#ifdef CONFIG_PLUGIN
|
||||
{ LOG_TB_OP_PLUGIN, "op_plugin",
|
||||
"show micro ops before plugin injection" },
|
||||
#endif
|
||||
{ CPU_LOG_INT, "int",
|
||||
"show interrupts/exceptions in short format" },
|
||||
{ CPU_LOG_EXEC, "exec",
|
||||
|
|
Loading…
Reference in New Issue