diff options
author | 2024-07-23 12:15:11 +1000 | |
---|---|---|
committer | 2024-07-23 12:15:11 +1000 | |
commit | 26b09663a9c1a04202ab089bd34230e08c44ece7 (patch) | |
tree | 399944ac076c5e5c405d0aed1a06ba3e518f32f2 | |
parent | Merge tag 'pull-request-2024-07-22' of https://gitlab.com/thuth/qemu into staging (diff) | |
parent | tests/tcg/aarch64: Fix test-mte.py (diff) | |
download | qemu-26b09663a9c1a04202ab089bd34230e08c44ece7.tar.xz qemu-26b09663a9c1a04202ab089bd34230e08c44ece7.zip |
Merge tag 'pull-maintainer-9.1-rc0-230724-1' of https://gitlab.com/stsquad/qemu into staging
Maintainer updates for testing, gdbstub, semihosting, plugins
- bump python in *BSD images via libvirt-ci
- remove old unused Leon3 Avocado test
- re-factor gdb command extension
- add stoptrigger plugin to contrib
- ensure plugin mem callbacks properly sized
- reduce check-tcg noise of inline plugin test
- fix register dumping in execlog plugin
- restrict semihosting to TCG builds
- fix regex in MTE test
# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmae5OcACgkQ+9DbCVqe
# KkR8cgf/eM2Sm7EG7zIQ8SbY53DS07ls6uT7Mfn4374GEmj4Cy1I+WNoLGM5vq1r
# qWAC9q2LgJVMQoWJA6Fi3SCKiylBp3/jIdJ7CWN5qj/NmePHSV3EisQXf2qOWWL9
# qOX2hJI7IIYNI2v3IvCzN/fB8F8U60iXERFHRypBH2p6Mz+EGMC3CEhesOEUta6o
# 2IMkRW8MoDv9x4B+FnNYav6CfqZjhRenu1CGgVGvWYRds2QDVNB/14kOunmBuwSs
# gPb7AhhnpobDYVxMarlJNPMbOdFjtDkYCajCNW7ffLcl+OjhoVR6cJcFpbOMv4kZ
# 8Nok8aDjUDWwUbmU0rBynca+1k8OTg==
# =TjRc
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 23 Jul 2024 09:01:59 AM AEST
# gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
* tag 'pull-maintainer-9.1-rc0-230724-1' of https://gitlab.com/stsquad/qemu:
tests/tcg/aarch64: Fix test-mte.py
semihosting: Restrict to TCG
target/xtensa: Restrict semihosting to TCG
target/riscv: Restrict semihosting to TCG
target/mips: Restrict semihosting to TCG
target/m68k: Restrict semihosting to TCG
target/mips: Add semihosting stub
target/m68k: Add semihosting stub
semihosting: Include missing 'gdbstub/syscalls.h' header
plugins/execlog.c: correct dump of registers values
tests/plugins: use qemu_plugin_outs for inline stats
plugins: fix mem callback array size
plugins/stoptrigger: TCG plugin to stop execution under conditions
gdbstub: Re-factor gdb command extensions
tests/avocado: Remove non-working sparc leon3 test
testing: bump to latest libvirt-ci
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
27 files changed, 369 insertions, 169 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/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/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, 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/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]); } 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 <simon.hamelin@grenoble-inp.org> + * + * 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 <assert.h> +#include <glib.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> + +#include <qemu-plugin.h> + +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 ========== 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/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. 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 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, 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 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é <philmd@linaro.org> + * 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(); +} 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 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é <philmd@linaro.org> + * 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(); +} 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 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 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é <f4bug@amsat.org> -# -# 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 ...') diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci -Subproject 0e9490cebc726ef772b6c9e27dac32e7ae99f9b +Subproject 789b4601bce4e01f43fdb6ad4ce5ab4e4667444 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); 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]+)" 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", |