mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-maintainer-july24-050724-1' of https://gitlab.com/stsquad/qemu into staging
Updates for testing, plugins, gdbstub - restore some 32 bit host builds and testing - move some physmem tracepoint definitions - use --userns keep-id for podman builds - cleanup check-tcg compiler flag checking for Arm - fix some casting in fcvt test - tweak check-tcg inline asm for clang - suppress some invalid clang warnings - disable KVM for the TCI builds - improve the insn tracking plugin - cleanups to the lockstep plugin - free plugin data on cpu finalise - assert cpu->index assigned - move qemu_plugin_vcpu_init__async into plugin code - add support for dynamic gdb command tables - allow targets to extend gdb capabilities - enable user-mode MTE support # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmaH3bEACgkQ+9DbCVqe # KkTnvwf9HS68sTICEJqBfY663hjcfdFGsSV/h3q7SN3fhKm/3JHGNK+kumgqdnaC # ykd7tx0AtBGgKm83B7G6MPywsVMIosMeV3mFeJTVHhKsFwGNjSiGkr3j4R2qxjFt # nYQ977FqBKyhvhSplR2wwhwi+JpuGWFGlnQTvdF2Z7ni4YCDFcbl4eiMyGwsjbWm # 0VBP+wCSSMIIbS9Qb7DrhZlfu0+wKZK/q0FLzVVofcLSXGou+Mse/qhtG+yAU/FI # qqqV+7J4PU9E4BqFaklxyRtBrpXNDgpo77pu6ZR7oDXD7HNMuIAuEIlkxMJjarNM # xN64WOOzw15R2RMVyXdYx6ccxWft2Q== # =9Gmk # -----END PGP SIGNATURE----- # gpg: Signature made Fri 05 Jul 2024 04:49:05 AM PDT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] * tag 'pull-maintainer-july24-050724-1' of https://gitlab.com/stsquad/qemu: (40 commits) tests/tcg/aarch64: Add MTE gdbstub tests gdbstub: Add support for MTE in user mode gdbstub: Use true to set cmd_startswith gdbstub: Pass CPU context to command handler gdbstub: Make hex conversion function non-internal target/arm: Factor out code for setting MTE TCF0 field target/arm: Make some MTE helpers widely available target/arm: Fix exception case in allocation_tag_mem_probe gdbstub: Add support for target-specific stubs gdbstub: Move GdbCmdParseEntry into a new header file gdbstub: Clean up process_string_cmd accel/tcg: Move qemu_plugin_vcpu_init__async() to plugins/ plugins: Free CPUPluginState before destroying vCPU state plugins: Ensure vCPU index is assigned in init/exit hooks plugins/lockstep: clean-up output plugins/lockstep: mention the one-insn-per-tb option plugins/lockstep: make mixed-mode safe plugins/lockstep: preserve sock_path test/plugins: preserve the instruction record over translations test/plugin: make insn plugin less noisy by default ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -635,7 +635,7 @@ build-tci:
|
||||
- TARGETS="aarch64 arm hppa m68k microblaze ppc64 s390x x86_64"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-tcg-interpreter --disable-docs --disable-gtk --disable-vnc
|
||||
- ../configure --enable-tcg-interpreter --disable-kvm --disable-docs --disable-gtk --disable-vnc
|
||||
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
|
||||
|| { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make -j"$JOBS"
|
||||
|
||||
@@ -37,6 +37,17 @@ cross-arm64-kvm-only:
|
||||
IMAGE: debian-arm64-cross
|
||||
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
|
||||
|
||||
cross-i686-system:
|
||||
extends:
|
||||
- .cross_system_build_job
|
||||
- .cross_test_artifacts
|
||||
needs:
|
||||
job: i686-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-i686-cross
|
||||
EXTRA_CONFIGURE_OPTS: --disable-kvm
|
||||
MAKE_CHECK_ARGS: check-qtest
|
||||
|
||||
cross-i686-user:
|
||||
extends:
|
||||
- .cross_user_build_job
|
||||
@@ -57,7 +68,7 @@ cross-i686-tci:
|
||||
variables:
|
||||
IMAGE: debian-i686-cross
|
||||
ACCEL: tcg-interpreter
|
||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins
|
||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins --disable-kvm
|
||||
MAKE_CHECK_ARGS: check check-tcg
|
||||
|
||||
cross-mipsel-system:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/aarch64-pauth.xml
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/aarch64-pauth.xml gdb-xml/aarch64-mte.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
||||
@@ -1673,6 +1673,10 @@ for target in $target_list; do
|
||||
echo "GDB=$gdb_bin" >> $config_target_mak
|
||||
fi
|
||||
|
||||
if test "${arch}" = "aarch64" && version_ge ${gdb_version##* } 15.0; then
|
||||
echo "GDB_HAS_MTE=y" >> $config_target_mak
|
||||
fi
|
||||
|
||||
echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> Makefile.prereqs
|
||||
tcg_tests_targets="$tcg_tests_targets $target"
|
||||
fi
|
||||
|
||||
+12
-11
@@ -14,7 +14,8 @@
|
||||
* particular run may execute the exact same sequence of blocks. An
|
||||
* asynchronous event (for example X11 graphics update) may cause a
|
||||
* block to end early and a new partial block to start. This means
|
||||
* serial only test cases are a better bet. -d nochain may also help.
|
||||
* serial only test cases are a better bet. -d nochain may also help
|
||||
* as well as -accel tcg,one-insn-per-tb=on
|
||||
*
|
||||
* This code is not thread safe!
|
||||
*
|
||||
@@ -57,7 +58,7 @@ typedef struct {
|
||||
/* The execution state we compare */
|
||||
typedef struct {
|
||||
uint64_t pc;
|
||||
unsigned long insn_count;
|
||||
uint64_t insn_count;
|
||||
} ExecState;
|
||||
|
||||
typedef struct {
|
||||
@@ -134,10 +135,13 @@ static void report_divergance(ExecState *us, ExecState *them)
|
||||
|
||||
/* Output short log entry of going out of sync... */
|
||||
if (verbose || divrec.distance == 1 || diverged) {
|
||||
g_string_printf(out,
|
||||
"@ 0x%016" PRIx64 " vs 0x%016" PRIx64
|
||||
g_string_printf(out, "@ "
|
||||
"0x%016" PRIx64 " (%" PRId64 ") vs "
|
||||
"0x%016" PRIx64 " (%" PRId64 ")"
|
||||
" (%d/%d since last)\n",
|
||||
us->pc, them->pc, g_slist_length(divergence_log),
|
||||
us->pc, us->insn_count,
|
||||
them->pc, them->insn_count,
|
||||
g_slist_length(divergence_log),
|
||||
divrec.distance);
|
||||
qemu_plugin_outs(out->str);
|
||||
}
|
||||
@@ -146,10 +150,7 @@ static void report_divergance(ExecState *us, ExecState *them)
|
||||
int i;
|
||||
GSList *entry;
|
||||
|
||||
g_string_printf(out,
|
||||
"Δ insn_count @ 0x%016" PRIx64
|
||||
" (%ld) vs 0x%016" PRIx64 " (%ld)\n",
|
||||
us->pc, us->insn_count, them->pc, them->insn_count);
|
||||
g_string_printf(out, "Δ too high, we have diverged, previous insns\n");
|
||||
|
||||
for (entry = log, i = 0;
|
||||
g_slist_next(entry) && i < 5;
|
||||
@@ -162,7 +163,7 @@ static void report_divergance(ExecState *us, ExecState *them)
|
||||
prev->insn_count);
|
||||
}
|
||||
qemu_plugin_outs(out->str);
|
||||
qemu_plugin_outs("too much divergence... giving up.");
|
||||
qemu_plugin_outs("giving up\n");
|
||||
qemu_plugin_uninstall(our_id, plugin_cleanup);
|
||||
}
|
||||
}
|
||||
@@ -347,7 +348,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
|
||||
return -1;
|
||||
}
|
||||
} else if (g_strcmp0(tokens[0], "sockpath") == 0) {
|
||||
sock_path = tokens[1];
|
||||
sock_path = g_strdup(tokens[1]);
|
||||
} else {
|
||||
fprintf(stderr, "option parsing failed: %s\n", p);
|
||||
return -1;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.aarch64.mte">
|
||||
<reg name="tag_ctl" bitsize="64" type="uint64" group="system" save-restore="no"/>
|
||||
</feature>
|
||||
+200
-141
File diff suppressed because it is too large
Load Diff
@@ -106,9 +106,7 @@ static inline int tohex(int v)
|
||||
*/
|
||||
|
||||
void gdb_put_strbuf(void);
|
||||
int gdb_put_packet(const char *buf);
|
||||
int gdb_put_packet_binary(const char *buf, int len, bool dump);
|
||||
void gdb_hextomem(GByteArray *mem, const char *buf, int len);
|
||||
void gdb_memtohex(GString *buf, const uint8_t *mem, int len);
|
||||
void gdb_memtox(GString *buf, const char *mem, int len);
|
||||
void gdb_read_byte(uint8_t ch);
|
||||
@@ -166,27 +164,6 @@ void gdb_put_buffer(const uint8_t *buf, int len);
|
||||
*/
|
||||
void gdb_init_gdbserver_state(void);
|
||||
|
||||
typedef enum GDBThreadIdKind {
|
||||
GDB_ONE_THREAD = 0,
|
||||
GDB_ALL_THREADS, /* One process, all threads */
|
||||
GDB_ALL_PROCESSES,
|
||||
GDB_READ_THREAD_ERR
|
||||
} GDBThreadIdKind;
|
||||
|
||||
typedef union GdbCmdVariant {
|
||||
const char *data;
|
||||
uint8_t opcode;
|
||||
unsigned long val_ul;
|
||||
unsigned long long val_ull;
|
||||
struct {
|
||||
GDBThreadIdKind kind;
|
||||
uint32_t pid;
|
||||
uint32_t tid;
|
||||
} thread_id;
|
||||
} GdbCmdVariant;
|
||||
|
||||
#define get_param(p, i) (&g_array_index(p, GdbCmdVariant, i))
|
||||
|
||||
void gdb_handle_query_rcmd(GArray *params, void *ctx); /* system */
|
||||
void gdb_handle_query_offsets(GArray *params, void *user_ctx); /* user */
|
||||
void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx); /*user */
|
||||
|
||||
+4
-3
@@ -16,6 +16,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "gdbstub/user.h"
|
||||
#include "gdbstub/syscalls.h"
|
||||
#include "gdbstub/commands.h"
|
||||
#include "trace.h"
|
||||
#include "internals.h"
|
||||
|
||||
@@ -154,9 +155,9 @@ void gdb_handle_file_io(GArray *params, void *user_ctx)
|
||||
uint64_t ret;
|
||||
int err;
|
||||
|
||||
ret = get_param(params, 0)->val_ull;
|
||||
ret = gdb_get_cmd_param(params, 0)->val_ull;
|
||||
if (params->len >= 2) {
|
||||
err = get_param(params, 1)->val_ull;
|
||||
err = gdb_get_cmd_param(params, 1)->val_ull;
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
@@ -196,7 +197,7 @@ void gdb_handle_file_io(GArray *params, void *user_ctx)
|
||||
gdbserver_syscall_state.current_syscall_cb = NULL;
|
||||
}
|
||||
|
||||
if (params->len >= 3 && get_param(params, 2)->opcode == (uint8_t)'C') {
|
||||
if (params->len >= 3 && gdb_get_cmd_param(params, 2)->opcode == (uint8_t)'C') {
|
||||
gdb_put_packet("T02");
|
||||
return;
|
||||
}
|
||||
|
||||
+4
-3
@@ -16,6 +16,7 @@
|
||||
#include "qemu/cutils.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "gdbstub/syscalls.h"
|
||||
#include "gdbstub/commands.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "sysemu/cpus.h"
|
||||
@@ -501,7 +502,7 @@ void gdb_handle_set_qemu_phy_mem_mode(GArray *params, void *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!get_param(params, 0)->val_ul) {
|
||||
if (!gdb_get_cmd_param(params, 0)->val_ul) {
|
||||
phy_memory_mode = 0;
|
||||
} else {
|
||||
phy_memory_mode = 1;
|
||||
@@ -519,7 +520,7 @@ void gdb_handle_query_rcmd(GArray *params, void *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(get_param(params, 0)->data);
|
||||
len = strlen(gdb_get_cmd_param(params, 0)->data);
|
||||
if (len % 2) {
|
||||
gdb_put_packet("E01");
|
||||
return;
|
||||
@@ -527,7 +528,7 @@ void gdb_handle_query_rcmd(GArray *params, void *ctx)
|
||||
|
||||
g_assert(gdbserver_state.mem_buf->len == 0);
|
||||
len = len / 2;
|
||||
gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
|
||||
gdb_hextomem(gdbserver_state.mem_buf, gdb_get_cmd_param(params, 0)->data, len);
|
||||
g_byte_array_append(gdbserver_state.mem_buf, &zero, 1);
|
||||
qemu_chr_be_write(gdbserver_system_state.mon_chr,
|
||||
gdbserver_state.mem_buf->data,
|
||||
|
||||
+13
-12
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "gdbstub/commands.h"
|
||||
#include "qemu.h"
|
||||
#include "internals.h"
|
||||
#ifdef CONFIG_LINUX
|
||||
@@ -250,8 +251,8 @@ void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
offset = get_param(params, 0)->val_ul;
|
||||
len = get_param(params, 1)->val_ul;
|
||||
offset = gdb_get_cmd_param(params, 0)->val_ul;
|
||||
len = gdb_get_cmd_param(params, 1)->val_ul;
|
||||
ts = get_task_state(gdbserver_state.c_cpu);
|
||||
saved_auxv = ts->info->saved_auxv;
|
||||
auxv_len = ts->info->auxv_len;
|
||||
@@ -288,7 +289,7 @@ void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx)
|
||||
|
||||
static const char *get_filename_param(GArray *params, int i)
|
||||
{
|
||||
const char *hex_filename = get_param(params, i)->data;
|
||||
const char *hex_filename = gdb_get_cmd_param(params, i)->data;
|
||||
gdb_hextomem(gdbserver_state.mem_buf, hex_filename,
|
||||
strlen(hex_filename) / 2);
|
||||
g_byte_array_append(gdbserver_state.mem_buf, (const guint8 *)"", 1);
|
||||
@@ -306,8 +307,8 @@ static void hostio_reply_with_data(const void *buf, size_t n)
|
||||
void gdb_handle_v_file_open(GArray *params, void *user_ctx)
|
||||
{
|
||||
const char *filename = get_filename_param(params, 0);
|
||||
uint64_t flags = get_param(params, 1)->val_ull;
|
||||
uint64_t mode = get_param(params, 2)->val_ull;
|
||||
uint64_t flags = gdb_get_cmd_param(params, 1)->val_ull;
|
||||
uint64_t mode = gdb_get_cmd_param(params, 2)->val_ull;
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
int fd = do_guest_openat(cpu_env(gdbserver_state.g_cpu), 0, filename,
|
||||
@@ -325,7 +326,7 @@ void gdb_handle_v_file_open(GArray *params, void *user_ctx)
|
||||
|
||||
void gdb_handle_v_file_close(GArray *params, void *user_ctx)
|
||||
{
|
||||
int fd = get_param(params, 0)->val_ul;
|
||||
int fd = gdb_get_cmd_param(params, 0)->val_ul;
|
||||
|
||||
if (close(fd) == -1) {
|
||||
g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
|
||||
@@ -338,9 +339,9 @@ void gdb_handle_v_file_close(GArray *params, void *user_ctx)
|
||||
|
||||
void gdb_handle_v_file_pread(GArray *params, void *user_ctx)
|
||||
{
|
||||
int fd = get_param(params, 0)->val_ul;
|
||||
size_t count = get_param(params, 1)->val_ull;
|
||||
off_t offset = get_param(params, 2)->val_ull;
|
||||
int fd = gdb_get_cmd_param(params, 0)->val_ul;
|
||||
size_t count = gdb_get_cmd_param(params, 1)->val_ull;
|
||||
off_t offset = gdb_get_cmd_param(params, 2)->val_ull;
|
||||
|
||||
size_t bufsiz = MIN(count, BUFSIZ);
|
||||
g_autofree char *buf = g_try_malloc(bufsiz);
|
||||
@@ -383,9 +384,9 @@ void gdb_handle_v_file_readlink(GArray *params, void *user_ctx)
|
||||
|
||||
void gdb_handle_query_xfer_exec_file(GArray *params, void *user_ctx)
|
||||
{
|
||||
uint32_t pid = get_param(params, 0)->val_ul;
|
||||
uint32_t offset = get_param(params, 1)->val_ul;
|
||||
uint32_t length = get_param(params, 2)->val_ul;
|
||||
uint32_t pid = gdb_get_cmd_param(params, 0)->val_ul;
|
||||
uint32_t offset = gdb_get_cmd_param(params, 1)->val_ul;
|
||||
uint32_t length = gdb_get_cmd_param(params, 2)->val_ul;
|
||||
|
||||
GDBProcess *process = gdb_get_process(pid);
|
||||
if (!process) {
|
||||
|
||||
+4
-3
@@ -16,6 +16,7 @@
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "gdbstub/commands.h"
|
||||
#include "gdbstub/syscalls.h"
|
||||
#include "gdbstub/user.h"
|
||||
#include "gdbstub/enums.h"
|
||||
@@ -793,7 +794,7 @@ void gdb_syscall_return(CPUState *cs, int num)
|
||||
|
||||
void gdb_handle_set_catch_syscalls(GArray *params, void *user_ctx)
|
||||
{
|
||||
const char *param = get_param(params, 0)->data;
|
||||
const char *param = gdb_get_cmd_param(params, 0)->data;
|
||||
GDBSyscallsMask catch_syscalls_mask;
|
||||
bool catch_all_syscalls;
|
||||
unsigned int num;
|
||||
@@ -858,8 +859,8 @@ void gdb_handle_query_xfer_siginfo(GArray *params, void *user_ctx)
|
||||
unsigned long offset, len;
|
||||
uint8_t *siginfo_offset;
|
||||
|
||||
offset = get_param(params, 0)->val_ul;
|
||||
len = get_param(params, 1)->val_ul;
|
||||
offset = gdb_get_cmd_param(params, 0)->val_ul;
|
||||
len = gdb_get_cmd_param(params, 1)->val_ul;
|
||||
|
||||
if (offset + len > gdbserver_user_state.siginfo_len) {
|
||||
/* Invalid offset and/or requested length. */
|
||||
|
||||
@@ -192,13 +192,6 @@ static void cpu_common_parse_features(const char *typename, char *features,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
static void qemu_plugin_vcpu_init__async(CPUState *cpu, run_on_cpu_data unused)
|
||||
{
|
||||
qemu_plugin_vcpu_init_hook(cpu);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cpu_common_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cpu = CPU(dev);
|
||||
@@ -274,7 +267,7 @@ static void cpu_common_initfn(Object *obj)
|
||||
#ifdef CONFIG_PLUGIN
|
||||
if (tcg_enabled()) {
|
||||
cpu->plugin_state = qemu_plugin_create_vcpu_state();
|
||||
async_run_on_cpu(cpu, qemu_plugin_vcpu_init__async, RUN_ON_CPU_NULL);
|
||||
qemu_plugin_vcpu_init_hook(cpu);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -283,6 +276,11 @@ static void cpu_common_finalize(Object *obj)
|
||||
{
|
||||
CPUState *cpu = CPU(obj);
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
if (tcg_enabled()) {
|
||||
g_free(cpu->plugin_state);
|
||||
}
|
||||
#endif
|
||||
g_array_free(cpu->gdb_regs, TRUE);
|
||||
qemu_lockcnt_destroy(&cpu->in_ioctl_lock);
|
||||
qemu_mutex_destroy(&cpu->work_mutex);
|
||||
|
||||
@@ -267,7 +267,7 @@ int load_fit(const struct fit_loader *ldr, const char *filename, void *opaque)
|
||||
const char *def_cfg_name;
|
||||
char path[FIT_LOADER_MAX_PATH];
|
||||
int itb_size, configs, cfg_off, off;
|
||||
hwaddr kernel_end;
|
||||
hwaddr kernel_end = 0;
|
||||
int ret;
|
||||
|
||||
itb = load_device_tree(filename, &itb_size);
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef GDBSTUB_COMMANDS_H
|
||||
#define GDBSTUB
|
||||
|
||||
typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx);
|
||||
|
||||
typedef enum GDBThreadIdKind {
|
||||
GDB_ONE_THREAD = 0,
|
||||
GDB_ALL_THREADS, /* One process, all threads */
|
||||
GDB_ALL_PROCESSES,
|
||||
GDB_READ_THREAD_ERR
|
||||
} GDBThreadIdKind;
|
||||
|
||||
typedef union GdbCmdVariant {
|
||||
const char *data;
|
||||
uint8_t opcode;
|
||||
unsigned long val_ul;
|
||||
unsigned long long val_ull;
|
||||
struct {
|
||||
GDBThreadIdKind kind;
|
||||
uint32_t pid;
|
||||
uint32_t tid;
|
||||
} thread_id;
|
||||
} GdbCmdVariant;
|
||||
|
||||
#define gdb_get_cmd_param(p, i) (&g_array_index(p, GdbCmdVariant, i))
|
||||
|
||||
/**
|
||||
* typedef GdbCmdParseEntry - gdb command parser
|
||||
*
|
||||
* This structure keeps the information necessary to match a gdb command,
|
||||
* parse it (extract its parameters), and select the correct handler for it.
|
||||
*
|
||||
* @cmd: The command to be matched
|
||||
* @cmd_startswith: If true, @cmd is compared using startswith
|
||||
* @schema: Each schema for the command parameter entry consists of 2 chars,
|
||||
* the first char represents the parameter type handling the second char
|
||||
* represents the delimiter for the next parameter.
|
||||
*
|
||||
* Currently supported schema types:
|
||||
* 'l' -> unsigned long (stored in .val_ul)
|
||||
* 'L' -> unsigned long long (stored in .val_ull)
|
||||
* 's' -> string (stored in .data)
|
||||
* 'o' -> single char (stored in .opcode)
|
||||
* 't' -> thread id (stored in .thread_id)
|
||||
* '?' -> skip according to delimiter
|
||||
*
|
||||
* Currently supported delimiters:
|
||||
* '?' -> Stop at any delimiter (",;:=\0")
|
||||
* '0' -> Stop at "\0"
|
||||
* '.' -> Skip 1 char unless reached "\0"
|
||||
* Any other value is treated as the delimiter value itself
|
||||
*
|
||||
* @allow_stop_reply: True iff the gdbstub can respond to this command with a
|
||||
* "stop reply" packet. The list of commands that accept such response is
|
||||
* defined at the GDB Remote Serial Protocol documentation. See:
|
||||
* https://sourceware.org/gdb/onlinedocs/gdb/Stop-Reply-Packets.html#Stop-Reply-Packets.
|
||||
*
|
||||
* @need_cpu_context: Pass current CPU context to command handler via user_ctx.
|
||||
*/
|
||||
typedef struct GdbCmdParseEntry {
|
||||
GdbCmdHandler handler;
|
||||
const char *cmd;
|
||||
bool cmd_startswith;
|
||||
const char *schema;
|
||||
bool allow_stop_reply;
|
||||
bool need_cpu_context;
|
||||
} GdbCmdParseEntry;
|
||||
|
||||
/**
|
||||
* gdb_put_packet() - put string into gdb server's buffer so it is sent
|
||||
* to the client
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void gdb_extend_query_table(GdbCmdParseEntry *table, int size);
|
||||
|
||||
/**
|
||||
* gdb_extend_set_table() - Extend set table.
|
||||
* @table: The table with the additional set packet handlers.
|
||||
* @size: The number of handlers to be added.
|
||||
*/
|
||||
void gdb_extend_set_table(GdbCmdParseEntry *table, int size);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void gdb_extend_qsupported_features(char *qsupported_features);
|
||||
|
||||
/**
|
||||
* Convert a hex string to bytes. Conversion is done per byte, so 2 hex digits
|
||||
* are converted to 1 byte. Invalid hex digits are treated as 0 digits.
|
||||
*/
|
||||
void gdb_hextomem(GByteArray *mem, const char *buf, int len);
|
||||
|
||||
#endif /* GDBSTUB_COMMANDS_H */
|
||||
@@ -149,6 +149,9 @@ struct CPUPluginState {
|
||||
|
||||
/**
|
||||
* qemu_plugin_create_vcpu_state: allocate plugin state
|
||||
*
|
||||
* The returned data must be released with g_free()
|
||||
* when no longer required.
|
||||
*/
|
||||
CPUPluginState *qemu_plugin_create_vcpu_state(void);
|
||||
|
||||
|
||||
@@ -9,3 +9,5 @@ vdso_le_inc = gen_vdso.process('vdso-le.so',
|
||||
extra_args: ['-r', '__kernel_rt_sigreturn'])
|
||||
|
||||
linux_user_ss.add(when: 'TARGET_AARCH64', if_true: [vdso_be_inc, vdso_le_inc])
|
||||
|
||||
linux_user_ss.add(when: 'TARGET_AARCH64', if_true: [files('mte_user_helper.c')])
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* ARM MemTag convenience functions.
|
||||
*
|
||||
* This code is licensed under the GNU GPL v2 or later.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "mte_user_helper.h"
|
||||
|
||||
void arm_set_mte_tcf0(CPUArchState *env, abi_long value)
|
||||
{
|
||||
/*
|
||||
* Write PR_MTE_TCF to SCTLR_EL1[TCF0].
|
||||
*
|
||||
* The kernel has a per-cpu configuration for the sysadmin,
|
||||
* /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred,
|
||||
* which qemu does not implement.
|
||||
*
|
||||
* Because there is no performance difference between the modes, and
|
||||
* because SYNC is most useful for debugging MTE errors, choose SYNC
|
||||
* as the preferred mode. With this preference, and the way the API
|
||||
* uses only two bits, there is no way for the program to select
|
||||
* ASYMM mode.
|
||||
*/
|
||||
unsigned tcf = 0;
|
||||
if (value & PR_MTE_TCF_SYNC) {
|
||||
tcf = 1;
|
||||
} else if (value & PR_MTE_TCF_ASYNC) {
|
||||
tcf = 2;
|
||||
}
|
||||
env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* ARM MemTag convenience functions.
|
||||
*
|
||||
* This code is licensed under the GNU GPL v2 or later.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef AARCH64_MTE_USER_HELPER_H
|
||||
#define AARCH64_MTE USER_HELPER_H
|
||||
|
||||
#ifndef PR_MTE_TCF_SHIFT
|
||||
# define PR_MTE_TCF_SHIFT 1
|
||||
# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
|
||||
# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
|
||||
# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
|
||||
# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
|
||||
# define PR_MTE_TAG_SHIFT 3
|
||||
# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* arm_set_mte_tcf0 - Set TCF0 field in SCTLR_EL1 register
|
||||
* @env: The CPU environment
|
||||
* @value: The value to be set for the Tag Check Fault in EL0 field.
|
||||
*
|
||||
* Only SYNC and ASYNC modes can be selected. If ASYMM mode is given, the SYNC
|
||||
* mode is selected instead. So, there is no way to set the ASYMM mode.
|
||||
*/
|
||||
void arm_set_mte_tcf0(CPUArchState *env, abi_long value);
|
||||
|
||||
#endif /* AARCH64_MTE_USER_HELPER_H */
|
||||
@@ -7,6 +7,7 @@
|
||||
#define AARCH64_TARGET_PRCTL_H
|
||||
|
||||
#include "target/arm/cpu-features.h"
|
||||
#include "mte_user_helper.h"
|
||||
|
||||
static abi_long do_prctl_sve_get_vl(CPUArchState *env)
|
||||
{
|
||||
@@ -173,26 +174,7 @@ static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2)
|
||||
env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE;
|
||||
|
||||
if (cpu_isar_feature(aa64_mte, cpu)) {
|
||||
/*
|
||||
* Write PR_MTE_TCF to SCTLR_EL1[TCF0].
|
||||
*
|
||||
* The kernel has a per-cpu configuration for the sysadmin,
|
||||
* /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred,
|
||||
* which qemu does not implement.
|
||||
*
|
||||
* Because there is no performance difference between the modes, and
|
||||
* because SYNC is most useful for debugging MTE errors, choose SYNC
|
||||
* as the preferred mode. With this preference, and the way the API
|
||||
* uses only two bits, there is no way for the program to select
|
||||
* ASYMM mode.
|
||||
*/
|
||||
unsigned tcf = 0;
|
||||
if (arg2 & PR_MTE_TCF_SYNC) {
|
||||
tcf = 1;
|
||||
} else if (arg2 & PR_MTE_TCF_ASYNC) {
|
||||
tcf = 2;
|
||||
}
|
||||
env->cp15.sctlr_el[1] = deposit64(env->cp15.sctlr_el[1], 38, 2, tcf);
|
||||
arm_set_mte_tcf0(env, arg2);
|
||||
|
||||
/*
|
||||
* Write PR_MTE_TAG to GCR_EL1[Exclude].
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user