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:
Richard Henderson 2024-05-01 15:15:33 -07:00
commit 4977ce198d
19 changed files with 399 additions and 938 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 */

View File

@ -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)); \

View File

@ -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 */

View File

@ -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 */

View File

@ -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. */

View File

@ -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.

View File

@ -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.

View File

@ -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 */

View File

@ -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,

View File

@ -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 */

View File

@ -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,

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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>

View File

@ -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",