From d84ed5d2d4d495845ed9c709a576e847f9d91746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 18 Jul 2024 10:45:09 +0100 Subject: [PATCH 01/16] testing: bump to latest libvirt-ci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This brings in the latest python mappings for the BSD updates. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-2-alex.bennee@linaro.org> --- .gitlab-ci.d/cirrus/freebsd-13.vars | 2 +- tests/lcitool/libvirt-ci | 2 +- tests/vm/generated/freebsd.json | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.d/cirrus/freebsd-13.vars b/.gitlab-ci.d/cirrus/freebsd-13.vars index 3785afca36..29ab9645f9 100644 --- a/.gitlab-ci.d/cirrus/freebsd-13.vars +++ b/.gitlab-ci.d/cirrus/freebsd-13.vars @@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-tomli py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd' +PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py311-numpy py311-pillow py311-pip py311-sphinx py311-sphinx_rtd_theme py311-tomli py311-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd' PYPI_PKGS='' PYTHON='/usr/local/bin/python3' diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci index 0e9490cebc..789b4601bc 160000 --- a/tests/lcitool/libvirt-ci +++ b/tests/lcitool/libvirt-ci @@ -1 +1 @@ -Subproject commit 0e9490cebc726ef772b6c9e27dac32e7ae99f9b2 +Subproject commit 789b4601bce4e01f43fdb6ad4ce5ab4e46674440 diff --git a/tests/vm/generated/freebsd.json b/tests/vm/generated/freebsd.json index 2d5895ebed..2a361cecd0 100644 --- a/tests/vm/generated/freebsd.json +++ b/tests/vm/generated/freebsd.json @@ -51,13 +51,13 @@ "pixman", "pkgconf", "png", - "py39-numpy", - "py39-pillow", - "py39-pip", - "py39-sphinx", - "py39-sphinx_rtd_theme", - "py39-tomli", - "py39-yaml", + "py311-numpy", + "py311-pillow", + "py311-pip", + "py311-sphinx", + "py311-sphinx_rtd_theme", + "py311-tomli", + "py311-yaml", "python3", "rpm2cpio", "sdl2", From 955ad1121d7df678603336f4af6c8e774f657558 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 18 Jul 2024 10:45:10 +0100 Subject: [PATCH 02/16] tests/avocado: Remove non-working sparc leon3 test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test has been marked as broken more than 4 years ago, and so far nobody ever cared to fix it. Thus let's simply remove it now ... if somebody ever needs it again, they can restore the file from an older version of QEMU. Signed-off-by: Thomas Huth Reviewed-by: Clément Chigot Acked-by: Alex Bennée Message-Id: <20240710111755.60584-1-thuth@redhat.com> [AJB: fix MAINTAINERS] Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-3-alex.bennee@linaro.org> --- MAINTAINERS | 1 - tests/avocado/machine_sparc_leon3.py | 37 ---------------------------- 2 files changed, 38 deletions(-) delete mode 100644 tests/avocado/machine_sparc_leon3.py diff --git a/MAINTAINERS b/MAINTAINERS index 7d9811458c..d5ff6c2498 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1727,7 +1727,6 @@ S: Maintained F: hw/sparc/leon3.c F: hw/*/grlib* F: include/hw/*/grlib* -F: tests/avocado/machine_sparc_leon3.py S390 Machines ------------- diff --git a/tests/avocado/machine_sparc_leon3.py b/tests/avocado/machine_sparc_leon3.py deleted file mode 100644 index e61b223185..0000000000 --- a/tests/avocado/machine_sparc_leon3.py +++ /dev/null @@ -1,37 +0,0 @@ -# Functional test that boots a Leon3 machine and checks its serial console. -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern -from avocado import skip - - -class Leon3Machine(QemuSystemTest): - - timeout = 60 - - @skip("Test currently broken") - # A Window Underflow exception occurs before booting the kernel, - # and QEMU exit calling cpu_abort(), which makes this test to fail. - def test_leon3_helenos_uimage(self): - """ - :avocado: tags=arch:sparc - :avocado: tags=machine:leon3_generic - :avocado: tags=binfmt:uimage - """ - kernel_url = ('http://www.helenos.org/releases/' - 'HelenOS-0.6.0-sparc32-leon3.bin') - kernel_hash = 'a88c9cfdb8430c66650e5290a08765f9bf049a30' - kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path) - - self.vm.launch() - - wait_for_console_pattern(self, 'Copyright (c) 2001-2014 HelenOS project') - wait_for_console_pattern(self, 'Booting the kernel ...') From e8122a7118eb22ace9e60c91bfbf2d4bbfc6f15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 18 Jul 2024 10:45:11 +0100 Subject: [PATCH 03/16] gdbstub: Re-factor gdb command extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity reported a memory leak (CID 1549757) in this code and its admittedly rather clumsy handling of extending the command table. Instead of handing over a full array of the commands lets use the lighter weight GPtrArray and simply test for the presence of each entry as we go. This avoids complications of transferring ownership of arrays and keeps the final command entries as static entries in the target code. Cc: Akihiko Odaki Cc: Gustavo Bueno Romero Cc: Peter Maydell Reviewed-by: Gustavo Romero Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-4-alex.bennee@linaro.org> --- gdbstub/gdbstub.c | 141 +++++++++++++++++++++---------------- include/gdbstub/commands.h | 19 +++-- target/arm/gdbstub.c | 16 ++--- target/arm/gdbstub64.c | 11 ++- target/arm/internals.h | 4 +- 5 files changed, 105 insertions(+), 86 deletions(-) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index b9ad0a063e..b7be8e5a44 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -1614,18 +1614,21 @@ static void handle_query_thread_extra(GArray *params, void *user_ctx) gdb_put_strbuf(); } -static char *extended_qsupported_features; -void gdb_extend_qsupported_features(char *qsupported_features) -{ - /* - * We don't support different sets of CPU gdb features on different CPUs yet - * so assert the feature strings are the same on all CPUs, or is set only - * once (1 CPU). - */ - g_assert(extended_qsupported_features == NULL || - g_strcmp0(extended_qsupported_features, qsupported_features) == 0); - extended_qsupported_features = qsupported_features; +static char **extra_query_flags; + +void gdb_extend_qsupported_features(char *qflags) +{ + if (!extra_query_flags) { + extra_query_flags = g_new0(char *, 2); + extra_query_flags[0] = g_strdup(qflags); + } else if (!g_strv_contains((const gchar * const *) extra_query_flags, + qflags)) { + int len = g_strv_length(extra_query_flags); + extra_query_flags = g_realloc_n(extra_query_flags, len + 2, + sizeof(char *)); + extra_query_flags[len] = g_strdup(qflags); + } } static void handle_query_supported(GArray *params, void *user_ctx) @@ -1668,8 +1671,11 @@ static void handle_query_supported(GArray *params, void *user_ctx) g_string_append(gdbserver_state.str_buf, ";vContSupported+;multiprocess+"); - if (extended_qsupported_features) { - g_string_append(gdbserver_state.str_buf, extended_qsupported_features); + if (extra_query_flags) { + int extras = g_strv_length(extra_query_flags); + for (int i = 0; i < extras; i++) { + g_string_append(gdbserver_state.str_buf, extra_query_flags[i]); + } } gdb_put_strbuf(); @@ -1753,39 +1759,58 @@ static const GdbCmdParseEntry gdb_gen_query_set_common_table[] = { }, }; -/* Compares if a set of command parsers is equal to another set of parsers. */ -static bool cmp_cmds(GdbCmdParseEntry *c, GdbCmdParseEntry *d, int size) +/** + * extend_table() - extend one of the command tables + * @table: the command table to extend (or NULL) + * @extensions: a list of GdbCmdParseEntry pointers + * + * The entries themselves should be pointers to static const + * GdbCmdParseEntry entries. If the entry is already in the table we + * skip adding it again. + * + * Returns (a potentially freshly allocated) GPtrArray of GdbCmdParseEntry + */ +static GPtrArray *extend_table(GPtrArray *table, GPtrArray *extensions) { - for (int i = 0; i < size; i++) { - if (!(c[i].handler == d[i].handler && - g_strcmp0(c[i].cmd, d[i].cmd) == 0 && - c[i].cmd_startswith == d[i].cmd_startswith && - g_strcmp0(c[i].schema, d[i].schema) == 0)) { + if (!table) { + table = g_ptr_array_new(); + } - /* Sets are different. */ - return false; + for (int i = 0; i < extensions->len; i++) { + gpointer entry = g_ptr_array_index(extensions, i); + if (!g_ptr_array_find(table, entry, NULL)) { + g_ptr_array_add(table, entry); } } - /* Sets are equal, i.e. contain the same command parsers. */ - return true; + return table; } -static GdbCmdParseEntry *extended_query_table; -static int extended_query_table_size; -void gdb_extend_query_table(GdbCmdParseEntry *table, int size) +/** + * process_extended_table() - run through an extended command table + * @table: the command table to check + * @data: parameters + * + * returns true if the command was found and executed + */ +static bool process_extended_table(GPtrArray *table, const char *data) { - /* - * We don't support different sets of CPU gdb features on different CPUs yet - * so assert query table is the same on all CPUs, or is set only once - * (1 CPU). - */ - g_assert(extended_query_table == NULL || - (extended_query_table_size == size && - cmp_cmds(extended_query_table, table, size))); + for (int i = 0; i < table->len; i++) { + const GdbCmdParseEntry *entry = g_ptr_array_index(table, i); + if (process_string_cmd(data, entry, 1)) { + return true; + } + } + return false; +} - extended_query_table = table; - extended_query_table_size = size; + +/* Ptr to GdbCmdParseEntry */ +static GPtrArray *extended_query_table; + +void gdb_extend_query_table(GPtrArray *new_queries) +{ + extended_query_table = extend_table(extended_query_table, new_queries); } static const GdbCmdParseEntry gdb_gen_query_table[] = { @@ -1880,20 +1905,12 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = { #endif }; -static GdbCmdParseEntry *extended_set_table; -static int extended_set_table_size; -void gdb_extend_set_table(GdbCmdParseEntry *table, int size) -{ - /* - * We don't support different sets of CPU gdb features on different CPUs yet - * so assert set table is the same on all CPUs, or is set only once (1 CPU). - */ - g_assert(extended_set_table == NULL || - (extended_set_table_size == size && - cmp_cmds(extended_set_table, table, size))); +/* Ptr to GdbCmdParseEntry */ +static GPtrArray *extended_set_table; - extended_set_table = table; - extended_set_table_size = size; +void gdb_extend_set_table(GPtrArray *new_set) +{ + extended_set_table = extend_table(extended_set_table, new_set); } static const GdbCmdParseEntry gdb_gen_set_table[] = { @@ -1924,26 +1941,28 @@ static const GdbCmdParseEntry gdb_gen_set_table[] = { static void handle_gen_query(GArray *params, void *user_ctx) { + const char *data; + if (!params->len) { return; } - if (process_string_cmd(gdb_get_cmd_param(params, 0)->data, + data = gdb_get_cmd_param(params, 0)->data; + + if (process_string_cmd(data, gdb_gen_query_set_common_table, ARRAY_SIZE(gdb_gen_query_set_common_table))) { return; } - if (process_string_cmd(gdb_get_cmd_param(params, 0)->data, + if (process_string_cmd(data, gdb_gen_query_table, ARRAY_SIZE(gdb_gen_query_table))) { return; } if (extended_query_table && - process_string_cmd(gdb_get_cmd_param(params, 0)->data, - extended_query_table, - extended_query_table_size)) { + process_extended_table(extended_query_table, data)) { return; } @@ -1953,26 +1972,28 @@ static void handle_gen_query(GArray *params, void *user_ctx) static void handle_gen_set(GArray *params, void *user_ctx) { + const char *data; + if (!params->len) { return; } - if (process_string_cmd(gdb_get_cmd_param(params, 0)->data, + data = gdb_get_cmd_param(params, 0)->data; + + if (process_string_cmd(data, gdb_gen_query_set_common_table, ARRAY_SIZE(gdb_gen_query_set_common_table))) { return; } - if (process_string_cmd(gdb_get_cmd_param(params, 0)->data, + if (process_string_cmd(data, gdb_gen_set_table, ARRAY_SIZE(gdb_gen_set_table))) { return; } if (extended_set_table && - process_string_cmd(gdb_get_cmd_param(params, 0)->data, - extended_set_table, - extended_set_table_size)) { + process_extended_table(extended_set_table, data)) { return; } diff --git a/include/gdbstub/commands.h b/include/gdbstub/commands.h index f3058f9dda..40f0514fe9 100644 --- a/include/gdbstub/commands.h +++ b/include/gdbstub/commands.h @@ -74,23 +74,28 @@ int gdb_put_packet(const char *buf); /** * gdb_extend_query_table() - Extend query table. - * @table: The table with the additional query packet handlers. - * @size: The number of handlers to be added. + * @table: GPtrArray of GdbCmdParseEntry entries. + * + * The caller should free @table afterwards */ -void gdb_extend_query_table(GdbCmdParseEntry *table, int size); +void gdb_extend_query_table(GPtrArray *table); /** * gdb_extend_set_table() - Extend set table. - * @table: The table with the additional set packet handlers. - * @size: The number of handlers to be added. + * @table: GPtrArray of GdbCmdParseEntry entries. + * + * The caller should free @table afterwards */ -void gdb_extend_set_table(GdbCmdParseEntry *table, int size); +void gdb_extend_set_table(GPtrArray *table); /** * gdb_extend_qsupported_features() - Extend the qSupported features string. * @qsupported_features: The additional qSupported feature(s) string. The string * should start with a semicolon and, if there are more than one feature, the - * features should be separate by a semiocolon. + * features should be separate by a semicolon. + * + * The caller should free @qsupported_features afterwards if + * dynamically allocated. */ void gdb_extend_qsupported_features(char *qsupported_features); diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index c3a9b5eb1e..554b8736bb 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -477,11 +477,9 @@ static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs, void arm_cpu_register_gdb_commands(ARMCPU *cpu) { - GArray *query_table = - g_array_new(FALSE, FALSE, sizeof(GdbCmdParseEntry)); - GArray *set_table = - g_array_new(FALSE, FALSE, sizeof(GdbCmdParseEntry)); - GString *qsupported_features = g_string_new(NULL); + g_autoptr(GPtrArray) query_table = g_ptr_array_new(); + g_autoptr(GPtrArray) set_table = g_ptr_array_new(); + g_autoptr(GString) qsupported_features = g_string_new(NULL); if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { #ifdef TARGET_AARCH64 @@ -492,16 +490,12 @@ void arm_cpu_register_gdb_commands(ARMCPU *cpu) /* Set arch-specific handlers for 'q' commands. */ if (query_table->len) { - gdb_extend_query_table(&g_array_index(query_table, - GdbCmdParseEntry, 0), - query_table->len); + gdb_extend_query_table(query_table); } /* Set arch-specific handlers for 'Q' commands. */ if (set_table->len) { - gdb_extend_set_table(&g_array_index(set_table, - GdbCmdParseEntry, 0), - set_table->len); + gdb_extend_set_table(set_table); } /* Set arch-specific qSupported feature. */ diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index 2e2bc2700b..c8cef8cbc0 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -564,7 +564,7 @@ enum Command { NUM_CMDS }; -static GdbCmdParseEntry cmd_handler_table[NUM_CMDS] = { +static const GdbCmdParseEntry cmd_handler_table[NUM_CMDS] = { [qMemTags] = { .handler = handle_q_memtag, .cmd_startswith = true, @@ -590,17 +590,16 @@ static GdbCmdParseEntry cmd_handler_table[NUM_CMDS] = { #endif /* CONFIG_USER_ONLY */ void aarch64_cpu_register_gdb_commands(ARMCPU *cpu, GString *qsupported, - GArray *qtable, GArray *stable) + GPtrArray *qtable, GPtrArray *stable) { #ifdef CONFIG_USER_ONLY /* MTE */ if (cpu_isar_feature(aa64_mte, cpu)) { g_string_append(qsupported, ";memory-tagging+"); - g_array_append_val(qtable, cmd_handler_table[qMemTags]); - g_array_append_val(qtable, cmd_handler_table[qIsAddressTagged]); - - g_array_append_val(stable, cmd_handler_table[QMemTags]); + g_ptr_array_add(qtable, (gpointer) &cmd_handler_table[qMemTags]); + g_ptr_array_add(qtable, (gpointer) &cmd_handler_table[qIsAddressTagged]); + g_ptr_array_add(stable, (gpointer) &cmd_handler_table[QMemTags]); } #endif } diff --git a/target/arm/internals.h b/target/arm/internals.h index da22d04121..757b1fae92 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -359,8 +359,8 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); void arm_translate_init(void); void arm_cpu_register_gdb_commands(ARMCPU *cpu); -void aarch64_cpu_register_gdb_commands(ARMCPU *cpu, GString *, GArray *, - GArray *); +void aarch64_cpu_register_gdb_commands(ARMCPU *cpu, GString *, + GPtrArray *, GPtrArray *); void arm_restore_state_to_opc(CPUState *cs, const TranslationBlock *tb, From 58fc249d9ebd7c6ed979cbf039ccfa93d1bae2b9 Mon Sep 17 00:00:00 2001 From: Simon Hamelin Date: Thu, 18 Jul 2024 10:45:12 +0100 Subject: [PATCH 04/16] plugins/stoptrigger: TCG plugin to stop execution under conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new plugin allows to stop emulation using conditions on the emulation state. By setting this plugin arguments, it is possible to set an instruction count limit and/or trigger address(es) to stop at. The code returned at emulation exit can be customized. This plugin demonstrates how someone could stop QEMU execution. It could be used for research purposes to launch some code and deterministically stop it and understand where its execution flow went. Co-authored-by: Alexandre Iooss Signed-off-by: Simon Hamelin Signed-off-by: Alexandre Iooss Reviewed-by: Pierrick Bouvier Message-Id: <20240715081521.19122-2-simon.hamelin@grenoble-inp.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-5-alex.bennee@linaro.org> --- contrib/plugins/Makefile | 1 + contrib/plugins/stoptrigger.c | 151 ++++++++++++++++++++++++++++++++++ docs/devel/tcg-plugins.rst | 22 +++++ 3 files changed, 174 insertions(+) create mode 100644 contrib/plugins/stoptrigger.c diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile index 449ead1130..98a89d5c40 100644 --- a/contrib/plugins/Makefile +++ b/contrib/plugins/Makefile @@ -28,6 +28,7 @@ NAMES += hwprofile NAMES += cache NAMES += drcov NAMES += ips +NAMES += stoptrigger ifeq ($(CONFIG_WIN32),y) SO_SUFFIX := .dll diff --git a/contrib/plugins/stoptrigger.c b/contrib/plugins/stoptrigger.c new file mode 100644 index 0000000000..03ee22f4c6 --- /dev/null +++ b/contrib/plugins/stoptrigger.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2024, Simon Hamelin + * + * Stop execution once a given address is reached or if the + * count of executed instructions reached a specified limit + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include +#include +#include + +#include + +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; + +/* Scoreboard to track executed instructions count */ +typedef struct { + uint64_t insn_count; +} InstructionsCount; +static struct qemu_plugin_scoreboard *insn_count_sb; +static qemu_plugin_u64 insn_count; + +static uint64_t icount; +static int icount_exit_code; + +static bool exit_on_icount; +static bool exit_on_address; + +/* Map trigger addresses to exit code */ +static GHashTable *addrs_ht; + +static void exit_emulation(int return_code, char *message) +{ + qemu_plugin_outs(message); + g_free(message); + exit(return_code); +} + +static void exit_icount_reached(unsigned int cpu_index, void *udata) +{ + uint64_t insn_vaddr = GPOINTER_TO_UINT(udata); + 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); +} + +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)); + + 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_cond_cb( + insn, exit_icount_reached, QEMU_PLUGIN_CB_NO_REGS, + QEMU_PLUGIN_COND_EQ, insn_count, icount + 1, insn_vaddr); + } + + if (exit_on_address) { + if (g_hash_table_contains(addrs_ht, insn_vaddr)) { + /* Exit triggered by address */ + qemu_plugin_register_vcpu_insn_exec_cb( + insn, exit_address_reached, QEMU_PLUGIN_CB_NO_REGS, + insn_vaddr); + } + } + } +} + +static void plugin_exit(qemu_plugin_id_t id, void *p) +{ + g_hash_table_destroy(addrs_ht); + qemu_plugin_scoreboard_free(insn_count_sb); +} + +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); + + insn_count_sb = qemu_plugin_scoreboard_new(sizeof(InstructionsCount)); + insn_count = qemu_plugin_scoreboard_u64_in_struct( + insn_count_sb, InstructionsCount, insn_count); + + for (int i = 0; i < argc; i++) { + char *opt = argv[i]; + g_auto(GStrv) tokens = g_strsplit(opt, "=", 2); + if (g_strcmp0(tokens[0], "icount") == 0) { + g_auto(GStrv) icount_tokens = g_strsplit(tokens[1], ":", 2); + icount = g_ascii_strtoull(icount_tokens[0], NULL, 0); + if (icount < 1 || g_strrstr(icount_tokens[0], "-") != NULL) { + fprintf(stderr, + "icount parsing failed: '%s' must be a positive " + "integer\n", + icount_tokens[0]); + return -1; + } + if (icount_tokens[1]) { + icount_exit_code = g_ascii_strtoull(icount_tokens[1], NULL, 0); + } + 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; + if (addr_tokens[1]) { + 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)); + exit_on_address = true; + } else { + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; + } + } + + if (!exit_on_icount && !exit_on_address) { + fprintf(stderr, "'icount' or 'addr' argument missing\n"); + return -1; + } + + /* Register translation block and exit callbacks */ + qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); + qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); + + return 0; +} diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index f7d7b9e3a4..954623f9bf 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -642,6 +642,28 @@ The plugin has a number of arguments, all of them are optional: configuration arguments implies ``l2=on``. (default: N = 2097152 (2MB), B = 64, A = 16) +- contrib/plugins/stoptrigger.c + +The stoptrigger plugin allows to setup triggers to stop emulation. +It can be used for research purposes to launch some code and precisely stop it +and understand where its execution flow went. + +Two types of triggers can be configured: a count of instructions to stop at, +or an address to stop at. Multiple triggers can be set at once. + +By default, QEMU will exit with return code 0. A custom return code can be +configured for each trigger using ``:CODE`` syntax. + +For example, to stop at the 20-th instruction with return code 41, at address +0xd4 with return code 0 or at address 0xd8 with return code 42:: + + $ qemu-system-aarch64 $(QEMU_ARGS) \ + -plugin ./contrib/plugins/libstoptrigger.so,icount=20:41,addr=0xd4,addr=0xd8:42 -d plugin + +The plugin will log the reason of exit, for example:: + + 0xd4 reached, exiting + Plugin API ========== From 94ae227e15bd5ede18a92947412ef47c2b89e269 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Thu, 18 Jul 2024 10:45:13 +0100 Subject: [PATCH 05/16] plugins: fix mem callback array size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit data was correctly copied, but size of array was not set (g_array_sized_new only reserves memory, but does not set size). As a result, callbacks were not called for code path relying on plugin_register_vcpu_mem_cb(). Found when trying to trigger mem access callbacks for atomic instructions. Reviewed-by: Xingtao Yao Reviewed-by: Richard Henderson Signed-off-by: Pierrick Bouvier Reviewed-by: Alex Bennée Signed-off-by: Alex Bennée Message-Id: <20240706191335.878142-2-pierrick.bouvier@linaro.org> Message-Id: <20240718094523.1198645-6-alex.bennee@linaro.org> --- accel/tcg/plugin-gen.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index b6bae32b99..ec89a085b4 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -85,8 +85,7 @@ static void gen_enable_mem_helper(struct qemu_plugin_tb *ptb, len = insn->mem_cbs->len; arr = g_array_sized_new(false, false, sizeof(struct qemu_plugin_dyn_cb), len); - memcpy(arr->data, insn->mem_cbs->data, - len * sizeof(struct qemu_plugin_dyn_cb)); + g_array_append_vals(arr, insn->mem_cbs->data, len); qemu_plugin_add_dyn_cb_arr(arr); tcg_gen_st_ptr(tcg_constant_ptr((intptr_t)arr), tcg_env, From 2d4f2c8cde67820ce3f6138313fa2d6455681384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 18 Jul 2024 10:45:14 +0100 Subject: [PATCH 06/16] tests/plugins: use qemu_plugin_outs for inline stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using bare printf's in plugins is perfectly acceptable but they do rather mess up the output of "make check-tcg". Convert the printfs to use g_string and then output with the plugin output helper which will already be captured to .pout files by the test harness. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-7-alex.bennee@linaro.org> --- tests/plugin/inline.c | 58 ++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/tests/plugin/inline.c b/tests/plugin/inline.c index cd63827b7d..73dde99578 100644 --- a/tests/plugin/inline.c +++ b/tests/plugin/inline.c @@ -71,10 +71,12 @@ static void stats_insn(void) const uint64_t cond_track_left = qemu_plugin_u64_sum(insn_cond_track_count); const uint64_t conditional = cond_num_trigger * cond_trigger_limit + cond_track_left; - printf("insn: %" PRIu64 "\n", expected); - printf("insn: %" PRIu64 " (per vcpu)\n", per_vcpu); - printf("insn: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); - printf("insn: %" PRIu64 " (cond cb)\n", conditional); + g_autoptr(GString) stats = g_string_new(""); + g_string_append_printf(stats, "insn: %" PRIu64 "\n", expected); + g_string_append_printf(stats, "insn: %" PRIu64 " (per vcpu)\n", per_vcpu); + g_string_append_printf(stats, "insn: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); + g_string_append_printf(stats, "insn: %" PRIu64 " (cond cb)\n", conditional); + qemu_plugin_outs(stats->str); g_assert(expected > 0); g_assert(per_vcpu == expected); g_assert(inl_per_vcpu == expected); @@ -91,10 +93,12 @@ static void stats_tb(void) const uint64_t cond_track_left = qemu_plugin_u64_sum(tb_cond_track_count); const uint64_t conditional = cond_num_trigger * cond_trigger_limit + cond_track_left; - printf("tb: %" PRIu64 "\n", expected); - printf("tb: %" PRIu64 " (per vcpu)\n", per_vcpu); - printf("tb: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); - printf("tb: %" PRIu64 " (conditional cb)\n", conditional); + g_autoptr(GString) stats = g_string_new(""); + g_string_append_printf(stats, "tb: %" PRIu64 "\n", expected); + g_string_append_printf(stats, "tb: %" PRIu64 " (per vcpu)\n", per_vcpu); + g_string_append_printf(stats, "tb: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); + g_string_append_printf(stats, "tb: %" PRIu64 " (conditional cb)\n", conditional); + qemu_plugin_outs(stats->str); g_assert(expected > 0); g_assert(per_vcpu == expected); g_assert(inl_per_vcpu == expected); @@ -107,9 +111,11 @@ static void stats_mem(void) const uint64_t per_vcpu = qemu_plugin_u64_sum(count_mem); const uint64_t inl_per_vcpu = qemu_plugin_u64_sum(count_mem_inline); - printf("mem: %" PRIu64 "\n", expected); - printf("mem: %" PRIu64 " (per vcpu)\n", per_vcpu); - printf("mem: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); + g_autoptr(GString) stats = g_string_new(""); + g_string_append_printf(stats, "mem: %" PRIu64 "\n", expected); + g_string_append_printf(stats, "mem: %" PRIu64 " (per vcpu)\n", per_vcpu); + g_string_append_printf(stats, "mem: %" PRIu64 " (per vcpu inline)\n", inl_per_vcpu); + qemu_plugin_outs(stats->str); g_assert(expected > 0); g_assert(per_vcpu == expected); g_assert(inl_per_vcpu == expected); @@ -118,6 +124,7 @@ static void stats_mem(void) static void plugin_exit(qemu_plugin_id_t id, void *udata) { const unsigned int num_cpus = qemu_plugin_num_vcpus(); + g_autoptr(GString) stats = g_string_new(""); g_assert(num_cpus == max_cpu_index + 1); for (int i = 0; i < num_cpus ; ++i) { @@ -135,20 +142,21 @@ static void plugin_exit(qemu_plugin_id_t id, void *udata) qemu_plugin_u64_get(insn_cond_num_trigger, i); const uint64_t insn_cond_left = qemu_plugin_u64_get(insn_cond_track_count, i); - printf("cpu %d: tb (%" PRIu64 ", %" PRIu64 - ", %" PRIu64 " * %" PRIu64 " + %" PRIu64 - ") | " - "insn (%" PRIu64 ", %" PRIu64 - ", %" PRIu64 " * %" PRIu64 " + %" PRIu64 - ") | " - "mem (%" PRIu64 ", %" PRIu64 ")" - "\n", - i, - tb, tb_inline, - tb_cond_trigger, cond_trigger_limit, tb_cond_left, - insn, insn_inline, - insn_cond_trigger, cond_trigger_limit, insn_cond_left, - mem, mem_inline); + g_string_printf(stats, "cpu %d: tb (%" PRIu64 ", %" PRIu64 + ", %" PRIu64 " * %" PRIu64 " + %" PRIu64 + ") | " + "insn (%" PRIu64 ", %" PRIu64 + ", %" PRIu64 " * %" PRIu64 " + %" PRIu64 + ") | " + "mem (%" PRIu64 ", %" PRIu64 ")" + "\n", + i, + tb, tb_inline, + tb_cond_trigger, cond_trigger_limit, tb_cond_left, + insn, insn_inline, + insn_cond_trigger, cond_trigger_limit, insn_cond_left, + mem, mem_inline); + qemu_plugin_outs(stats->str); g_assert(tb == tb_inline); g_assert(insn == insn_inline); g_assert(mem == mem_inline); From 8d073d48b7eae34dad6ec71d6d0ef418d931602b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 18 Jul 2024 10:45:15 +0100 Subject: [PATCH 07/16] plugins/execlog.c: correct dump of registers values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Register values are dumped as 'sz' chunks of two nibbles in the execlog plugin, sz was 1 too big. Signed-off-by: Frédéric Pétrot Reviewed-by: Pierrick Bouvier Message-Id: <20240620083805.73603-1-frederic.petrot@univ-grenoble-alpes.fr> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-8-alex.bennee@linaro.org> --- contrib/plugins/execlog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index 371db97eb1..1c1601cc0b 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -101,7 +101,7 @@ static void insn_check_regs(CPU *cpu) GByteArray *temp = reg->last; g_string_append_printf(cpu->last_exec, ", %s -> 0x", reg->name); /* TODO: handle BE properly */ - for (int i = sz; i >= 0; i--) { + for (int i = sz - 1; i >= 0; i--) { g_string_append_printf(cpu->last_exec, "%02x", reg->new->data[i]); } From f961773ce13d61f56506dc4964e28f0594c7920f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:16 +0100 Subject: [PATCH 08/16] semihosting: Include missing 'gdbstub/syscalls.h' header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "semihosting/syscalls.h" requires definitions from "gdbstub/syscalls.h", include it in order to avoid: include/semihosting/syscalls.h:23:38: error: unknown type name 'gdb_syscall_complete_cb' void semihost_sys_open(CPUState *cs, gdb_syscall_complete_cb complete, ^ Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20240717105723.58965-2-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-9-alex.bennee@linaro.org> --- include/semihosting/syscalls.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/semihosting/syscalls.h b/include/semihosting/syscalls.h index 3a5ec229eb..b5937c619a 100644 --- a/include/semihosting/syscalls.h +++ b/include/semihosting/syscalls.h @@ -9,6 +9,8 @@ #ifndef SEMIHOSTING_SYSCALLS_H #define SEMIHOSTING_SYSCALLS_H +#include "gdbstub/syscalls.h" + /* * Argument loading from the guest is performed by the caller; * results are returned via the 'complete' callback. From bf9ab9d1317e9e27e27d63e94c2e13db2319e2c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:17 +0100 Subject: [PATCH 09/16] target/m68k: Add semihosting stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the SEMIHOSTING feature is optional, we need a stub to link when it is disabled. Suggested-by: Paolo Bonzini Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20240717105723.58965-3-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-10-alex.bennee@linaro.org> --- target/m68k/meson.build | 5 ++++- target/m68k/semihosting-stub.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 target/m68k/semihosting-stub.c diff --git a/target/m68k/meson.build b/target/m68k/meson.build index 8d3f9ce288..4d213daaf6 100644 --- a/target/m68k/meson.build +++ b/target/m68k/meson.build @@ -11,9 +11,12 @@ m68k_ss.add(files( m68k_system_ss = ss.source_set() m68k_system_ss.add(files( - 'm68k-semi.c', 'monitor.c' )) +m68k_system_ss.add(when: ['CONFIG_SEMIHOSTING'], + if_true: files('m68k-semi.c'), + if_false: files('semihosting-stub.c') +) target_arch += {'m68k': m68k_ss} target_system_arch += {'m68k': m68k_system_ss} diff --git a/target/m68k/semihosting-stub.c b/target/m68k/semihosting-stub.c new file mode 100644 index 0000000000..d6a5965e29 --- /dev/null +++ b/target/m68k/semihosting-stub.c @@ -0,0 +1,15 @@ +/* + * m68k/ColdFire semihosting stub + * + * SPDX-FileContributor: Philippe Mathieu-Daudé + * SPDX-FileCopyrightText: 2024 Linaro Ltd. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "cpu.h" + +void do_m68k_semihosting(CPUM68KState *env, int nr) +{ + g_assert_not_reached(); +} From fca2ffcb0b1292ef5dc29e2d1a33e30de9876da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:18 +0100 Subject: [PATCH 10/16] target/mips: Add semihosting stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the SEMIHOSTING feature is optional, we need a stub to link when it is disabled. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20240717105723.58965-4-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-11-alex.bennee@linaro.org> --- target/mips/tcg/sysemu/meson.build | 6 ++++-- target/mips/tcg/sysemu/semihosting-stub.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 target/mips/tcg/sysemu/semihosting-stub.c diff --git a/target/mips/tcg/sysemu/meson.build b/target/mips/tcg/sysemu/meson.build index ec665a4b1e..911341ac37 100644 --- a/target/mips/tcg/sysemu/meson.build +++ b/target/mips/tcg/sysemu/meson.build @@ -1,10 +1,12 @@ mips_system_ss.add(files( 'cp0_helper.c', - 'mips-semi.c', 'special_helper.c', 'tlb_helper.c', )) - +mips_system_ss.add(when: ['CONFIG_SEMIHOSTING'], + if_true: files('mips-semi.c'), + if_false: files('semihosting-stub.c') +) mips_system_ss.add(when: 'TARGET_MIPS64', if_true: files( 'lcsr_helper.c', )) diff --git a/target/mips/tcg/sysemu/semihosting-stub.c b/target/mips/tcg/sysemu/semihosting-stub.c new file mode 100644 index 0000000000..7ae27d746f --- /dev/null +++ b/target/mips/tcg/sysemu/semihosting-stub.c @@ -0,0 +1,15 @@ +/* + * MIPS semihosting stub + * + * SPDX-FileContributor: Philippe Mathieu-Daudé + * SPDX-FileCopyrightText: 2024 Linaro Ltd. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "internal.h" + +void mips_semihosting(CPUMIPSState *env) +{ + g_assert_not_reached(); +} From 099505b375aae2ab7436e14238826f6a06535334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:19 +0100 Subject: [PATCH 11/16] target/m68k: Restrict semihosting to TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The semihosting feature depends on TCG (due to the probe_access API access). Although TCG is the single accelerator currently available for the m68k target, use the Kconfig "imply" directive which is more correct (if we were to support a different accel). Reported-by: Anton Johansson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20240717105723.58965-5-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-12-alex.bennee@linaro.org> --- target/m68k/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/m68k/Kconfig b/target/m68k/Kconfig index 9eae71486f..23aae24ebe 100644 --- a/target/m68k/Kconfig +++ b/target/m68k/Kconfig @@ -1,3 +1,3 @@ config M68K bool - select SEMIHOSTING + imply SEMIHOSTING if TCG From 75cdcc7a2c75a0f22040be535572261bf4ee7240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:20 +0100 Subject: [PATCH 12/16] target/mips: Restrict semihosting to TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Semihosting currently uses the TCG probe_access API. To prepare for encoding the TCG dependency in Kconfig, do not enable it unless TCG is available. Suggested-by: Paolo Bonzini Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Anton Johansson Message-Id: <20240717105723.58965-6-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-13-alex.bennee@linaro.org> --- target/mips/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/Kconfig b/target/mips/Kconfig index eb19c94c7d..876048b150 100644 --- a/target/mips/Kconfig +++ b/target/mips/Kconfig @@ -1,6 +1,6 @@ config MIPS bool - select SEMIHOSTING + imply SEMIHOSTING if TCG config MIPS64 bool From 10425887ba54241be1ce97f8935fc320332b531c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:21 +0100 Subject: [PATCH 13/16] target/riscv: Restrict semihosting to TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Semihosting currently uses the TCG probe_access API. To prepare for encoding the TCG dependency in Kconfig, do not enable it unless TCG is available. Suggested-by: Paolo Bonzini Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Anton Johansson Message-Id: <20240717105723.58965-7-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-14-alex.bennee@linaro.org> --- target/riscv/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/Kconfig b/target/riscv/Kconfig index 5f30df22f2..c332616d36 100644 --- a/target/riscv/Kconfig +++ b/target/riscv/Kconfig @@ -1,9 +1,9 @@ config RISCV32 bool - select ARM_COMPATIBLE_SEMIHOSTING # for do_common_semihosting() + imply ARM_COMPATIBLE_SEMIHOSTING if TCG select DEVICE_TREE # needed by boot.c config RISCV64 bool - select ARM_COMPATIBLE_SEMIHOSTING # for do_common_semihosting() + imply ARM_COMPATIBLE_SEMIHOSTING if TCG select DEVICE_TREE # needed by boot.c From 41b37a178bafeaa23ca2121bd024073b1c751879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:22 +0100 Subject: [PATCH 14/16] target/xtensa: Restrict semihosting to TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The semihosting feature depends on TCG (due to the probe_access API access). Although TCG is the single accelerator currently available for the xtensa target, use the Kconfig "imply" directive which is more correct (if we were to support a different accel). Reported-by: Anton Johansson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20240717105723.58965-8-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-15-alex.bennee@linaro.org> --- target/xtensa/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/xtensa/Kconfig b/target/xtensa/Kconfig index 5e46049262..e8c2598c4d 100644 --- a/target/xtensa/Kconfig +++ b/target/xtensa/Kconfig @@ -1,3 +1,3 @@ config XTENSA bool - select SEMIHOSTING + imply SEMIHOSTING if TCG From ddd1731385442db6d09d37157158c52487eda1f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 18 Jul 2024 10:45:23 +0100 Subject: [PATCH 15/16] semihosting: Restrict to TCG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Semihosting currently uses the TCG probe_access API. It is pointless to have it in the binary when TCG isn't. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20240717105723.58965-9-philmd@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20240718094523.1198645-16-alex.bennee@linaro.org> --- semihosting/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/semihosting/Kconfig b/semihosting/Kconfig index eaf3a20ef5..fbe6ac87f9 100644 --- a/semihosting/Kconfig +++ b/semihosting/Kconfig @@ -1,6 +1,7 @@ config SEMIHOSTING bool + depends on TCG config ARM_COMPATIBLE_SEMIHOSTING bool From c135d5eaafe7aa2533da663d8e5a34a424b71eb9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 19 Jul 2024 10:41:43 +1000 Subject: [PATCH 16/16] tests/tcg/aarch64: Fix test-mte.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python 3.12 warns: TEST gdbstub MTE support on aarch64 /home/rth/qemu/src/tests/tcg/aarch64/gdbstub/test-mte.py:21: SyntaxWarning: invalid escape sequence '\(' PATTERN_0 = "Memory tags for address 0x[0-9a-f]+ match \(0x[0-9a-f]+\)." Double up the \ to pass one through to the pattern. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Pierrick Bouvier Message-Id: <20240719004143.1319260-1-richard.henderson@linaro.org> Signed-off-by: Alex Bennée --- tests/tcg/aarch64/gdbstub/test-mte.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tcg/aarch64/gdbstub/test-mte.py b/tests/tcg/aarch64/gdbstub/test-mte.py index 2db0663c1a..66f9c25f8a 100644 --- a/tests/tcg/aarch64/gdbstub/test-mte.py +++ b/tests/tcg/aarch64/gdbstub/test-mte.py @@ -18,7 +18,7 @@ import re from test_gdbstub import main, report -PATTERN_0 = "Memory tags for address 0x[0-9a-f]+ match \(0x[0-9a-f]+\)." +PATTERN_0 = "Memory tags for address 0x[0-9a-f]+ match \\(0x[0-9a-f]+\\)." PATTERN_1 = ".*(0x[0-9a-f]+)"