@samitouri / QOSamiQemu / commits / 9fb1f82794

tests/tcg/plugins: test register accesses

The additional plugin tests register accesses, specifically both for read-only and read-write registers. Writing to a read-only register is currently not tested, as this would trigger an assertion and fail the test. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Florian Hofhammer <florian.hofhammer@epfl.ch> Link: https://lore.kernel.org/qemu-devel/20260305-setpc-v5-v7-8-4c3adba52403@epfl.ch Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>

Florian Hofhammer committed Mar 5, 2026 at 11:06 UTC 9fb1f82794fd61c2bb4d0d933ab03495f43af691
2 files changed +80
tests/tcg/plugins/meson.build
+1
@@ -6,6 +6,7 @@ test_plugins = [
6 'insn.c',
7 'mem.c',
8 'patch.c',
9 +'registers.c',
10 'reset.c',
11 'setpc.c',
12 'syscall.c',
tests/tcg/plugins/registers.c new
+79
@@ -0,0 +1,79 @@
1 +/*
2 + * SPDX-License-Identifier: GPL-2.0-or-later
3 + *
4 + * Copyright (C) 2026, Florian Hofhammer <florian.hofhammer@epfl.ch>
5 + */
6 +#include "glib.h"
7 +#include <inttypes.h>
8 +#include <assert.h>
9 +#include <stdlib.h>
10 +#include <string.h>
11 +#include <unistd.h>
12 +#include <stdio.h>
13 +
14 +#include <qemu-plugin.h>
15 +
16 +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
17 +
18 +/*
19 + * This plugin tests whether we can read and write registers via the plugin
20 + * API. We try to just read/write a single register, as some architectures have
21 + * registers that cannot be written to, which would fail the test.
22 + * See: https://lists.gnu.org/archive/html/qemu-devel/2026-02/msg07025.html
23 + */
24 +static void vcpu_init_cb(qemu_plugin_id_t id, unsigned int vcpu_index)
25 +{
26 + g_autoptr(GArray) regs = qemu_plugin_get_registers();
27 + g_assert(regs != NULL);
28 + g_autoptr(GByteArray) buf = g_byte_array_sized_new(0);
29 + qemu_plugin_reg_descriptor *reg_desc = NULL;
30 + bool success = false;
31 +
32 + /* Make sure we can read and write a register not marked as readonly */
33 + for (size_t i = 0; i < regs->len; i++) {
34 + reg_desc = &g_array_index(regs, qemu_plugin_reg_descriptor, i);
35 + if (!reg_desc->is_readonly) {
36 + g_byte_array_set_size(buf, 0);
37 + success = qemu_plugin_read_register(reg_desc->handle, buf);
38 + g_assert(success);
39 + g_assert(buf->len > 0);
40 + success = qemu_plugin_write_register(reg_desc->handle, buf);
41 + g_assert(success);
42 + break;
43 + } else {
44 + reg_desc = NULL;
45 + }
46 + }
47 + g_assert(regs->len == 0 || reg_desc != NULL);
48 +
49 + /*
50 + * Check whether we can still read a read-only register. On each
51 + * architecture, at least the PC should be read-only because it's only
52 + * supposed to be modified via the qemu_plugin_set_pc() function.
53 + */
54 + for (size_t i = 0; i < regs->len; i++) {
55 + reg_desc = &g_array_index(regs, qemu_plugin_reg_descriptor, i);
56 + if (reg_desc->is_readonly) {
57 + g_byte_array_set_size(buf, 0);
58 + success = qemu_plugin_read_register(reg_desc->handle, buf);
59 + g_assert(success);
60 + g_assert(buf->len > 0);
61 + break;
62 + } else {
63 + reg_desc = NULL;
64 + }
65 + }
66 + g_assert(regs->len == 0 || reg_desc != NULL);
67 + /*
68 + * Note: we currently do not test whether the read-only register can be
69 + * written to, because doing so would throw an assert in the plugin API.
70 + */
71 +}
72 +
73 +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
74 + const qemu_info_t *info,
75 + int argc, char **argv)
76 +{
77 + qemu_plugin_register_vcpu_init_cb(id, vcpu_init_cb);
78 + return 0;
79 +}