On 12/2/24 11:41, Julian Ganz wrote:
We recently introduced plugin API for the registration of callbacks for
discontinuity events, specifically for interrupts, exceptions and host
call events. The callback receives, among other information, the VCPU
index and the PC after the event. This change introduces a test plugin
asserting that particular behaviour.
---
  tests/tcg/plugins/discons.c   | 95 +++++++++++++++++++++++++++++++++++
  tests/tcg/plugins/meson.build |  2 +-
  2 files changed, 96 insertions(+), 1 deletion(-)
  create mode 100644 tests/tcg/plugins/discons.c

diff --git a/tests/tcg/plugins/discons.c b/tests/tcg/plugins/discons.c
new file mode 100644
index 0000000000..54e52f563a
--- /dev/null
+++ b/tests/tcg/plugins/discons.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024, Julian Ganz <neither@nut.email>
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ */

Would be nice to include a description of the plugin here.

+#include <stdio.h>
+
+#include <qemu-plugin.h>
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+struct cpu_state {
+    uint64_t next_pc;
+    bool has_next;
+};
+
+static struct qemu_plugin_scoreboard *states;
+
+static bool abort_on_mismatch;
+
+static void vcpu_discon(qemu_plugin_id_t id, unsigned int vcpu_index,
+                        enum qemu_plugin_discon_type type, uint64_t from_pc,
+                        uint64_t to_pc)
+{
+    struct cpu_state *state = qemu_plugin_scoreboard_find(states, vcpu_index);
+    state->next_pc = to_pc;
+    state->has_next = true;
+}
+
+static void insn_exec(unsigned int vcpu_index, void *userdata)
+{
+    struct cpu_state *state = qemu_plugin_scoreboard_find(states, vcpu_index);
+    uint64_t pc = (uint64_t) userdata;
+    GString* report;
+
+    if (state->has_next) {
+        if (state->next_pc != pc) {
+            report = g_string_new("Trap target PC mismatch\n");
+            g_string_append_printf(report,
+                                   "Expected:    %"PRIx64"\nEncountered: %"
+                                   PRIx64"\n",
+                                   state->next_pc, pc);
+            qemu_plugin_outs(report->str);
+            if (abort_on_mismatch) {
+                g_abort();
+            }
+            g_string_free(report, true);
+        }
+        state->has_next = false;
+    }
+}

When booting an arm64 vm, I get this message:
Trap target PC mismatch
Expected:    23faf3a80
Encountered: 23faf3a84

From what I understand, it means that the next_pc we have is incorrect.

+
+static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
+{
+    size_t i;
+    size_t n_insns = qemu_plugin_tb_n_insns(tb);
+
+    for (i = 0; i < n_insns; i++) {
+        struct qemu_plugin_insn * insn = qemu_plugin_tb_get_insn(tb, i);
+        uint64_t pc = qemu_plugin_insn_vaddr(insn);
+        qemu_plugin_register_vcpu_insn_exec_cb(insn, insn_exec,
+                                               QEMU_PLUGIN_CB_NO_REGS,
+                                               (void*) pc);
+    }
> +}> +
+QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
+                                           const qemu_info_t *info,
+                                           int argc, char **argv)
+{
+    int i;
+
+    for (i = 0; i < argc; i++) {
+        char *opt = argv[i];
+        g_auto(GStrv) tokens = g_strsplit(opt, "=", 2);
+        if (g_strcmp0(tokens[0], "abort") == 0) {
+            if (!qemu_plugin_bool_parse(tokens[0], tokens[1], 
&abort_on_mismatch)) {
+                fprintf(stderr, "boolean argument parsing failed: %s\n", opt);
+                return -1;
+            }
+        } else {
+            fprintf(stderr, "option parsing failed: %s\n", opt);
+            return -1;
+        }
+    }
+
+    states = qemu_plugin_scoreboard_new(sizeof(struct cpu_state));
+
+    qemu_plugin_register_vcpu_discon_cb(id, QEMU_PLUGIN_DISCON_ALL,
+                                        vcpu_discon);
+    qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
+
+    return 0;
+}
diff --git a/tests/tcg/plugins/meson.build b/tests/tcg/plugins/meson.build
index f847849b1b..f057238da1 100644
--- a/tests/tcg/plugins/meson.build
+++ b/tests/tcg/plugins/meson.build
@@ -1,6 +1,6 @@
  t = []
  if get_option('plugins')
-  foreach i : ['bb', 'empty', 'inline', 'insn', 'mem', 'syscall']
+  foreach i : ['bb', 'discons', 'empty', 'inline', 'insn', 'mem', 'syscall']
      if host_os == 'windows'
        t += shared_module(i, files(i + '.c') + 
'../../../contrib/plugins/win32_linker.c',
                          include_directories: '../../../include/qemu',


Reply via email to