Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
---
contrib/plugins/stoptrigger.c | 48 ++++++++++++++++++++---------------
1 file changed, 27 insertions(+), 21 deletions(-)
diff --git a/contrib/plugins/stoptrigger.c b/contrib/plugins/stoptrigger.c
index 03ee22f4c6a..b3a6ed66a7b 100644
--- a/contrib/plugins/stoptrigger.c
+++ b/contrib/plugins/stoptrigger.c
@@ -21,9 +21,11 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
/* Scoreboard to track executed instructions count */
typedef struct {
uint64_t insn_count;
+ uint64_t current_pc;
} InstructionsCount;
static struct qemu_plugin_scoreboard *insn_count_sb;
static qemu_plugin_u64 insn_count;
+static qemu_plugin_u64 current_pc;
static uint64_t icount;
static int icount_exit_code;
@@ -34,6 +36,11 @@ static bool exit_on_address;
/* Map trigger addresses to exit code */
static GHashTable *addrs_ht;
+typedef struct {
+ uint64_t exit_addr;
+ int exit_code;
+} ExitInfo;
+
static void exit_emulation(int return_code, char *message)
{
qemu_plugin_outs(message);
@@ -43,23 +50,18 @@ static void exit_emulation(int return_code, char *message)
static void exit_icount_reached(unsigned int cpu_index, void *udata)
{
- uint64_t insn_vaddr = GPOINTER_TO_UINT(udata);
+ uint64_t insn_vaddr = qemu_plugin_u64_get(current_pc, cpu_index);
char *msg = g_strdup_printf("icount reached at 0x%" PRIx64 ", exiting\n",
insn_vaddr);
-
exit_emulation(icount_exit_code, msg);
}
static void exit_address_reached(unsigned int cpu_index, void *udata)
{
- uint64_t insn_vaddr = GPOINTER_TO_UINT(udata);
- char *msg = g_strdup_printf("0x%" PRIx64 " reached, exiting\n", insn_vaddr);
- int exit_code;
-
- exit_code = GPOINTER_TO_INT(
- g_hash_table_lookup(addrs_ht, GUINT_TO_POINTER(insn_vaddr)));
-
- exit_emulation(exit_code, msg);
+ ExitInfo *ei = udata;
+ g_assert(ei);
+ char *msg = g_strdup_printf("0x%" PRIx64 " reached, exiting\n", ei->exit_addr);
+ exit_emulation(ei->exit_code, msg);
}
static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
@@ -67,23 +69,25 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
size_t tb_n = qemu_plugin_tb_n_insns(tb);
for (size_t i = 0; i < tb_n; i++) {
struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
- gpointer insn_vaddr = GUINT_TO_POINTER(qemu_plugin_insn_vaddr(insn));
+ uint64_t insn_vaddr = qemu_plugin_insn_vaddr(insn);
if (exit_on_icount) {
/* Increment and check scoreboard for each instruction */
qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
insn, QEMU_PLUGIN_INLINE_ADD_U64, insn_count, 1);
+ qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
+ insn, QEMU_PLUGIN_INLINE_STORE_U64, current_pc, insn_vaddr);
qemu_plugin_register_vcpu_insn_exec_cond_cb(
insn, exit_icount_reached, QEMU_PLUGIN_CB_NO_REGS,
- QEMU_PLUGIN_COND_EQ, insn_count, icount + 1, insn_vaddr);
+ QEMU_PLUGIN_COND_EQ, insn_count, icount + 1, NULL);
}
if (exit_on_address) {
- if (g_hash_table_contains(addrs_ht, insn_vaddr)) {
+ ExitInfo *ei = g_hash_table_lookup(addrs_ht, &insn_vaddr);
+ if (ei) {
/* Exit triggered by address */
qemu_plugin_register_vcpu_insn_exec_cb(
- insn, exit_address_reached, QEMU_PLUGIN_CB_NO_REGS,
- insn_vaddr);
+ insn, exit_address_reached, QEMU_PLUGIN_CB_NO_REGS, ei);
}
}
}
@@ -99,11 +103,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
const qemu_info_t *info, int argc,
char **argv)
{
- addrs_ht = g_hash_table_new(NULL, g_direct_equal);
+ addrs_ht = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, g_free);
insn_count_sb = qemu_plugin_scoreboard_new(sizeof(InstructionsCount));
insn_count = qemu_plugin_scoreboard_u64_in_struct(
insn_count_sb, InstructionsCount, insn_count);
+ current_pc = qemu_plugin_scoreboard_u64_in_struct(
+ insn_count_sb, InstructionsCount, current_pc);
for (int i = 0; i < argc; i++) {
char *opt = argv[i];
@@ -124,13 +130,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
exit_on_icount = true;
} else if (g_strcmp0(tokens[0], "addr") == 0) {
g_auto(GStrv) addr_tokens = g_strsplit(tokens[1], ":", 2);
- uint64_t exit_addr = g_ascii_strtoull(addr_tokens[0], NULL, 0);
- int exit_code = 0;
+ ExitInfo *ei = g_malloc(sizeof(ExitInfo));
+ ei->exit_addr = g_ascii_strtoull(addr_tokens[0], NULL, 0);
+ ei->exit_code = 0;
if (addr_tokens[1]) {
- exit_code = g_ascii_strtoull(addr_tokens[1], NULL, 0);
+ ei->exit_code = g_ascii_strtoull(addr_tokens[1], NULL, 0);
}
- g_hash_table_insert(addrs_ht, GUINT_TO_POINTER(exit_addr),
- GINT_TO_POINTER(exit_code));
+ g_hash_table_insert(addrs_ht, &ei->exit_addr, ei);
exit_on_address = true;
} else {
fprintf(stderr, "option parsing failed: %s\n", opt);
--
2.39.5
On 12/17/24 16:43, Pierrick Bouvier wrote:
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> ---
> contrib/plugins/stoptrigger.c | 48 ++++++++++++++++++++---------------
> 1 file changed, 27 insertions(+), 21 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
>
> diff --git a/contrib/plugins/stoptrigger.c b/contrib/plugins/stoptrigger.c
> index 03ee22f4c6a..b3a6ed66a7b 100644
> --- a/contrib/plugins/stoptrigger.c
> +++ b/contrib/plugins/stoptrigger.c
> @@ -21,9 +21,11 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
> /* Scoreboard to track executed instructions count */
> typedef struct {
> uint64_t insn_count;
> + uint64_t current_pc;
> } InstructionsCount;
> static struct qemu_plugin_scoreboard *insn_count_sb;
> static qemu_plugin_u64 insn_count;
> +static qemu_plugin_u64 current_pc;
>
> static uint64_t icount;
> static int icount_exit_code;
> @@ -34,6 +36,11 @@ static bool exit_on_address;
> /* Map trigger addresses to exit code */
> static GHashTable *addrs_ht;
>
> +typedef struct {
> + uint64_t exit_addr;
> + int exit_code;
> +} ExitInfo;
> +
> static void exit_emulation(int return_code, char *message)
> {
> qemu_plugin_outs(message);
> @@ -43,23 +50,18 @@ static void exit_emulation(int return_code, char *message)
>
> static void exit_icount_reached(unsigned int cpu_index, void *udata)
> {
> - uint64_t insn_vaddr = GPOINTER_TO_UINT(udata);
> + uint64_t insn_vaddr = qemu_plugin_u64_get(current_pc, cpu_index);
> char *msg = g_strdup_printf("icount reached at 0x%" PRIx64 ", exiting\n",
> insn_vaddr);
> -
> exit_emulation(icount_exit_code, msg);
> }
>
> static void exit_address_reached(unsigned int cpu_index, void *udata)
> {
> - uint64_t insn_vaddr = GPOINTER_TO_UINT(udata);
> - char *msg = g_strdup_printf("0x%" PRIx64 " reached, exiting\n", insn_vaddr);
> - int exit_code;
> -
> - exit_code = GPOINTER_TO_INT(
> - g_hash_table_lookup(addrs_ht, GUINT_TO_POINTER(insn_vaddr)));
> -
> - exit_emulation(exit_code, msg);
> + ExitInfo *ei = udata;
> + g_assert(ei);
> + char *msg = g_strdup_printf("0x%" PRIx64 " reached, exiting\n", ei->exit_addr);
> + exit_emulation(ei->exit_code, msg);
> }
>
> static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
> @@ -67,23 +69,25 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
> size_t tb_n = qemu_plugin_tb_n_insns(tb);
> for (size_t i = 0; i < tb_n; i++) {
> struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
> - gpointer insn_vaddr = GUINT_TO_POINTER(qemu_plugin_insn_vaddr(insn));
> + uint64_t insn_vaddr = qemu_plugin_insn_vaddr(insn);
>
> if (exit_on_icount) {
> /* Increment and check scoreboard for each instruction */
> qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
> insn, QEMU_PLUGIN_INLINE_ADD_U64, insn_count, 1);
> + qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
> + insn, QEMU_PLUGIN_INLINE_STORE_U64, current_pc, insn_vaddr);
> qemu_plugin_register_vcpu_insn_exec_cond_cb(
> insn, exit_icount_reached, QEMU_PLUGIN_CB_NO_REGS,
> - QEMU_PLUGIN_COND_EQ, insn_count, icount + 1, insn_vaddr);
> + QEMU_PLUGIN_COND_EQ, insn_count, icount + 1, NULL);
> }
>
> if (exit_on_address) {
> - if (g_hash_table_contains(addrs_ht, insn_vaddr)) {
> + ExitInfo *ei = g_hash_table_lookup(addrs_ht, &insn_vaddr);
> + if (ei) {
> /* Exit triggered by address */
> qemu_plugin_register_vcpu_insn_exec_cb(
> - insn, exit_address_reached, QEMU_PLUGIN_CB_NO_REGS,
> - insn_vaddr);
> + insn, exit_address_reached, QEMU_PLUGIN_CB_NO_REGS, ei);
> }
> }
> }
> @@ -99,11 +103,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
> const qemu_info_t *info, int argc,
> char **argv)
> {
> - addrs_ht = g_hash_table_new(NULL, g_direct_equal);
> + addrs_ht = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, g_free);
>
> insn_count_sb = qemu_plugin_scoreboard_new(sizeof(InstructionsCount));
> insn_count = qemu_plugin_scoreboard_u64_in_struct(
> insn_count_sb, InstructionsCount, insn_count);
> + current_pc = qemu_plugin_scoreboard_u64_in_struct(
> + insn_count_sb, InstructionsCount, current_pc);
>
> for (int i = 0; i < argc; i++) {
> char *opt = argv[i];
> @@ -124,13 +130,13 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
> exit_on_icount = true;
> } else if (g_strcmp0(tokens[0], "addr") == 0) {
> g_auto(GStrv) addr_tokens = g_strsplit(tokens[1], ":", 2);
> - uint64_t exit_addr = g_ascii_strtoull(addr_tokens[0], NULL, 0);
> - int exit_code = 0;
> + ExitInfo *ei = g_malloc(sizeof(ExitInfo));
> + ei->exit_addr = g_ascii_strtoull(addr_tokens[0], NULL, 0);
> + ei->exit_code = 0;
> if (addr_tokens[1]) {
> - exit_code = g_ascii_strtoull(addr_tokens[1], NULL, 0);
> + ei->exit_code = g_ascii_strtoull(addr_tokens[1], NULL, 0);
> }
> - g_hash_table_insert(addrs_ht, GUINT_TO_POINTER(exit_addr),
> - GINT_TO_POINTER(exit_code));
> + g_hash_table_insert(addrs_ht, &ei->exit_addr, ei);
> exit_on_address = true;
> } else {
> fprintf(stderr, "option parsing failed: %s\n", opt);
© 2016 - 2026 Red Hat, Inc.