Skip to content

Commit

Permalink
Merge tag 'pull-maintainer-may24-160524-2' of https://gitlab.com/stsq…
Browse files Browse the repository at this point in the history
…uad/qemu into staging

plugin and testing updates

 - don't duplicate options for microbit test
 - don't spam the linux source tree when importing headers
 - add STORE_U64 inline op to TCG plugins
 - add conditional callback op to TCG plugins

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmZFvCMACgkQ+9DbCVqe
# KkSrYQf/aj9+eCWCKZk3Hym0lT+qNKxUeNSx3juUN8h7iG1vkA1f/XaQle5XvKDr
# ROIdo8urcr8onJ4PBH+4C7VZhUmnpL8zLH80pCuuTkF03MCNhaW/5qJ67niWmPVM
# QJHVqNomkykKOMBh+WtD5M0m/BYPT5lsa10sE3bDH8ziGjp0An2v24R89tzYEXnf
# 1QePItQN5vzEvhrZj6oKWVmeucqLsqS6yqS8V3sEpmF0+zqNjGZlrI86A4SAp74k
# 8vuduVuRbeyki7zWBTOLUeoiuHM2Zmh7v74zm/Hc1ITBaDjWMwPctcI/vFjsrCI/
# yoFRhgrV87DtIZdkrJzk5qBYFOWoeQ==
# =znN0
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 16 May 2024 09:56:19 AM CEST
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]

* tag 'pull-maintainer-may24-160524-2' of https://gitlab.com/stsquad/qemu:
  plugins: remove op from qemu_plugin_inline_cb
  plugins: extract cpu_index generate
  plugins: distinct types for callbacks
  tests/plugin/inline: add test for conditional callback
  plugins: conditional callbacks
  tests/plugin/inline: add test for STORE_U64 inline op
  plugins: add new inline op STORE_U64
  plugins: extract generate ptr for qemu_plugin_u64
  plugins: prepare introduction of new inline ops
  scripts/update-linux-header.sh: be more src tree friendly
  tests/tcg: don't append QEMU_OPTS for armv6m-undef test

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 16, 2024
2 parents 922582a + 09afe96 commit 85ef20f
Show file tree
Hide file tree
Showing 10 changed files with 508 additions and 124 deletions.
136 changes: 105 additions & 31 deletions accel/tcg/plugin-gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,49 +101,111 @@ static void gen_disable_mem_helper(void)
offsetof(ArchCPU, env));
}

