From 7885b8558a6f1f11465a62021d96b0fd45ab6452 Mon Sep 17 00:00:00 2001 From: Denis Drakhnia Date: Wed, 6 Dec 2023 19:07:21 +0200 Subject: [PATCH] e2k: add gdb_rw_tags --- gdbstub/gdbstub.c | 46 +++++++++++++++++++++++++++++++++++++++++++ include/hw/core/cpu.h | 2 ++ target/e2k/cpu.c | 1 + target/e2k/cpu.h | 2 ++ target/e2k/gdbstub.c | 34 ++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 9c23d44baf..d0671d95b6 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -1681,6 +1681,12 @@ static void handle_query_supported(GArray *params, void *user_ctx) #endif } + if (cc->gdb_rw_tags) { + g_string_append(gdbserver_state.str_buf, ";qXfer:tags:read+"); + // TODO: g_string_append(gdbserver_state.str_buf, ";qXfer:tags:write+"); + // TODO: g_string_append(gdbserver_state.str_buf, ";qXfer:packed_tags:read+"); + } + g_string_append(gdbserver_state.str_buf, ";vContSupported+;multiprocess+"); gdb_put_strbuf(); } @@ -1745,6 +1751,40 @@ static void handle_query_qemu_supported(GArray *params, void *user_ctx) gdb_put_strbuf(); } +static void handle_query_tags_read(GArray *params, void *user_ctx) +{ + CPUClass *cc; + unsigned long long addr; + unsigned long len; + uint8_t buf[256]; + + if (params->len < 2) { + gdb_put_packet("E22"); + return; + } + + addr = get_param(params, 0)->val_ull; + len = get_param(params, 1)->val_ul; + cc = CPU_GET_CLASS(gdbserver_state.g_cpu); + + g_string_assign(gdbserver_state.str_buf, "l"); + while (len) { + unsigned long l = MIN(len, sizeof(buf)); + + cc->gdb_rw_tags(gdbserver_state.g_cpu, addr, buf, l, false); + + for (int i = 0; i < l; i++) { + g_string_append_c(gdbserver_state.str_buf, buf[i]); + } + + addr += l; + len -= l; + } + + gdb_put_packet_binary(gdbserver_state.str_buf->str, + gdbserver_state.str_buf->len, true); +} + static const GdbCmdParseEntry gdb_gen_query_set_common_table[] = { /* Order is important if has same prefix */ { @@ -1853,6 +1893,12 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = { .cmd = "qemu.PhyMemMode", }, #endif + { + .handler = handle_query_tags_read, + .cmd = "Xfer:tags:read::", + .cmd_startswith = 1, + .schema = "L,l0", + }, }; static const GdbCmdParseEntry gdb_gen_set_table[] = { diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index ec14f74ce5..5ade9ab1d6 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -159,6 +159,8 @@ struct CPUClass { vaddr (*get_pc)(CPUState *cpu); int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg); int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg); + void (*gdb_rw_tags)(CPUState *cpu, vaddr addr, + uint8_t *buf, int len, bool is_write); vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr); const char *gdb_core_xml_file; diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 3b0ff4d52b..0e2d4d9e22 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -281,6 +281,7 @@ static void e2k_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_arch_name = e2k_cpu_gdb_arch_name; cc->gdb_read_register = e2k_cpu_gdb_read_register; cc->gdb_write_register = e2k_cpu_gdb_write_register; + cc->gdb_rw_tags = e2k_cpu_gdb_rw_tags; cc->gdb_num_core_regs = 574; cc->tcg_ops = &e2k_tcg_ops; diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index e8b2917405..db0af7a878 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -939,6 +939,8 @@ void e2k_cpu_list(void); int e2k_cpu_signal_handler(int host_signum, void *pinfo, void *puc); int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n); int e2k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n); +void e2k_cpu_gdb_rw_tags(CPUState *cpu, vaddr addr, + uint8_t *buf, int len, bool is_write); void e2k_cpu_register_gdb_regs_for_features(CPUState *cs); bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size, MMUAccessType access_type, int mmu_idx, diff --git a/target/e2k/gdbstub.c b/target/e2k/gdbstub.c index 11b82ccd11..ba5e69cf37 100644 --- a/target/e2k/gdbstub.c +++ b/target/e2k/gdbstub.c @@ -384,3 +384,37 @@ void e2k_cpu_register_gdb_regs_for_features(CPUState *cs) gdb_find_static_feature("e2k-v5.xml"), 576); } } + +void e2k_cpu_gdb_rw_tags(CPUState *cs, vaddr addr, + uint8_t *buf, int len, bool is_write) +{ + E2KCPU *cpu = E2K_CPU(cs); + CPUE2KState *env = &cpu->env; + + if (is_write) { + // TODO: e2k write tags + return; + } + +#ifdef CONFIG_USER_ONLY + if (env->psp.base <= addr && addr < (env->psp.base + env->psp.size)) { + target_ulong offset = addr - env->psp.base; + target_ulong ptr = env->psp.base_tag + offset / 8; + + for (int i = 0; i < len; i += 4, ptr++) { + uint8_t tags; + + cpu_memory_rw_debug(cs, ptr, &tags, sizeof(tags), false); + + for (int j = 0; j < 4 && (i + j) < len; j++) { + buf[i + j] = (tags >> (j * 2)) & 3; + } + } + } else { + memset(buf, 0, len); + } +#else + // TODO: e2k-softmmu read tags + memset(buf, 0, len); +#endif +}