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-----

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>
This commit is contained in:
Richard Henderson 2024-07-23 12:15:11 +10:00
commit 26b09663a9
27 changed files with 370 additions and 170 deletions

View File

@ -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'

View File

@ -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
-------------

View File

@ -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,

View File

@ -28,6 +28,7 @@ NAMES += hwprofile
NAMES += cache
NAMES += drcov
NAMES += ips
NAMES += stoptrigger
ifeq ($(CONFIG_WIN32),y)
SO_SUFFIX := .dll

View File

@ -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]);
}

View File

@ -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;
}

View File

@ -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
==========

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -1,6 +1,7 @@
config SEMIHOSTING
bool
depends on TCG
config ARM_COMPATIBLE_SEMIHOSTING
bool

View File

@ -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. */

View File

@ -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
}

View File

@ -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,

View File

@ -1,3 +1,3 @@
config M68K
bool
select SEMIHOSTING
imply SEMIHOSTING if TCG

View File

@ -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}

View File

@ -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();
}

View File

@ -1,6 +1,6 @@
config MIPS
bool
select SEMIHOSTING
imply SEMIHOSTING if TCG
config MIPS64
bool

View File

@ -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',
))

View File

@ -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();
}

View File

@ -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

View File

@ -1,3 +1,3 @@
config XTENSA
bool
select SEMIHOSTING
imply SEMIHOSTING if TCG

View File

@ -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 ...')

@ -1 +1 @@
Subproject commit 0e9490cebc726ef772b6c9e27dac32e7ae99f9b2
Subproject commit 789b4601bce4e01f43fdb6ad4ce5ab4e46674440

View File

@ -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);

View File

@ -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]+)"

View File

@ -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",