static void gen_udata_cb(struct qemu_plugin_dyn_cb *cb)
static TCGv_i32 gen_cpu_index(void)
{
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();

tcg_gen_ld_i32(cpu_index, tcg_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
tcg_gen_call2(cb->regular.f.vcpu_udata, cb->regular.info, NULL,
return cpu_index;
}

static void gen_udata_cb(struct qemu_plugin_regular_cb *cb)
{
TCGv_i32 cpu_index = gen_cpu_index();
tcg_gen_call2(cb->f.vcpu_udata, cb->info, NULL,
tcgv_i32_temp(cpu_index),
tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
tcg_temp_free_i32(cpu_index);
}

static void gen_inline_cb(struct qemu_plugin_dyn_cb *cb)
static TCGv_ptr gen_plugin_u64_ptr(qemu_plugin_u64 entry)
{
GArray *arr = cb->inline_insn.entry.score->data;
size_t offset = cb->inline_insn.entry.offset;
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
TCGv_i64 val = tcg_temp_ebb_new_i64();
TCGv_ptr ptr = tcg_temp_ebb_new_ptr();

tcg_gen_ld_i32(cpu_index, tcg_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
tcg_gen_muli_i32(cpu_index, cpu_index, g_array_get_element_size(arr));
GArray *arr = entry.score->data;
char *base_ptr = arr->data + entry.offset;
size_t entry_size = g_array_get_element_size(arr);

TCGv_i32 cpu_index = gen_cpu_index();
tcg_gen_muli_i32(cpu_index, cpu_index, entry_size);
tcg_gen_ext_i32_ptr(ptr, cpu_index);
tcg_temp_free_i32(cpu_index);
tcg_gen_addi_ptr(ptr, ptr, (intptr_t) base_ptr);

tcg_gen_addi_ptr(ptr, ptr, (intptr_t)arr->data);
tcg_gen_ld_i64(val, ptr, offset);
tcg_gen_addi_i64(val, val, cb->inline_insn.imm);
tcg_gen_st_i64(val, ptr, offset);
return ptr;
}

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

static void gen_udata_cond_cb(struct qemu_plugin_conditional_cb *cb)
{
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->entry);
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 */
TCGCond cond = tcg_invert_cond(plugin_cond_to_tcgcond(cb->cond));

tcg_gen_ld_i64(val, ptr, 0);
tcg_gen_brcondi_i64(cond, val, cb->imm, after_cb);
TCGv_i32 cpu_index = gen_cpu_index();
tcg_gen_call2(cb->f.vcpu_udata, cb->info, NULL,
tcgv_i32_temp(cpu_index),
tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
tcg_temp_free_i32(cpu_index);
gen_set_label(after_cb);

tcg_temp_free_i64(val);
tcg_temp_free_ptr(ptr);
}

static void gen_mem_cb(struct qemu_plugin_dyn_cb *cb,
qemu_plugin_meminfo_t meminfo, TCGv_i64 addr)
static void gen_inline_add_u64_cb(struct qemu_plugin_inline_cb *cb)
{
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->entry);
TCGv_i64 val = tcg_temp_ebb_new_i64();

tcg_gen_ld_i32(cpu_index, tcg_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
tcg_gen_call4(cb->regular.f.vcpu_mem, cb->regular.info, NULL,
tcg_gen_ld_i64(val, ptr, 0);
tcg_gen_addi_i64(val, val, cb->imm);
tcg_gen_st_i64(val, ptr, 0);

tcg_temp_free_i64(val);
tcg_temp_free_ptr(ptr);
}

static void gen_inline_store_u64_cb(struct qemu_plugin_inline_cb *cb)
{
TCGv_ptr ptr = gen_plugin_u64_ptr(cb->entry);
TCGv_i64 val = tcg_constant_i64(cb->imm);

tcg_gen_st_i64(val, ptr, 0);

tcg_temp_free_ptr(ptr);
}

static void gen_mem_cb(struct qemu_plugin_regular_cb *cb,
qemu_plugin_meminfo_t meminfo, TCGv_i64 addr)
{
TCGv_i32 cpu_index = gen_cpu_index();
tcg_gen_call4(cb->f.vcpu_mem, cb->info, NULL,
tcgv_i32_temp(cpu_index),
tcgv_i32_temp(tcg_constant_i32(meminfo)),
tcgv_i64_temp(addr),
Expand All @@ -156,10 +218,16 @@ static void inject_cb(struct qemu_plugin_dyn_cb *cb)
{
switch (cb->type) {
case PLUGIN_CB_REGULAR:
gen_udata_cb(cb);
gen_udata_cb(&cb->regular);
break;
case PLUGIN_CB_COND:
gen_udata_cond_cb(&cb->cond);
break;
case PLUGIN_CB_INLINE:
gen_inline_cb(cb);
case PLUGIN_CB_INLINE_ADD_U64:
gen_inline_add_u64_cb(&cb->inline_insn);
break;
case PLUGIN_CB_INLINE_STORE_U64:
gen_inline_store_u64_cb(&cb->inline_insn);
break;
default:
g_assert_not_reached();
Expand All @@ -170,15 +238,21 @@ 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)
{
if (cb->rw & rw) {
switch (cb->type) {
case PLUGIN_CB_MEM_REGULAR:
gen_mem_cb(cb, meminfo, addr);
break;
default:
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) {
inject_cb(cb);
break;
}
break;
default:
g_assert_not_reached();
break;
}
}

Expand Down
42 changes: 28 additions & 14 deletions include/qemu/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,32 @@ union qemu_plugin_cb_sig {

enum plugin_dyn_cb_type {
PLUGIN_CB_REGULAR,
PLUGIN_CB_COND,
PLUGIN_CB_MEM_REGULAR,
PLUGIN_CB_INLINE,
PLUGIN_CB_INLINE_ADD_U64,
PLUGIN_CB_INLINE_STORE_U64,
};

struct qemu_plugin_regular_cb {
union qemu_plugin_cb_sig f;
TCGHelperInfo *info;
void *userp;
enum qemu_plugin_mem_rw rw;
};

struct qemu_plugin_inline_cb {
qemu_plugin_u64 entry;
uint64_t imm;
enum qemu_plugin_mem_rw rw;
};

struct qemu_plugin_conditional_cb {
union qemu_plugin_cb_sig f;
TCGHelperInfo *info;
void *userp;
qemu_plugin_u64 entry;
enum qemu_plugin_cond cond;
uint64_t imm;
};

/*
Expand All @@ -78,21 +102,11 @@ enum plugin_dyn_cb_type {
* instance of a callback to be called upon the execution of a particular TB.
*/
struct qemu_plugin_dyn_cb {
void *userp;
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;
uint64_t imm;
} inline_insn;
struct qemu_plugin_regular_cb regular;
struct qemu_plugin_conditional_cb cond;
struct qemu_plugin_inline_cb inline_insn;
};
};

Expand Down
80 changes: 78 additions & 2 deletions include/qemu/qemu-plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,29 @@ enum qemu_plugin_mem_rw {
QEMU_PLUGIN_MEM_RW,
};

/**
* enum qemu_plugin_cond - condition to enable callback
*
* @QEMU_PLUGIN_COND_NEVER: false
* @QEMU_PLUGIN_COND_ALWAYS: true
* @QEMU_PLUGIN_COND_EQ: is equal?
* @QEMU_PLUGIN_COND_NE: is not equal?
* @QEMU_PLUGIN_COND_LT: is less than?
* @QEMU_PLUGIN_COND_LE: is less than or equal?
* @QEMU_PLUGIN_COND_GT: is greater than?
* @QEMU_PLUGIN_COND_GE: is greater than or equal?
*/
enum qemu_plugin_cond {
QEMU_PLUGIN_COND_NEVER,
QEMU_PLUGIN_COND_ALWAYS,
QEMU_PLUGIN_COND_EQ,
QEMU_PLUGIN_COND_NE,
QEMU_PLUGIN_COND_LT,
QEMU_PLUGIN_COND_LE,
QEMU_PLUGIN_COND_GT,
QEMU_PLUGIN_COND_GE,
};

/**
* typedef qemu_plugin_vcpu_tb_trans_cb_t - translation callback
* @id: unique plugin id
Expand Down Expand Up @@ -301,16 +324,42 @@ void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,
enum qemu_plugin_cb_flags flags,
void *userdata);

/**
* qemu_plugin_register_vcpu_tb_exec_cond_cb() - register conditional callback
* @tb: the opaque qemu_plugin_tb handle for the translation
* @cb: callback function
* @cond: condition to enable callback
* @entry: first operand for condition
* @imm: second operand for condition
* @flags: does the plugin read or write the CPU's registers?
* @userdata: any plugin data to pass to the @cb?
*
* The @cb function is called when a translated unit executes if
* entry @cond imm is true.
* If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and
* this function is equivalent to qemu_plugin_register_vcpu_tb_exec_cb.
* If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and
* callback is never installed.
*/
QEMU_PLUGIN_API
void qemu_plugin_register_vcpu_tb_exec_cond_cb(struct qemu_plugin_tb *tb,
qemu_plugin_vcpu_udata_cb_t cb,
enum qemu_plugin_cb_flags flags,
enum qemu_plugin_cond cond,
qemu_plugin_u64 entry,
uint64_t imm,
void *userdata);

/**
* enum qemu_plugin_op - describes an inline op
*
* @QEMU_PLUGIN_INLINE_ADD_U64: add an immediate value uint64_t
*
* Note: currently only a single inline op is supported.
* @QEMU_PLUGIN_INLINE_STORE_U64: store an immediate value uint64_t
*/

enum qemu_plugin_op {
QEMU_PLUGIN_INLINE_ADD_U64,
QEMU_PLUGIN_INLINE_STORE_U64,
};

/**
Expand Down Expand Up @@ -344,6 +393,33 @@ void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,
enum qemu_plugin_cb_flags flags,
void *userdata);

/**
* qemu_plugin_register_vcpu_insn_exec_cond_cb() - conditional insn execution cb
* @insn: the opaque qemu_plugin_insn handle for an instruction
* @cb: callback function
* @flags: does the plugin read or write the CPU's registers?
* @cond: condition to enable callback
* @entry: first operand for condition
* @imm: second operand for condition
* @userdata: any plugin data to pass to the @cb?
*
* The @cb function is called when an instruction executes if
* entry @cond imm is true.
* If condition is QEMU_PLUGIN_COND_ALWAYS, condition is never interpreted and
* this function is equivalent to qemu_plugin_register_vcpu_insn_exec_cb.
* If condition QEMU_PLUGIN_COND_NEVER, condition is never interpreted and
* callback is never installed.
*/
QEMU_PLUGIN_API
void qemu_plugin_register_vcpu_insn_exec_cond_cb(
struct qemu_plugin_insn *insn,
qemu_plugin_vcpu_udata_cb_t cb,
enum qemu_plugin_cb_flags flags,
enum qemu_plugin_cond cond,
qemu_plugin_u64 entry,
uint64_t imm,
void *userdata);

/**
* qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu() - insn exec inline op
* @insn: the opaque qemu_plugin_insn handle for an instruction
Expand Down

0 comments on commit 85ef20f

Please sign in to comment.