From patchwork Fri Oct 6 09:05:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844287 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22d05vs2z1yqF for ; Fri, 6 Oct 2023 20:07:32 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogmp-0007z4-J5; Fri, 06 Oct 2023 05:06:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmn-0007yo-Ie for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:17 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogml-0000sO-6w for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:17 -0400 Received: (qmail 19360 invoked by uid 484); 6 Oct 2023 09:06:13 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.07498 secs); 06 Oct 2023 09:06:13 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:12 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 01/29] mcdstub initial commit, mcdstub file structure added Date: Fri, 6 Oct 2023 11:05:42 +0200 Message-Id: <20231006090610.26171-2-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- include/exec/mcdstub.h | 31 +++++++++++++ mcdstub/mcd_softmmu.c | 85 +++++++++++++++++++++++++++++++++++ mcdstub/mcd_syscalls.c | 0 mcdstub/mcd_tcp_server.c | 95 ++++++++++++++++++++++++++++++++++++++++ mcdstub/mcdstub.c | 0 softmmu/vl.c | 4 ++ 6 files changed, 215 insertions(+) create mode 100644 include/exec/mcdstub.h create mode 100644 mcdstub/mcd_softmmu.c create mode 100644 mcdstub/mcd_syscalls.c create mode 100644 mcdstub/mcd_tcp_server.c create mode 100644 mcdstub/mcdstub.c diff --git a/include/exec/mcdstub.h b/include/exec/mcdstub.h new file mode 100644 index 0000000000..8afbc09367 --- /dev/null +++ b/include/exec/mcdstub.h @@ -0,0 +1,31 @@ +#ifndef MCDSTUB_H +#define MCDSTUB_H + +#define DEFAULT_MCDSTUB_PORT "1234" + +/* MCD breakpoint/watchpoint types */ +#define MCD_BREAKPOINT_SW 0 +#define MCD_BREAKPOINT_HW 1 +#define MCD_WATCHPOINT_WRITE 2 +#define MCD_WATCHPOINT_READ 3 +#define MCD_WATCHPOINT_ACCESS 4 + + +/* Get or set a register. Returns the size of the register. */ +typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg); +typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg); +void gdb_register_coprocessor(CPUState *cpu, + gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg, + int num_regs, const char *xml, int g_pos); + +/** + * mcdserver_start: start the mcd server + * @port_or_device: connection spec for mcd + * + * This is a TCP port + */ +int mcdserver_start(const char *port_or_device); + +void gdb_set_stop_cpu(CPUState *cpu); + +#endif diff --git a/mcdstub/mcd_softmmu.c b/mcdstub/mcd_softmmu.c new file mode 100644 index 0000000000..17e1d3ca1b --- /dev/null +++ b/mcdstub/mcd_softmmu.c @@ -0,0 +1,85 @@ +/* + * this handeles all system emulation functions for the mcdstub + */ + +#include "exec/mcdstub.h" + +int mcdserver_start(const char *device) +{ + trace_gdbstub_op_start(device); + + char gdbstub_device_name[128]; + Chardev *chr = NULL; + Chardev *mon_chr; + + if (!first_cpu) { + error_report("gdbstub: meaningless to attach gdb to a " + "machine without any CPU."); + return -1; + } + + if (!gdb_supports_guest_debug()) { + error_report("gdbstub: current accelerator doesn't " + "support guest debugging"); + return -1; + } + + if (!device) { + return -1; + } + if (strcmp(device, "none") != 0) { + if (strstart(device, "tcp:", NULL)) { + /* enforce required TCP attributes */ + snprintf(gdbstub_device_name, sizeof(gdbstub_device_name), + "%s,wait=off,nodelay=on,server=on", device); + device = gdbstub_device_name; + } +#ifndef _WIN32 + else if (strcmp(device, "stdio") == 0) { + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler = gdb_sigterm_handler; + sigaction(SIGINT, &act, NULL); + } +#endif + /* + * FIXME: it's a bit weird to allow using a mux chardev here + * and implicitly setup a monitor. We may want to break this. + */ + chr = qemu_chr_new_noreplay("gdb", device, true, NULL); + if (!chr) { + return -1; + } + } + + if (!gdbserver_state.init) { + gdb_init_gdbserver_state(); + + qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL); + + /* Initialize a monitor terminal for gdb */ + mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB, + NULL, NULL, &error_abort); + monitor_init_hmp(mon_chr, false, &error_abort); + } else { + qemu_chr_fe_deinit(&gdbserver_system_state.chr, true); + mon_chr = gdbserver_system_state.mon_chr; + reset_gdbserver_state(); + } + + create_processes(&gdbserver_state); + + if (chr) { + qemu_chr_fe_init(&gdbserver_system_state.chr, chr, &error_abort); + qemu_chr_fe_set_handlers(&gdbserver_system_state.chr, + gdb_chr_can_receive, + gdb_chr_receive, gdb_chr_event, + NULL, &gdbserver_state, NULL, true); + } + gdbserver_state.state = chr ? RS_IDLE : RS_INACTIVE; + gdbserver_system_state.mon_chr = mon_chr; + gdb_syscall_reset(); + + return 0; +} \ No newline at end of file diff --git a/mcdstub/mcd_syscalls.c b/mcdstub/mcd_syscalls.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mcdstub/mcd_tcp_server.c b/mcdstub/mcd_tcp_server.c new file mode 100644 index 0000000000..9a1baea2e4 --- /dev/null +++ b/mcdstub/mcd_tcp_server.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include +#include // read(), write(), close() +#define MAX 80 +#define DEFAULT_MCDSTUB_PORT "1234" +#define SA struct sockaddr + +// Function designed for chat between client and server. +void func(int connfd) +{ + char buff[MAX]; + int n; + // infinite loop for chat + for (;;) { + bzero(buff, MAX); + + // read the message from client and copy it in buffer + read(connfd, buff, sizeof(buff)); + // print buffer which contains the client contents + printf("From client: %s\t To client : ", buff); + bzero(buff, MAX); + n = 0; + // copy server message in the buffer + while ((buff[n++] = getchar()) != '\n') + ; + + // and send that buffer to client + write(connfd, buff, sizeof(buff)); + + // if msg contains "Exit" then server exit and chat ended. + if (strncmp("exit", buff, 4) == 0) { + printf("Server Exit...\n"); + break; + } + } +} + +// Driver function +int main() +{ + int sockfd, connfd, len; + struct sockaddr_in servaddr, cli; + + // socket create and verification + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + printf("socket creation failed...\n"); + exit(0); + } + else + printf("Socket successfully created..\n"); + bzero(&servaddr, sizeof(servaddr)); + + // assign IP, PORT + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(DEFAULT_MCDSTUB_PORT); + + // Binding newly created socket to given IP and verification + if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) { + printf("socket bind failed...\n"); + exit(0); + } + else + printf("Socket successfully binded..\n"); + + // Now server is ready to listen and verification + if ((listen(sockfd, 5)) != 0) { + printf("Listen failed...\n"); + exit(0); + } + else + printf("Server listening..\n"); + len = sizeof(cli); + + // Accept the data packet from client and verification + connfd = accept(sockfd, (SA*)&cli, &len); + if (connfd < 0) { + printf("server accept failed...\n"); + exit(0); + } + else + printf("server accept the client...\n"); + + // Function for chatting between client and server + func(connfd); + + // After chatting close the socket + close(sockfd); +} diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/softmmu/vl.c b/softmmu/vl.c index 98e071e63b..3278f204ea 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1258,6 +1258,7 @@ struct device_config { DEV_PARALLEL, /* -parallel */ DEV_DEBUGCON, /* -debugcon */ DEV_GDB, /* -gdb, -s */ + DEV_MCD, /* -mcd */ DEV_SCLP, /* s390 sclp */ } type; const char *cmdline; @@ -3011,6 +3012,9 @@ void qemu_init(int argc, char **argv) case QEMU_OPTION_gdb: add_device_config(DEV_GDB, optarg); break; + case QEMU_OPTION_mcd: + add_device_config(DEV_MCD, optarg); + break; case QEMU_OPTION_L: if (is_help_option(optarg)) { list_data_dirs = true; From patchwork Fri Oct 6 09:05:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844303 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22gT1nT6z1yqF for ; Fri, 6 Oct 2023 20:09:41 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogmu-00081I-HN; Fri, 06 Oct 2023 05:06:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmp-0007zK-R8 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:19 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmm-0000sa-4w for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:19 -0400 Received: (qmail 19382 invoked by uid 484); 6 Oct 2023 09:06:14 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.074411 secs); 06 Oct 2023 09:06:14 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:13 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 02/29] TCP chardev added, handshake with TRACE32 working Date: Fri, 6 Oct 2023 11:05:43 +0200 Message-Id: <20231006090610.26171-3-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- gdbstub/gdbstub.c | 2 +- include/exec/mcdstub.h | 21 +- include/mcdstub/syscalls.h | 6 + mcdstub/internals.h | 135 ++++++++++ mcdstub/mcd_softmmu.c | 218 +++++++++++----- mcdstub/mcd_syscalls.c | 20 ++ mcdstub/mcd_tcp_server.c | 2 +- mcdstub/mcdstub.c | 519 +++++++++++++++++++++++++++++++++++++ mcdstub/meson.build | 25 ++ meson.build | 1 + qemu-options.hx | 25 ++ softmmu/vl.c | 9 + 12 files changed, 901 insertions(+), 82 deletions(-) create mode 100644 include/mcdstub/syscalls.h create mode 100644 mcdstub/internals.h create mode 100644 mcdstub/meson.build diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 349d348c7b..2ff50757bb 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -857,7 +857,7 @@ static int process_string_cmd(const char *data, if (cmd->schema) { if (cmd_parse_params(&data[strlen(cmd->cmd)], - cmd->schema, params)) { + cmd->schema, params)) { return -1; } } diff --git a/include/exec/mcdstub.h b/include/exec/mcdstub.h index 8afbc09367..abf7beb634 100644 --- a/include/exec/mcdstub.h +++ b/include/exec/mcdstub.h @@ -1,7 +1,10 @@ #ifndef MCDSTUB_H #define MCDSTUB_H -#define DEFAULT_MCDSTUB_PORT "1234" +#define DEFAULT_MCDSTUB_PORT "1235" +#define TYPE_CHARDEV_MCD "chardev-mcd" +#define MX_INPUT_LENGTH 9 +#define MCD_TCP_DATALEN 80 /* MCD breakpoint/watchpoint types */ #define MCD_BREAKPOINT_SW 0 @@ -10,22 +13,12 @@ #define MCD_WATCHPOINT_READ 3 #define MCD_WATCHPOINT_ACCESS 4 - -/* Get or set a register. Returns the size of the register. */ -typedef int (*gdb_get_reg_cb)(CPUArchState *env, GByteArray *buf, int reg); -typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg); -void gdb_register_coprocessor(CPUState *cpu, - gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg, - int num_regs, const char *xml, int g_pos); - /** - * mcdserver_start: start the mcd server - * @port_or_device: connection spec for mcd + * mcd_tcp_server_start: start the tcp server to connect via mcd + * @device: connection spec for mcd * * This is a TCP port */ -int mcdserver_start(const char *port_or_device); - -void gdb_set_stop_cpu(CPUState *cpu); +int mcdserver_start(const char *device); #endif diff --git a/include/mcdstub/syscalls.h b/include/mcdstub/syscalls.h new file mode 100644 index 0000000000..1f86634140 --- /dev/null +++ b/include/mcdstub/syscalls.h @@ -0,0 +1,6 @@ +#ifndef _SYSCALLS_H_ +#define _SYSCALLS_H_ + +typedef void (*gdb_syscall_complete_cb)(CPUState *cpu, uint64_t ret, int err); + +#endif /* _SYSCALLS_H_ */ \ No newline at end of file diff --git a/mcdstub/internals.h b/mcdstub/internals.h new file mode 100644 index 0000000000..7b0f4b0b36 --- /dev/null +++ b/mcdstub/internals.h @@ -0,0 +1,135 @@ +/* + * this header includes a lookup table for the transmitted messages over the tcp connection to trace32, + * as well as function declarations for all functios used inside the mcdstub + */ + +#ifndef MCDSTUB_INTERNALS_H +#define MCDSTUB_INTERNALS_H + +#include "exec/cpu-common.h" +#include "chardev/char.h" + +#define MAX_PACKET_LENGTH 1024 + +/* + * lookuptable for transmitted signals + */ + +enum { + MCD_SIGNAL_HANDSHAKE = 0 +}; + + +/* + * struct for an MCD Process, each process can establish one connection + */ + +typedef struct MCDProcess { + uint32_t pid; + bool attached; + + char target_xml[1024]; +} MCDProcess; + + +/* + * not sure for what this is used exactly + */ + + +enum RSState { + RS_INACTIVE, + RS_IDLE, + RS_GETLINE, + RS_GETLINE_ESC, + RS_GETLINE_RLE, + RS_CHKSUM1, + RS_CHKSUM2, +}; + +typedef struct MCDState { + bool init; /* have we been initialised? */ + CPUState *c_cpu; /* current CPU for step/continue ops */ + CPUState *g_cpu; /* current CPU for other ops */ + CPUState *query_cpu; /* for q{f|s}ThreadInfo */ + enum RSState state; /* parsing state */ + char line_buf[MAX_PACKET_LENGTH]; + int line_buf_index; + int line_sum; /* running checksum */ + int line_csum; /* checksum at the end of the packet */ + GByteArray *last_packet; + int signal; + bool multiprocess; + MCDProcess *processes; + int process_num; + GString *str_buf; + GByteArray *mem_buf; + int sstep_flags; + int supported_sstep_flags; +} MCDState; + +/* lives in main mcdstub.c */ +extern MCDState mcdserver_state; + + +// Inline utility function, convert from int to hex and back + + +static inline int fromhex(int v) +{ + if (v >= '0' && v <= '9') { + return v - '0'; + } else if (v >= 'A' && v <= 'F') { + return v - 'A' + 10; + } else if (v >= 'a' && v <= 'f') { + return v - 'a' + 10; + } else { + return 0; + } +} + +static inline int tohex(int v) +{ + if (v < 10) { + return v + '0'; + } else { + return v - 10 + 'a'; + } +} + + +/*old functions +void mcd_init_mcdserver_state(void); +int mcd_open_tcp_socket(int tcp_port); +int mcd_extract_tcp_port_num(const char *in_string, char *out_string); +*/ +#ifndef _WIN32 +void mcd_sigterm_handler(int signal); +#endif + +void mcd_init_mcdserver_state(void); +void reset_mcdserver_state(void); +void create_processes(MCDState *s); +void mcd_create_default_process(MCDState *s); +int find_cpu_clusters(Object *child, void *opaque); +int pid_order(const void *a, const void *b); +int mcd_chr_can_receive(void *opaque); +void mcd_chr_receive(void *opaque, const uint8_t *buf, int size); +void mcd_chr_event(void *opaque, QEMUChrEvent event); +bool mcd_supports_guest_debug(void); +void mcd_vm_state_change(void *opaque, bool running, RunState state); +int mcd_put_packet(const char *buf); +int mcd_put_packet_binary(const char *buf, int len, bool dump); +bool mcd_got_immediate_ack(void); +void mcd_put_buffer(const uint8_t *buf, int len); +void mcd_set_stop_cpu(CPUState *cpu); +MCDProcess *mcd_get_cpu_process(CPUState *cpu); +uint32_t mcd_get_cpu_pid(CPUState *cpu); +MCDProcess *mcd_get_process(uint32_t pid); +CPUState *mcd_first_attached_cpu(void); +CPUState *mcd_next_attached_cpu(CPUState *cpu); + +/* sycall handling */ +void mcd_syscall_reset(void); + +#endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/mcd_softmmu.c b/mcdstub/mcd_softmmu.c index 17e1d3ca1b..52dcb182b2 100644 --- a/mcdstub/mcd_softmmu.c +++ b/mcdstub/mcd_softmmu.c @@ -1,85 +1,171 @@ /* - * this handeles all system emulation functions for the mcdstub - */ +#if defined(WIN32) +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#include +#include +//#pragma comment(lib, "Ws2_32.lib") +#define ISVALIDSOCKET(s) ((s) != INVALID_SOCKET) +#define CLOSESOCKET(s) closesocket(s) +#define GETSOCKETERRNO() (WSAGetLastError()) +#else +#include +#include +#include +#include +#include +#include +//#include +#define SOCKET int +#define ISVALIDSOCKET(s) ((s) >= 0) +#define CLOSESOCKET(s) close(s) +#define GETSOCKETERRNO() (errno) +#endif -#include "exec/mcdstub.h" +#define SA struct sockaddr -int mcdserver_start(const char *device) -{ - trace_gdbstub_op_start(device); - char gdbstub_device_name[128]; - Chardev *chr = NULL; - Chardev *mon_chr; - if (!first_cpu) { - error_report("gdbstub: meaningless to attach gdb to a " - "machine without any CPU."); - return -1; - } +#include "exec/mcdstub.h" +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/cutils.h" +#include "gdbstub/syscalls.h" +#include "exec/hwaddr.h" +#include "exec/tb-flush.h" +#include "sysemu/cpus.h" +#include "sysemu/runstate.h" +#include "sysemu/replay.h" +#include "hw/core/cpu.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "chardev/char.h" +#include "chardev/char-fe.h" +#include "monitor/monitor.h" +#include "internals.h" - if (!gdb_supports_guest_debug()) { - error_report("gdbstub: current accelerator doesn't " - "support guest debugging"); - return -1; - } +//here only deprecated code: - if (!device) { +int old_mcdserver_start(const char *device) +{ + //the device is a char array. if its "default" we use tcp with the default DEFAULT_MCDSTUB_PORT. Otherwise it has to look like "tcp::" + char tcp_port[MX_INPUT_LENGTH]; + int error; + error = mcd_extract_tcp_port_num(device, tcp_port); + if (error != 0) { return -1; } - if (strcmp(device, "none") != 0) { - if (strstart(device, "tcp:", NULL)) { - /* enforce required TCP attributes */ - snprintf(gdbstub_device_name, sizeof(gdbstub_device_name), - "%s,wait=off,nodelay=on,server=on", device); - device = gdbstub_device_name; - } -#ifndef _WIN32 - else if (strcmp(device, "stdio") == 0) { - struct sigaction act; - - memset(&act, 0, sizeof(act)); - act.sa_handler = gdb_sigterm_handler; - sigaction(SIGINT, &act, NULL); - } -#endif - /* - * FIXME: it's a bit weird to allow using a mux chardev here - * and implicitly setup a monitor. We may want to break this. - */ - chr = qemu_chr_new_noreplay("gdb", device, true, NULL); - if (!chr) { - return -1; - } + int tcp_port_num = atoi(tcp_port); + + if (!mcdserver_state.init) { + mcd_init_mcdserver_state(); } + return mcd_open_tcp_socket(tcp_port_num); +} + +int mcd_open_tcp_socket(int tcp_port) +//soon to be deprecated (hopefully) +{ + SOCKET socked_fd, connect_fd; + struct sockaddr_in server_address, client_address; + +#if defined(WIN32) + WSADATA d; + if (WSAStartup(MAKEWORD(2, 2), &d)) { + return -1; + } + int len; +#else + unsigned int len; +#endif - if (!gdbserver_state.init) { - gdb_init_gdbserver_state(); + // socket create and verification + socked_fd = socket(AF_INET, SOCK_STREAM, 0); + if (!ISVALIDSOCKET(socked_fd)) { + return -1; + } + memset(&server_address, 0, sizeof(server_address)); - qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL); + // assign IP, PORT + server_address.sin_family = AF_INET; + server_address.sin_port = htons(tcp_port); + server_address.sin_addr.s_addr = htonl(INADDR_ANY); - /* Initialize a monitor terminal for gdb */ - mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB, - NULL, NULL, &error_abort); - monitor_init_hmp(mon_chr, false, &error_abort); - } else { - qemu_chr_fe_deinit(&gdbserver_system_state.chr, true); - mon_chr = gdbserver_system_state.mon_chr; - reset_gdbserver_state(); + // Binding newly created socket to given IP and verification + if ((bind(socked_fd, (SA*)&server_address, sizeof(server_address))) != 0) { + CLOSESOCKET(socked_fd); + return -1; + } + + // Now server is ready to listen and verification + if ((listen(socked_fd, 5)) != 0) { + CLOSESOCKET(socked_fd); + return -1; + } + else { + printf("TCP server listening on port %d\n", tcp_port); + } + + //accepting connection + len = sizeof(client_address); + connect_fd = accept(socked_fd, (SA*)&client_address, &len); + if (!ISVALIDSOCKET(connect_fd)) { + CLOSESOCKET(socked_fd); + return -1; } - create_processes(&gdbserver_state); + //lets do the handshake + + char buff[MCD_TCP_DATALEN]; + char expected_buff[MCD_TCP_DATALEN]; - if (chr) { - qemu_chr_fe_init(&gdbserver_system_state.chr, chr, &error_abort); - qemu_chr_fe_set_handlers(&gdbserver_system_state.chr, - gdb_chr_can_receive, - gdb_chr_receive, gdb_chr_event, - NULL, &gdbserver_state, NULL, true); + memset(buff, 0, sizeof(buff)); + memset(expected_buff, 0, sizeof(buff)); + strcpy((char*)expected_buff, "initializing handshake"); + + // read the message from client + recv(connect_fd, buff, MCD_TCP_DATALEN, 0); + + if (strcmp(buff, expected_buff)==0) { + strcpy((char*)buff, "shaking your hand"); + send(connect_fd, buff, MCD_TCP_DATALEN, 0); + printf("handshake complete\n"); + return 0; + } + else { + CLOSESOCKET(socked_fd); + CLOSESOCKET(connect_fd); + return -1; + } +} + +int mcd_extract_tcp_port_num(const char *in_string, char *out_string) +{ + int string_length = strlen(in_string); + if (string_length>MX_INPUT_LENGTH+1) { + return -1; } - gdbserver_state.state = chr ? RS_IDLE : RS_INACTIVE; - gdbserver_system_state.mon_chr = mon_chr; - gdb_syscall_reset(); + const char default_str[] = "default"; + + if ((string_length==strlen(default_str)) && (strcmp(default_str, in_string)==0)) { + strcpy((char*)out_string, DEFAULT_MCDSTUB_PORT); + return 0; + } + else if (strcmp("tcp::", in_string)==0) { + for (int index = 5; index < string_length; index++) { + if (!isdigit(in_string[index])) { + return -1; + } + } + } + else { + return -1; + } + strcpy((char*)out_string, in_string+5); return 0; -} \ No newline at end of file +} + +*/ \ No newline at end of file diff --git a/mcdstub/mcd_syscalls.c b/mcdstub/mcd_syscalls.c index e69de29bb2..663ffde1b6 100644 --- a/mcdstub/mcd_syscalls.c +++ b/mcdstub/mcd_syscalls.c @@ -0,0 +1,20 @@ +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "semihosting/semihost.h" +#include "sysemu/runstate.h" +#include "mcdstub/syscalls.h" +//#include "trace.h" +#include "internals.h" + +typedef struct { + char syscall_buf[256]; + //TODO: this needs to be get fixed mcd_syscall_complete_cb + int current_syscall_cb; +} MCDSyscallState; + +static MCDSyscallState mcdserver_syscall_state; + +void mcd_syscall_reset(void) +{ + mcdserver_syscall_state.current_syscall_cb = 0; +} \ No newline at end of file diff --git a/mcdstub/mcd_tcp_server.c b/mcdstub/mcd_tcp_server.c index 9a1baea2e4..558ddcb969 100644 --- a/mcdstub/mcd_tcp_server.c +++ b/mcdstub/mcd_tcp_server.c @@ -6,8 +6,8 @@ #include #include #include // read(), write(), close() +#include "exec/mcdstub.h" #define MAX 80 -#define DEFAULT_MCDSTUB_PORT "1234" #define SA struct sockaddr // Function designed for chat between client and server. diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index e69de29bb2..c68cab9391 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -0,0 +1,519 @@ +/* + * This is the main mcdstub. It needs to be complemented by other mcd stubs for each target. + */ + +//from original gdbstub.c +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +//#include "trace.h" +#include "exec/mcdstub.h" +#include "mcdstub/syscalls.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" + +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.h" + +#include "internals.h" + +//from original softmmu.c (minus what was already here) +#include "qapi/error.h" +#include "exec/tb-flush.h" +#include "sysemu/cpus.h" +#include "sysemu/replay.h" +#include "hw/core/cpu.h" +#include "chardev/char.h" +#include "chardev/char-fe.h" +#include "monitor/monitor.h" + +typedef struct { + CharBackend chr; + //Chardev *mon_chr; +} MCDSystemState; + +MCDSystemState mcdserver_system_state; + +MCDState mcdserver_state; + +void mcd_init_mcdserver_state(void) +{ + g_assert(!mcdserver_state.init); + memset(&mcdserver_state, 0, sizeof(MCDState)); + mcdserver_state.init = true; + mcdserver_state.str_buf = g_string_new(NULL); + mcdserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH); + mcdserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 4); + + /* + * What single-step modes are supported is accelerator dependent. + * By default try to use no IRQs and no timers while single + * stepping so as to make single stepping like a typical ICE HW step. + */ + // TODO: + // this is weird and might be able to sit just like it is here with the same value as for gdb + mcdserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); + mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; + mcdserver_state.sstep_flags &= mcdserver_state.supported_sstep_flags; +} + +void reset_mcdserver_state(void) +{ + g_free(mcdserver_state.processes); + mcdserver_state.processes = NULL; + mcdserver_state.process_num = 0; +} + +void create_processes(MCDState *s) +{ + object_child_foreach(object_get_root(), find_cpu_clusters, s); + + if (mcdserver_state.processes) { + /* Sort by PID */ + qsort(mcdserver_state.processes, + mcdserver_state.process_num, + sizeof(mcdserver_state.processes[0]), + pid_order); + } + + mcd_create_default_process(s); +} + +void mcd_create_default_process(MCDState *s) +{ + MCDProcess *process; + int max_pid = 0; + + if (mcdserver_state.process_num) { + max_pid = s->processes[s->process_num - 1].pid; + } + + s->processes = g_renew(MCDProcess, s->processes, ++s->process_num); + process = &s->processes[s->process_num - 1]; + + /* We need an available PID slot for this process */ + assert(max_pid < UINT32_MAX); + + process->pid = max_pid + 1; + process->attached = false; + process->target_xml[0] = '\0'; +} + +int find_cpu_clusters(Object *child, void *opaque) +{ + if (object_dynamic_cast(child, TYPE_CPU_CLUSTER)) { + MCDState *s = (MCDState *) opaque; + CPUClusterState *cluster = CPU_CLUSTER(child); + MCDProcess *process; + + s->processes = g_renew(MCDProcess, s->processes, ++s->process_num); + + process = &s->processes[s->process_num - 1]; + + /* + * GDB process IDs -1 and 0 are reserved. To avoid subtle errors at + * runtime, we enforce here that the machine does not use a cluster ID + * that would lead to PID 0. + */ + assert(cluster->cluster_id != UINT32_MAX); + process->pid = cluster->cluster_id + 1; + process->attached = false; + process->target_xml[0] = '\0'; + + return 0; + } + + return object_child_foreach(child, find_cpu_clusters, opaque); +} + +int pid_order(const void *a, const void *b) +{ + MCDProcess *pa = (MCDProcess *) a; + MCDProcess *pb = (MCDProcess *) b; + + if (pa->pid < pb->pid) { + return -1; + } else if (pa->pid > pb->pid) { + return 1; + } else { + return 0; + } +} + +int mcdserver_start(const char *device) +{ + //might wann add tracing later (no idea for what this is used) + //trace_gdbstub_op_start(device); + + char mcdstub_device_name[128]; + Chardev *chr = NULL; + //Chardev *mon_chr; + + if (!first_cpu) { + error_report("mcdstub: meaningless to attach to a " + "machine without any CPU."); + return -1; + } + + // + if (!mcd_supports_guest_debug()) { + error_report("mcdstub: current accelerator doesn't " + "support guest debugging"); + return -1; + } + + if (!device) { + return -1; + } + + //if device == default -> set device = tcp::1235 + if (strcmp(device, "default") == 0) { + device = "tcp::1235"; + } + + if (strcmp(device, "none") != 0) { + if (strstart(device, "tcp:", NULL)) { + /* enforce required TCP attributes */ + snprintf(mcdstub_device_name, sizeof(mcdstub_device_name), + "%s,wait=off,nodelay=on,server=on", device); + device = mcdstub_device_name; + } +#ifndef _WIN32 + else if (strcmp(device, "stdio") == 0) { + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler = mcd_sigterm_handler; + sigaction(SIGINT, &act, NULL); + } +#endif + + chr = qemu_chr_new_noreplay("mcd", device, true, NULL); + if (!chr) { + return -1; + } + } + + if (!mcdserver_state.init) { + mcd_init_mcdserver_state(); + + qemu_add_vm_change_state_handler(mcd_vm_state_change, NULL); + + /* Initialize a monitor terminal for mcd */ + //mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_MCD, NULL, NULL, &error_abort); + //monitor_init_hmp(mon_chr, false, &error_abort); + } else { + qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); + //mon_chr = mcdserver_system_state.mon_chr; + reset_mcdserver_state(); + } + + create_processes(&mcdserver_state); + + if (chr) { + qemu_chr_fe_init(&mcdserver_system_state.chr, chr, &error_abort); + qemu_chr_fe_set_handlers(&mcdserver_system_state.chr, + mcd_chr_can_receive, + mcd_chr_receive, mcd_chr_event, + NULL, &mcdserver_state, NULL, true); + } + mcdserver_state.state = chr ? RS_IDLE : RS_INACTIVE; + //mcdserver_system_state.mon_chr = mon_chr; + mcd_syscall_reset(); + + return 0; +} + +int mcd_chr_can_receive(void *opaque) +{ + return MAX_PACKET_LENGTH; +} + +void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) +{ + printf("incoming buffer: %s\n", buf); + char send_buffer[] = "shaking your hand"; + mcd_put_packet(send_buffer); + //int i; + /* + for (i = 0; i < size; i++) { + //TODO: some byte reading or idk gdb_read_byte(buf[i]); + }*/ +} + +void mcd_chr_event(void *opaque, QEMUChrEvent event) +{ + int i; + MCDState *s = (MCDState *) opaque; + + switch (event) { + case CHR_EVENT_OPENED: + // Start with first process attached, others detached + for (i = 0; i < s->process_num; i++) { + s->processes[i].attached = !i; + } + + s->c_cpu = mcd_first_attached_cpu(); + s->g_cpu = s->c_cpu; + + vm_stop(RUN_STATE_PAUSED); + //TODO: this might not be necessary + //replay_gdb_attached(); + //gdb_has_xml = false; + break; + default: + break; + } +} + +bool mcd_supports_guest_debug(void) +{ + const AccelOpsClass *ops = cpus_get_accel(); + if (ops->supports_guest_debug) { + return ops->supports_guest_debug(); + } + return false; +} + +#ifndef _WIN32 +void mcd_sigterm_handler(int signal) +{ + if (runstate_is_running()) { + vm_stop(RUN_STATE_PAUSED); + } +} +#endif + +void mcd_vm_state_change(void *opaque, bool running, RunState state) +{ + printf("this calls state_change\n"); + /* + CPUState *cpu = mcdserver_state.c_cpu; + g_autoptr(GString) buf = g_string_new(NULL); + g_autoptr(GString) tid = g_string_new(NULL); + const char *type; + int ret; + + if (running || mcdserver_state.state == RS_INACTIVE) { + return; + } + + //Is there a GDB syscall waiting to be sent? + if (gdb_handled_syscall()) { + return; + } + + if (cpu == NULL) { + //No process attached + return; + } + + gdb_append_thread_id(cpu, tid); + + switch (state) { + case RUN_STATE_DEBUG: + if (cpu->watchpoint_hit) { + switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { + case BP_MEM_READ: + type = "r"; + break; + case BP_MEM_ACCESS: + type = "a"; + break; + default: + type = ""; + break; + } + trace_gdbstub_hit_watchpoint(type, + gdb_get_cpu_index(cpu), + cpu->watchpoint_hit->vaddr); + g_string_printf(buf, "T%02xthread:%s;%swatch:%" VADDR_PRIx ";", + GDB_SIGNAL_TRAP, tid->str, type, + cpu->watchpoint_hit->vaddr); + cpu->watchpoint_hit = NULL; + goto send_packet; + } else { + trace_gdbstub_hit_break(); + } + tb_flush(cpu); + ret = GDB_SIGNAL_TRAP; + break; + case RUN_STATE_PAUSED: + trace_gdbstub_hit_paused(); + ret = GDB_SIGNAL_INT; + break; + case RUN_STATE_SHUTDOWN: + trace_gdbstub_hit_shutdown(); + ret = GDB_SIGNAL_QUIT; + break; + case RUN_STATE_IO_ERROR: + trace_gdbstub_hit_io_error(); + ret = GDB_SIGNAL_IO; + break; + case RUN_STATE_WATCHDOG: + trace_gdbstub_hit_watchdog(); + ret = GDB_SIGNAL_ALRM; + break; + case RUN_STATE_INTERNAL_ERROR: + trace_gdbstub_hit_internal_error(); + ret = GDB_SIGNAL_ABRT; + break; + case RUN_STATE_SAVE_VM: + case RUN_STATE_RESTORE_VM: + return; + case RUN_STATE_FINISH_MIGRATE: + ret = GDB_SIGNAL_XCPU; + break; + default: + trace_gdbstub_hit_unknown(state); + ret = GDB_SIGNAL_UNKNOWN; + break; + } + mcd_set_stop_cpu(cpu); + g_string_printf(buf, "T%02xthread:%s;", ret, tid->str); + +send_packet: + mcd_put_packet(buf->str); + + // disable single step if it was enabled + cpu_single_step(cpu, 0); +*/ +} + +int mcd_put_packet(const char *buf) +{ + //tracing + //trace_gdbstub_io_reply(buf); + + return mcd_put_packet_binary(buf, strlen(buf), false); +} + +int mcd_put_packet_binary(const char *buf, int len, bool dump) +{ + //int csum, i; + //uint8_t footer[3]; + + //trace stuff + //if (dump && trace_event_get_state_backends(TRACE_GDBSTUB_IO_BINARYREPLY)) { + // hexdump(buf, len, trace_gdbstub_io_binaryreply); + //} + + for(;;) { + //super interesting if we want a chekcsum or something like that here!! + g_byte_array_set_size(mcdserver_state.last_packet, 0); + //g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "$", 1); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) buf, len); + /* + csum = 0; + for(i = 0; i < len; i++) { + csum += buf[i]; + } + footer[0] = '#'; + footer[1] = tohex((csum >> 4) & 0xf); + footer[2] = tohex((csum) & 0xf); + g_byte_array_append(mcdserver_state.last_packet, footer, 3); + */ + mcd_put_buffer(mcdserver_state.last_packet->data, + mcdserver_state.last_packet->len); + + if (mcd_got_immediate_ack()) { + break; + } + } + return 0; +} + +bool mcd_got_immediate_ack(void) +{ + return true; +} + +void mcd_put_buffer(const uint8_t *buf, int len) +{ + /* + * XXX this blocks entire thread. Rewrite to use + * qemu_chr_fe_write and background I/O callbacks + */ + qemu_chr_fe_write_all(&mcdserver_system_state.chr, buf, len); +} + +void mcd_set_stop_cpu(CPUState *cpu) +{ + MCDProcess *p = mcd_get_cpu_process(cpu); + + if (!p->attached) { + /* + * Having a stop CPU corresponding to a process that is not attached + * confuses GDB. So we ignore the request. + */ + return; + } + + mcdserver_state.c_cpu = cpu; + mcdserver_state.g_cpu = cpu; +} + +MCDProcess *mcd_get_cpu_process(CPUState *cpu) +{ + return mcd_get_process(mcd_get_cpu_pid(cpu)); +} + +uint32_t mcd_get_cpu_pid(CPUState *cpu) +{ + if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) { + /* Return the default process' PID */ + int index = mcdserver_state.process_num - 1; + return mcdserver_state.processes[index].pid; + } + return cpu->cluster_index + 1; +} + +MCDProcess *mcd_get_process(uint32_t pid) +{ + int i; + + if (!pid) { + /* 0 means any process, we take the first one */ + return &mcdserver_state.processes[0]; + } + + for (i = 0; i < mcdserver_state.process_num; i++) { + if (mcdserver_state.processes[i].pid == pid) { + return &mcdserver_state.processes[i]; + } + } + + return NULL; +} + +CPUState *mcd_first_attached_cpu(void) +{ + CPUState *cpu = first_cpu; + MCDProcess *process = mcd_get_cpu_process(cpu); + + if (!process->attached) { + return mcd_next_attached_cpu(cpu); + } + + return cpu; +} + +CPUState *mcd_next_attached_cpu(CPUState *cpu) +{ + cpu = CPU_NEXT(cpu); + + while (cpu) { + if (mcd_get_cpu_process(cpu)->attached) { + break; + } + + cpu = CPU_NEXT(cpu); + } + + return cpu; +} \ No newline at end of file diff --git a/mcdstub/meson.build b/mcdstub/meson.build new file mode 100644 index 0000000000..f17e2f3e89 --- /dev/null +++ b/mcdstub/meson.build @@ -0,0 +1,25 @@ +# +# The main gdbstub still relies on per-build definitions of various +# types. The bits pushed to softmmu/user.c try to use guest agnostic +# types such as hwaddr. +# + +# We need to build the core mcd code via a library to be able to tweak +# cflags so: + +mcd_softmmu_ss = ss.source_set() + +# We build one version of the mcdstub, because it only needs to work for system emulation +mcd_softmmu_ss.add(files('mcdstub.c')) + +mcd_softmmu_ss = mcd_softmmu_ss.apply(config_host, strict: false) + +libmcd_softmmu = static_library('mcd_softmmu', + mcd_softmmu_ss.sources() + genh, + name_suffix: 'fa') + +mcd_softmmu = declare_dependency(link_whole: libmcd_softmmu) +softmmu_ss.add(mcd_softmmu) + +# this might cause problems because we don't support user mode +common_ss.add(files('mcd_syscalls.c')) diff --git a/meson.build b/meson.build index 21a1bc03f8..bd1d982522 100644 --- a/meson.build +++ b/meson.build @@ -3356,6 +3356,7 @@ subdir('crypto') subdir('ui') subdir('hw') subdir('gdbstub') +subdir('mcdstub') if enable_modules libmodulecommon = static_library('module-common', files('module-common.c') + genh, pic: true, c_args: '-DBUILD_DSO') diff --git a/qemu-options.hx b/qemu-options.hx index 9ce8a5b957..0c15125b92 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4414,6 +4414,31 @@ SRST (see the :ref:`GDB usage` chapter in the System Emulation Users Guide). ERST +DEF("mcd", HAS_ARG, QEMU_OPTION_mcd, \ + "-mcd dev accept mcd connection on 'dev'. (QEMU defaults to starting\n" + " the guest without waiting for a mcd client to connect; use -S too\n" + " if you want it to not start execution.)\n", + QEMU_ARCH_ALL) +SRST +``-mcd dev`` + Accept a mcd connection on device dev. Note that this option does not pause QEMU + execution -- if you want QEMU to not start the guest until you + connect with mcd and issue a ``run`` command, you will need to + also pass the ``-S`` option to QEMU. + + The most usual configuration is to listen on a local TCP socket:: + + -mcd tcp::1234 +ERST + +DEF("mcdd", 0, QEMU_OPTION_mcdd, \ + "-mcdd shorthand for -mcd tcp::" DEFAULT_MCDSTUB_PORT "\n", + QEMU_ARCH_ALL) +SRST +``-mcdd`` + Shorthand for -mcd tcp::1234, i.e. open a mcdserver on TCP port 1234 +ERST + DEF("d", HAS_ARG, QEMU_OPTION_d, \ "-d item1,... enable logging of specified items (use '-d help' for a list of log items)\n", QEMU_ARCH_ALL) diff --git a/softmmu/vl.c b/softmmu/vl.c index 3278f204ea..2d66f612a7 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -68,6 +68,7 @@ #include "sysemu/numa.h" #include "sysemu/hostmem.h" #include "exec/gdbstub.h" +#include "exec/mcdstub.h" #include "qemu/timer.h" #include "chardev/char.h" #include "qemu/bitmap.h" @@ -2662,6 +2663,14 @@ static void qemu_machine_creation_done(void) if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { exit(1); } + + if (foreach_device_config(DEV_MCD, mcdserver_start) < 0) { + /* + * starts the mcdserver if the mcd option was set + */ + exit(1); + } + if (!vga_interface_created && !default_vga && vga_interface_type != VGA_NONE) { warn_report("A -vga option was passed but this machine " From patchwork Fri Oct 6 09:05:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844284 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22cb2YsMz1yqF for ; Fri, 6 Oct 2023 20:07:11 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogmz-00082y-DL; Fri, 06 Oct 2023 05:06:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmr-0007zc-9T for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:21 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmo-0000sr-4O for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:21 -0400 Received: (qmail 19403 invoked by uid 484); 6 Oct 2023 09:06:15 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 4e-06 secs); 06 Oct 2023 09:06:15 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:14 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 03/29] TCP packet handling added Date: Fri, 6 Oct 2023 11:05:44 +0200 Message-Id: <20231006090610.26171-4-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 64 ++++- mcdstub/mcd_syscalls.c | 11 + mcdstub/mcdstub.c | 541 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 596 insertions(+), 20 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 7b0f4b0b36..5af705a12a 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -25,12 +25,42 @@ enum { */ typedef struct MCDProcess { + //this is probably what we would call a system (in qemu its a cluster) uint32_t pid; bool attached; char target_xml[1024]; } MCDProcess; +typedef void (*MCDCmdHandler)(GArray *params, void *user_ctx); +typedef struct MCDCmdParseEntry { + MCDCmdHandler handler; + const char *cmd; + bool cmd_startswith; + const char *schema; +} MCDCmdParseEntry; + +typedef enum MCDThreadIdKind { + GDB_ONE_THREAD = 0, + GDB_ALL_THREADS, /* One process, all threads */ + GDB_ALL_PROCESSES, + GDB_READ_THREAD_ERR +} MCDThreadIdKind; + +typedef union MCDCmdVariant { + const char *data; + uint8_t opcode; + unsigned long val_ul; + unsigned long long val_ull; + struct { + MCDThreadIdKind kind; + uint32_t pid; + uint32_t tid; + } thread_id; +} MCDCmdVariant; + +#define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) + /* * not sure for what this is used exactly @@ -41,10 +71,11 @@ enum RSState { RS_INACTIVE, RS_IDLE, RS_GETLINE, - RS_GETLINE_ESC, - RS_GETLINE_RLE, - RS_CHKSUM1, - RS_CHKSUM2, + RS_DATAEND, + //RS_GETLINE_ESC, + //RS_GETLINE_RLE, + //RS_CHKSUM1, + //RS_CHKSUM2, }; typedef struct MCDState { @@ -59,11 +90,13 @@ typedef struct MCDState { int line_csum; /* checksum at the end of the packet */ GByteArray *last_packet; int signal; - bool multiprocess; + //the next one is about stub compatibility and we should be able to assume this is true anyway + //bool multiprocess; MCDProcess *processes; int process_num; GString *str_buf; GByteArray *mem_buf; + // maybe we don't need those flags int sstep_flags; int supported_sstep_flags; } MCDState; @@ -128,8 +161,29 @@ uint32_t mcd_get_cpu_pid(CPUState *cpu); MCDProcess *mcd_get_process(uint32_t pid); CPUState *mcd_first_attached_cpu(void); CPUState *mcd_next_attached_cpu(CPUState *cpu); +void mcd_read_byte(uint8_t ch); +int mcd_handle_packet(const char *line_buf); +void mcd_put_strbuf(void); +void mcd_exit(int code); +void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd); +int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds); +int cmd_parse_params(const char *data, const char *schema, GArray *params); +void handle_continue(GArray *params, void *user_ctx); +void handle_gen_query(GArray *params, void *user_ctx); +void mcd_append_thread_id(CPUState *cpu, GString *buf); +int mcd_get_cpu_index(CPUState *cpu); +CPUState* mcd_get_cpu(uint32_t i_cpu_index); +void handle_query_cores(GArray *params, void *user_ctx); +void handle_query_system(GArray *params, void *user_ctx); +CPUState *get_first_cpu_in_process(MCDProcess *process); +CPUState *find_cpu(uint32_t thread_id); +void handle_core_open(GArray *params, void *user_ctx); +void handle_query_reset(GArray *params, void *user_ctx); +void handle_detach(GArray *params, void *user_ctx); +void mcd_continue(void); /* sycall handling */ void mcd_syscall_reset(void); +void mcd_disable_syscalls(void); #endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/mcd_syscalls.c b/mcdstub/mcd_syscalls.c index 663ffde1b6..dec0af51b7 100644 --- a/mcdstub/mcd_syscalls.c +++ b/mcdstub/mcd_syscalls.c @@ -12,9 +12,20 @@ typedef struct { int current_syscall_cb; } MCDSyscallState; +static enum { + MCD_SYS_UNKNOWN, + MCD_SYS_ENABLED, + MCD_SYS_DISABLED, +} mcd_syscall_mode; + static MCDSyscallState mcdserver_syscall_state; void mcd_syscall_reset(void) { mcdserver_syscall_state.current_syscall_cb = 0; +} + +void mcd_disable_syscalls(void) +{ + mcd_syscall_mode = MCD_SYS_DISABLED; } \ No newline at end of file diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index c68cab9391..75b38d910a 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -31,6 +31,9 @@ #include "chardev/char-fe.h" #include "monitor/monitor.h" +// just used for the xml_builtin stuff +//#include "exec/gdbstub.h" /* xml_builtin */ + typedef struct { CharBackend chr; //Chardev *mon_chr; @@ -40,6 +43,22 @@ MCDSystemState mcdserver_system_state; MCDState mcdserver_state; +static const MCDCmdParseEntry mcd_gen_query_table[] = { + // this is a list of all query commands. it gets iterated over only the handler of the matching command will get executed + { + .handler = handle_query_system, + .cmd = "system", + }, + { + .handler = handle_query_cores, + .cmd = "cores", + }, + { + .handler = handle_query_reset, + .cmd = "reset", + }, +}; + void mcd_init_mcdserver_state(void) { g_assert(!mcdserver_state.init); @@ -55,7 +74,7 @@ void mcd_init_mcdserver_state(void) * stepping so as to make single stepping like a typical ICE HW step. */ // TODO: - // this is weird and might be able to sit just like it is here with the same value as for gdb + // this is weird and we might not actually need it after all mcdserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; mcdserver_state.sstep_flags &= mcdserver_state.supported_sstep_flags; @@ -235,14 +254,343 @@ int mcd_chr_can_receive(void *opaque) void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) { - printf("incoming buffer: %s\n", buf); - char send_buffer[] = "shaking your hand"; - mcd_put_packet(send_buffer); - //int i; - /* + int i; + for (i = 0; i < size; i++) { - //TODO: some byte reading or idk gdb_read_byte(buf[i]); - }*/ + mcd_read_byte(buf[i]); + } +} + +void mcd_read_byte(uint8_t ch) +{ + uint8_t reply; + + if (mcdserver_state.last_packet->len) { + /* Waiting for a response to the last packet. If we see the start + of a new command then abandon the previous response. */ + if (ch == '-') { + //the previous packet was not akcnowledged + //trace_gdbstub_err_got_nack(); + //we are resending the last packet + mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); + } + else if (ch == '+') { + //the previous packet was acknowledged + //trace_gdbstub_io_got_ack(); + } + + if (ch == '+' || ch == '$') { + //either acknowledged or a new communication starts -> we discard previous communication + g_byte_array_set_size(mcdserver_state.last_packet, 0); + } + if (ch != '$') { + // we only continue if we are processing a new commant. otherwise we skip to ne next character in the packet which sould be a $ + return; + } + } + if (runstate_is_running()) { + /* when the CPU is running, we cannot do anything except stop + it when receiving a char */ + vm_stop(RUN_STATE_PAUSED); + } + else { + switch(mcdserver_state.state) { + case RS_IDLE: + if (ch == '$') { + /* start of command packet */ + mcdserver_state.line_buf_index = 0; + mcdserver_state.line_sum = 0; + mcdserver_state.state = RS_GETLINE; + } + else { + //new communication has to start with a $ + //trace_gdbstub_err_garbage(ch); + } + break; + case RS_GETLINE: + if (ch == '#') { + /* end of command, start of checksum*/ + mcdserver_state.state = RS_DATAEND; + } + else if (mcdserver_state.line_buf_index >= sizeof(mcdserver_state.line_buf) - 1) { + //the input string is too long for the linebuffer! + //trace_gdbstub_err_overrun(); + mcdserver_state.state = RS_IDLE; + } + else { + /* unescaped command character */ + //this means the character is part of the real content fo the packet and we copy it to the line_buf + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = ch; + mcdserver_state.line_sum += ch; + } + break; + case RS_DATAEND: + // we are now done with copying the data and in the suffix of the packet + // TODO: maybe wanna implement a checksum or sth like the gdb protocol has + + if (ch == '~') { + // ~ indicates that there is an additional package coming + //acknowledged -> send + + reply = '+'; + mcd_put_buffer(&reply, 1); + mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); + } + else if (ch == '|') { + //acknowledged -> send + + // | indicates that there is no additional package coming + reply = '+'; + mcd_put_buffer(&reply, 1); + mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); + } + else { + //trace_gdbstub_err_checksum_incorrect(mcdserver_state.line_sum, mcdserver_state.line_csum); + //not acknowledged -> send - + reply = '-'; + mcd_put_buffer(&reply, 1); + //waiting for package to get resent + mcdserver_state.state = RS_IDLE; + } + break; + default: + abort(); + } + } +} + +int mcd_handle_packet(const char *line_buf) +{ + //decides what function (handler) to call depending on what the first character in the line_buf is! + const MCDCmdParseEntry *cmd_parser = NULL; + + //trace_gdbstub_io_command(line_buf); + + switch (line_buf[0]) { + case 'i': + //handshake + mcd_put_packet("shaking your hand"); + //gdb_put_packet("OK"); + break; + case 'c': + //go command + { + static const MCDCmdParseEntry continue_cmd_desc = { + .handler = handle_continue, + .cmd = "c", + //.cmd_startswith = 1, + //.schema = "L0" + }; + cmd_parser = &continue_cmd_desc; + } + break; + case 'k': + // kill qemu completely + error_report("QEMU: Terminated via MCDstub"); + mcd_exit(0); + exit(0); + case 'q': + //query inquiry + { + static const MCDCmdParseEntry gen_query_cmd_desc = { + .handler = handle_gen_query, + .cmd = "q", + //.cmd_startswith = 1, + .schema = "ss" + }; + cmd_parser = &gen_query_cmd_desc; + } + break; + case 'H': + //current alias for open core, later this will probably be a part of the 'i' requests + { + static const MCDCmdParseEntry gen_core_open = { + .handler = handle_core_open, + .cmd = "H", + //.cmd_startswith = 1, + .schema = "ss" + }; + cmd_parser = &gen_core_open; + } + break; + case 'D': + { + static const MCDCmdParseEntry detach_cmd_desc = { + .handler = handle_detach, + .cmd = "D", + //.cmd_startswith = 1, + //.schema = "?.l0" + }; + cmd_parser = &detach_cmd_desc; + } + break; + default: + //could not perform the command (because its unknown) + mcd_put_packet(""); + break; + } + + if (cmd_parser) { + //now parse commands and run the selected function (handler) + run_cmd_parser(line_buf, cmd_parser); + } + + return RS_IDLE; +} + +void handle_continue(GArray *params, void *user_ctx) +{ + /* + if (params->len) { + gdb_set_cpu_pc(get_param(params, 0)->val_ull); + } + + mcdserver_state.signal = 0; + gdb_continue(); + */ +} + +void handle_gen_query(GArray *params, void *user_ctx) +{ + if (!params->len) { + return; + } + //now iterate over all possible query functions and execute the right one + if (process_string_cmd(NULL, get_param(params, 0)->data, + mcd_gen_query_table, + ARRAY_SIZE(mcd_gen_query_table))) { + mcd_put_packet(""); + } +} + +void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) +{ + if (!data) { + return; + } + + g_string_set_size(mcdserver_state.str_buf, 0); + g_byte_array_set_size(mcdserver_state.mem_buf, 0); + + /* In case there was an error during the command parsing we must + * send a NULL packet to indicate the command is not supported */ + if (process_string_cmd(NULL, data, cmd, 1)) { + mcd_put_packet(""); + } +} + +int cmd_parse_params(const char *data, const char *schema, GArray *params) +{ + MCDCmdVariant this_param; + this_param.data = data; + g_array_append_val(params, this_param); + /* + const char *curr_schema, *curr_data; + + g_assert(schema); + g_assert(params->len == 0); + + curr_schema = schema; + curr_data = data; + while (curr_schema[0] && curr_schema[1] && *curr_data) { + GdbCmdVariant this_param; + + switch (curr_schema[0]) { + case 'l': + if (qemu_strtoul(curr_data, &curr_data, 16, + &this_param.val_ul)) { + return -EINVAL; + } + curr_data = cmd_next_param(curr_data, curr_schema[1]); + g_array_append_val(params, this_param); + break; + case 'L': + if (qemu_strtou64(curr_data, &curr_data, 16, + (uint64_t *)&this_param.val_ull)) { + return -EINVAL; + } + curr_data = cmd_next_param(curr_data, curr_schema[1]); + g_array_append_val(params, this_param); + break; + case 's': + this_param.data = curr_data; + curr_data = cmd_next_param(curr_data, curr_schema[1]); + g_array_append_val(params, this_param); + break; + case 'o': + this_param.opcode = *(uint8_t *)curr_data; + curr_data = cmd_next_param(curr_data, curr_schema[1]); + g_array_append_val(params, this_param); + break; + case 't': + this_param.thread_id.kind = + read_thread_id(curr_data, &curr_data, + &this_param.thread_id.pid, + &this_param.thread_id.tid); + curr_data = cmd_next_param(curr_data, curr_schema[1]); + g_array_append_val(params, this_param); + break; + case '?': + curr_data = cmd_next_param(curr_data, curr_schema[1]); + break; + default: + return -EINVAL; + } + curr_schema += 2; + } + */ + return 0; + +} + +int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds) +{ + int i; + g_autoptr(GArray) params = g_array_new(false, true, sizeof(MCDCmdVariant)); + + if (!cmds) { + return -1; + } + + for (i = 0; i < num_cmds; i++) { + const MCDCmdParseEntry *cmd = &cmds[i]; + //terminate if we don't have handler and cmd + g_assert(cmd->handler && cmd->cmd); + + // if data and command are different continue + if (strncmp(data, cmd->cmd, strlen(cmd->cmd))) { + continue; + } + + // if a schema is provided we need to extract parameters from the data string + if (cmd->schema) { + //currently doing nothing + if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, params)) { + return -1; + } + } + + // the correct handler function is called + cmd->handler(params, user_ctx); + return 0; + } + + return -1; +} + +void mcd_exit(int code) +{ + char buf[4]; + + if (!mcdserver_state.init) { + return; + } + + //trace_gdbstub_op_exiting((uint8_t)code); + + //need to check what is sent here and dapt it to my needs + snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code); + mcd_put_packet(buf); + + qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); } void mcd_chr_event(void *opaque, QEMUChrEvent event) @@ -392,6 +740,11 @@ int mcd_put_packet(const char *buf) return mcd_put_packet_binary(buf, strlen(buf), false); } +void mcd_put_strbuf(void) +{ + mcd_put_packet(mcdserver_state.str_buf->str); +} + int mcd_put_packet_binary(const char *buf, int len, bool dump) { //int csum, i; @@ -405,9 +758,10 @@ int mcd_put_packet_binary(const char *buf, int len, bool dump) for(;;) { //super interesting if we want a chekcsum or something like that here!! g_byte_array_set_size(mcdserver_state.last_packet, 0); - //g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "$", 1); - g_byte_array_append(mcdserver_state.last_packet, - (const uint8_t *) buf, len); + g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "$", 1); + g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) buf, len); + g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "#", 1); + g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "|", 1); /* csum = 0; for(i = 0; i < len; i++) { @@ -418,8 +772,7 @@ int mcd_put_packet_binary(const char *buf, int len, bool dump) footer[2] = tohex((csum) & 0xf); g_byte_array_append(mcdserver_state.last_packet, footer, 3); */ - mcd_put_buffer(mcdserver_state.last_packet->data, - mcdserver_state.last_packet->len); + mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); if (mcd_got_immediate_ack()) { break; @@ -453,7 +806,7 @@ void mcd_set_stop_cpu(CPUState *cpu) */ return; } - + //FIXME: we probably can delete this because in the opern_core function we set these two anyway mcdserver_state.c_cpu = cpu; mcdserver_state.g_cpu = cpu; } @@ -470,6 +823,7 @@ uint32_t mcd_get_cpu_pid(CPUState *cpu) int index = mcdserver_state.process_num - 1; return mcdserver_state.processes[index].pid; } + // TODO: maybe +1 because we start numbering at 1 return cpu->cluster_index + 1; } @@ -491,6 +845,19 @@ MCDProcess *mcd_get_process(uint32_t pid) return NULL; } +CPUState* mcd_get_cpu(uint32_t i_cpu_index) { + CPUState *cpu = first_cpu; + + while (cpu) { + if (cpu->cpu_index == i_cpu_index) { + return cpu; + } + cpu = mcd_next_attached_cpu(cpu); + } + + return cpu; +} + CPUState *mcd_first_attached_cpu(void) { CPUState *cpu = first_cpu; @@ -516,4 +883,148 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu) } return cpu; -} \ No newline at end of file +} +/* +void handle_query_first_threads(GArray *params, void *user_ctx) +{ + // chache the first cpu + mcdserver_state.query_cpu = mcd_first_attached_cpu(); + // new answer over tcp + handle_query_threads(params, user_ctx); +} + +void handle_query_threads(GArray *params, void *user_ctx) +{ + if (!mcdserver_state.query_cpu) { + // send packet back that that there is no more threads + //gdb_put_packet("l"); + return; + } + + g_string_assign(mcdserver_state.str_buf, "m"); + mcd_append_thread_id(mcdserver_state.query_cpu, mcdserver_state.str_buf); + mcd_put_strbuf(); + mcdserver_state.query_cpu = mcd_next_attached_cpu(mcdserver_state.query_cpu); +} + + +void mcd_append_thread_id(CPUState *cpu, GString *buf) +{ + g_string_append_printf(buf, "p%02x.%02x", mcd_get_cpu_pid(cpu), mcd_get_cpu_index(cpu)); +} +*/ + +int mcd_get_cpu_index(CPUState *cpu) +{ + // TODO: maybe plus 1 because we start numbering at 1 + return cpu->cpu_index + 1; +} + +CPUState *get_first_cpu_in_process(MCDProcess *process) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (mcd_get_cpu_pid(cpu) == process->pid) { + return cpu; + } + } + + return NULL; +} + +CPUState *find_cpu(uint32_t thread_id) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + if (mcd_get_cpu_index(cpu) == thread_id) { + return cpu; + } + } + + return NULL; +} + +void handle_query_system(GArray *params, void *user_ctx) { + mcd_put_packet("qemu-system"); +} + +void handle_query_cores(GArray *params, void *user_ctx) { + //TODO: add cluster support: in gdb each inferior (process) handles one cluster we might want to have sth similar here + + // get first cpu + CPUState *cpu = mcd_first_attached_cpu(); + if (!cpu) { + return; + } + + ObjectClass *oc = object_get_class(OBJECT(cpu)); + const char *cpu_model = object_class_get_name(oc); + + CPUClass *cc = CPU_GET_CLASS(cpu); + gchar *arch = cc->gdb_arch_name(cpu); + + //const char *cpu_name = object_get_canonical_path_component(OBJECT(cpu)); + //int process_id = mcd_get_cpu_pid(cpu); + //int cpu_index = cpu->cpu_index; + //int cpu_cluster = cpu->cluster_index; + int nr_cores = cpu->nr_cores; + + g_string_append_printf(mcdserver_state.str_buf, "device=\"qemu-%s-device\",core=\"%s\",nr_cores=\"%d\"", arch, cpu_model, nr_cores); + mcd_put_strbuf(); + g_free(arch); +} + +void handle_core_open(GArray *params, void *user_ctx) { + // get the cpu whith the given id + uint32_t cpu_id = atoi(get_param(params, 0)->data); + + CPUState *cpu = mcd_get_cpu(cpu_id); + + // select the the cpu as the current cpu for all request from the mcd interface + mcdserver_state.c_cpu = cpu; + mcdserver_state.g_cpu = cpu; + +} + +void handle_query_reset(GArray *params, void *user_ctx) { + // resetting has to be done over a monitor (look ar Rcmd) so we tell MCD that we can reset but this still need to be implemented + // we only support one reset over this monitor and that would be a fully "system_restart" + mcd_put_packet("info_rst=\"results in a full system restart\""); +} + +void handle_detach(GArray *params, void *user_ctx) { + uint32_t pid = 1; + MCDProcess *process = mcd_get_process(pid); + + // 1. cleanup + // gdb_process_breakpoint_remove_all(process); + + // 2. detach + process->attached = false; + + // reset current cpus + // TODO: if we don't use c_cpu we can delete this + // this also checks to only reset THIS process we also probably don't need this since we only got one process! + if (pid == mcd_get_cpu_pid(mcdserver_state.c_cpu)) { + mcdserver_state.c_cpu = mcd_first_attached_cpu(); + } + + if (pid == mcd_get_cpu_pid(mcdserver_state.g_cpu)) { + mcdserver_state.g_cpu = mcd_first_attached_cpu(); + } + + if (!mcdserver_state.c_cpu) { + /* No more process attached */ + mcd_disable_syscalls(); + mcd_continue(); + } +} + +void mcd_continue(void) +{ + if (!runstate_needs_reset()) { + vm_start(); + } +} From patchwork Fri Oct 6 09:05:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844297 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dx2RM3z20Vp for ; Fri, 6 Oct 2023 20:08:21 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogmx-00082N-95; Fri, 06 Oct 2023 05:06:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmr-0007zb-9E for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:21 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmp-0000tA-7s for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:21 -0400 Received: (qmail 19425 invoked by uid 484); 6 Oct 2023 09:06:16 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.071552 secs); 06 Oct 2023 09:06:16 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:15 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 04/29] queries for resets and triggers added Date: Fri, 6 Oct 2023 11:05:45 +0200 Message-Id: <20231006090610.26171-5-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 9 +++++++++ mcdstub/mcdstub.c | 19 ++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 5af705a12a..ce3bffe7e6 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -11,6 +11,14 @@ #define MAX_PACKET_LENGTH 1024 +// trigger defines +#define MCD_TRIG_TYPE_IP 0x00000001 +#define MCD_TRIG_TYPE_READ 0x00000002 +#define MCD_TRIG_TYPE_WRITE 0x00000004 +#define MCD_TRIG_TYPE_RW 0x00000008 +#define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 +#define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 + /* * lookuptable for transmitted signals */ @@ -180,6 +188,7 @@ CPUState *find_cpu(uint32_t thread_id); void handle_core_open(GArray *params, void *user_ctx); void handle_query_reset(GArray *params, void *user_ctx); void handle_detach(GArray *params, void *user_ctx); +void handle_query_trigger(GArray *params, void *user_ctx); void mcd_continue(void); /* sycall handling */ diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 75b38d910a..1d066c8169 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -57,6 +57,10 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { .handler = handle_query_reset, .cmd = "reset", }, + { + .handler = handle_query_trigger, + .cmd = "trigger", + }, }; void mcd_init_mcdserver_state(void) @@ -991,7 +995,8 @@ void handle_core_open(GArray *params, void *user_ctx) { void handle_query_reset(GArray *params, void *user_ctx) { // resetting has to be done over a monitor (look ar Rcmd) so we tell MCD that we can reset but this still need to be implemented // we only support one reset over this monitor and that would be a fully "system_restart" - mcd_put_packet("info_rst=\"results in a full system restart\""); + mcd_put_packet("nr=\"3\",info=\"0,full_system_reset;1,gpr_reset;2,memory_reset;\""); + // TODO: we still need to implement the gpr and memory reset here! } void handle_detach(GArray *params, void *user_ctx) { @@ -1022,6 +1027,18 @@ void handle_detach(GArray *params, void *user_ctx) { } } +void handle_query_trigger(GArray *params, void *user_ctx) { + // set the type, option and action bitmask and send it + + uint32_t type = (MCD_TRIG_TYPE_IP | MCD_TRIG_TYPE_READ | MCD_TRIG_TYPE_WRITE | MCD_TRIG_TYPE_RW); + uint32_t option = (MCD_TRIG_OPT_DATA_IS_CONDITION); + uint32_t action = (MCD_TRIG_ACTION_DBG_DEBUG); + uint32_t nr_trigger = 4; + + g_string_append_printf(mcdserver_state.str_buf, "nr=\"%d\",info=\"%d;%d;%d;\"", nr_trigger, type, option, action); + mcd_put_strbuf(); +} + void mcd_continue(void) { if (!runstate_needs_reset()) { From patchwork Fri Oct 6 09:05:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844307 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22gm6JXtz1yqF for ; Fri, 6 Oct 2023 20:09:56 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogn7-00087D-Rg; Fri, 06 Oct 2023 05:06:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmv-00082K-Ed for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:26 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmr-0000tR-3H for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:24 -0400 Received: (qmail 19447 invoked by uid 484); 6 Oct 2023 09:06:18 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.073842 secs); 06 Oct 2023 09:06:18 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:17 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 05/29] queries for memory spaces and register groups added Date: Fri, 6 Oct 2023 11:05:46 +0200 Message-Id: <20231006090610.26171-6-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 29 +++--- mcdstub/mcdstub.c | 240 ++++++++++++++++++++++++-------------------- 2 files changed, 147 insertions(+), 122 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index ce3bffe7e6..8df535e92a 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -19,21 +19,13 @@ #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 -/* - * lookuptable for transmitted signals - */ - -enum { - MCD_SIGNAL_HANDSHAKE = 0 -}; - /* * struct for an MCD Process, each process can establish one connection */ typedef struct MCDProcess { - //this is probably what we would call a system (in qemu its a cluster) + //this is a relict from the gdb process, we might be able to delete this uint32_t pid; bool attached; @@ -65,6 +57,9 @@ typedef union MCDCmdVariant { uint32_t pid; uint32_t tid; } thread_id; + + // used to synchronize stub and dll for functions with multiple packets + int index_handle; } MCDCmdVariant; #define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) @@ -88,9 +83,7 @@ enum RSState { typedef struct MCDState { bool init; /* have we been initialised? */ - CPUState *c_cpu; /* current CPU for step/continue ops */ - CPUState *g_cpu; /* current CPU for other ops */ - CPUState *query_cpu; /* for q{f|s}ThreadInfo */ + CPUState *c_cpu; /* current CPU for everything */ enum RSState state; /* parsing state */ char line_buf[MAX_PACKET_LENGTH]; int line_buf_index; @@ -107,11 +100,19 @@ typedef struct MCDState { // maybe we don't need those flags int sstep_flags; int supported_sstep_flags; + + // my stuff + GArray *reggroups; } MCDState; /* lives in main mcdstub.c */ extern MCDState mcdserver_state; +typedef struct mcd_reg_group_st { + const char *name; + const char *id; +} mcd_reg_group_st; + // Inline utility function, convert from int to hex and back @@ -190,6 +191,10 @@ void handle_query_reset(GArray *params, void *user_ctx); void handle_detach(GArray *params, void *user_ctx); void handle_query_trigger(GArray *params, void *user_ctx); void mcd_continue(void); +void handle_query_mem_spaces(GArray *params, void *user_ctx); +void handle_query_reg_groups_f(GArray *params, void *user_ctx); +void handle_query_reg_groups_c(GArray *params, void *user_ctx); +void handle_init(GArray *params, void *user_ctx); /* sycall handling */ void mcd_syscall_reset(void); diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 1d066c8169..9817f0893c 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -33,6 +33,7 @@ // just used for the xml_builtin stuff //#include "exec/gdbstub.h" /* xml_builtin */ +#include "hw/core/sysemu-cpu-ops.h" typedef struct { CharBackend chr; @@ -61,6 +62,19 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { .handler = handle_query_trigger, .cmd = "trigger", }, + { + .handler = handle_query_mem_spaces, + .cmd = "memory", + }, + { + .handler = handle_query_reg_groups_f, + .cmd = "reggroupf", + }, + { + .handler = handle_query_reg_groups_c, + .cmd = "reggroupc", + .schema = "i", + }, }; void mcd_init_mcdserver_state(void) @@ -314,6 +328,8 @@ void mcd_read_byte(uint8_t ch) case RS_GETLINE: if (ch == '#') { /* end of command, start of checksum*/ + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0; + //mcdserver_state.line_sum += ch; mcdserver_state.state = RS_DATAEND; } else if (mcdserver_state.line_buf_index >= sizeof(mcdserver_state.line_buf) - 1) { @@ -363,25 +379,26 @@ void mcd_read_byte(uint8_t ch) int mcd_handle_packet(const char *line_buf) { - //decides what function (handler) to call depending on what the first character in the line_buf is! + // decides what function (handler) to call depending on what the first character in the line_buf is! const MCDCmdParseEntry *cmd_parser = NULL; - //trace_gdbstub_io_command(line_buf); - switch (line_buf[0]) { case 'i': - //handshake - mcd_put_packet("shaking your hand"); - //gdb_put_packet("OK"); + // handshake and lookup initialization + { + static const MCDCmdParseEntry continue_cmd_desc = { + .handler = handle_init, + .cmd = "i", + }; + cmd_parser = &continue_cmd_desc; + } break; case 'c': - //go command + // go command { static const MCDCmdParseEntry continue_cmd_desc = { .handler = handle_continue, .cmd = "c", - //.cmd_startswith = 1, - //.schema = "L0" }; cmd_parser = &continue_cmd_desc; } @@ -397,8 +414,7 @@ int mcd_handle_packet(const char *line_buf) static const MCDCmdParseEntry gen_query_cmd_desc = { .handler = handle_gen_query, .cmd = "q", - //.cmd_startswith = 1, - .schema = "ss" + .schema = "s" }; cmd_parser = &gen_query_cmd_desc; } @@ -409,8 +425,7 @@ int mcd_handle_packet(const char *line_buf) static const MCDCmdParseEntry gen_core_open = { .handler = handle_core_open, .cmd = "H", - //.cmd_startswith = 1, - .schema = "ss" + .schema = "s" }; cmd_parser = &gen_core_open; } @@ -420,20 +435,18 @@ int mcd_handle_packet(const char *line_buf) static const MCDCmdParseEntry detach_cmd_desc = { .handler = handle_detach, .cmd = "D", - //.cmd_startswith = 1, - //.schema = "?.l0" }; cmd_parser = &detach_cmd_desc; } break; default: - //could not perform the command (because its unknown) + // could not perform the command (because its unknown) mcd_put_packet(""); break; } if (cmd_parser) { - //now parse commands and run the selected function (handler) + // now parse commands and run the selected function (handler) run_cmd_parser(line_buf, cmd_parser); } @@ -484,63 +497,16 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) int cmd_parse_params(const char *data, const char *schema, GArray *params) { MCDCmdVariant this_param; - this_param.data = data; - g_array_append_val(params, this_param); - /* - const char *curr_schema, *curr_data; - g_assert(schema); - g_assert(params->len == 0); - - curr_schema = schema; - curr_data = data; - while (curr_schema[0] && curr_schema[1] && *curr_data) { - GdbCmdVariant this_param; - - switch (curr_schema[0]) { - case 'l': - if (qemu_strtoul(curr_data, &curr_data, 16, - &this_param.val_ul)) { - return -EINVAL; - } - curr_data = cmd_next_param(curr_data, curr_schema[1]); - g_array_append_val(params, this_param); - break; - case 'L': - if (qemu_strtou64(curr_data, &curr_data, 16, - (uint64_t *)&this_param.val_ull)) { - return -EINVAL; - } - curr_data = cmd_next_param(curr_data, curr_schema[1]); - g_array_append_val(params, this_param); - break; - case 's': - this_param.data = curr_data; - curr_data = cmd_next_param(curr_data, curr_schema[1]); - g_array_append_val(params, this_param); - break; - case 'o': - this_param.opcode = *(uint8_t *)curr_data; - curr_data = cmd_next_param(curr_data, curr_schema[1]); - g_array_append_val(params, this_param); - break; - case 't': - this_param.thread_id.kind = - read_thread_id(curr_data, &curr_data, - &this_param.thread_id.pid, - &this_param.thread_id.tid); - curr_data = cmd_next_param(curr_data, curr_schema[1]); - g_array_append_val(params, this_param); - break; - case '?': - curr_data = cmd_next_param(curr_data, curr_schema[1]); - break; - default: - return -EINVAL; - } - curr_schema += 2; + if (schema[0] == 's') { + this_param.data = data; + g_array_append_val(params, this_param); } - */ + else if (schema[0] == 'i') { + this_param.index_handle = atoi(data); + g_array_append_val(params, this_param); + } + return 0; } @@ -566,7 +532,7 @@ int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry // if a schema is provided we need to extract parameters from the data string if (cmd->schema) { - //currently doing nothing + // this only gets the data from data beginning after the command name if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, params)) { return -1; } @@ -610,7 +576,6 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event) } s->c_cpu = mcd_first_attached_cpu(); - s->g_cpu = s->c_cpu; vm_stop(RUN_STATE_PAUSED); //TODO: this might not be necessary @@ -812,7 +777,6 @@ void mcd_set_stop_cpu(CPUState *cpu) } //FIXME: we probably can delete this because in the opern_core function we set these two anyway mcdserver_state.c_cpu = cpu; - mcdserver_state.g_cpu = cpu; } MCDProcess *mcd_get_cpu_process(CPUState *cpu) @@ -888,35 +852,6 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu) return cpu; } -/* -void handle_query_first_threads(GArray *params, void *user_ctx) -{ - // chache the first cpu - mcdserver_state.query_cpu = mcd_first_attached_cpu(); - // new answer over tcp - handle_query_threads(params, user_ctx); -} - -void handle_query_threads(GArray *params, void *user_ctx) -{ - if (!mcdserver_state.query_cpu) { - // send packet back that that there is no more threads - //gdb_put_packet("l"); - return; - } - - g_string_assign(mcdserver_state.str_buf, "m"); - mcd_append_thread_id(mcdserver_state.query_cpu, mcdserver_state.str_buf); - mcd_put_strbuf(); - mcdserver_state.query_cpu = mcd_next_attached_cpu(mcdserver_state.query_cpu); -} - - -void mcd_append_thread_id(CPUState *cpu, GString *buf) -{ - g_string_append_printf(buf, "p%02x.%02x", mcd_get_cpu_pid(cpu), mcd_get_cpu_index(cpu)); -} -*/ int mcd_get_cpu_index(CPUState *cpu) { @@ -950,6 +885,34 @@ CPUState *find_cpu(uint32_t thread_id) return NULL; } +void handle_init(GArray *params, void *user_ctx) { + CPUState *cpu = mcdserver_state.c_cpu; + CPUClass *cc = CPU_GET_CLASS(cpu); + + gchar *arch = cc->gdb_arch_name(cpu); + + // store reg groups + if (strcmp(arch, "arm")==0) { + // at the moment we just assume there are 3 spaces (gpr, per and debug) + // TODO: this might cause a memory leak when called a second time -> maybe free the Garray first + mcdserver_state.reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); + + mcd_reg_group_st group1 = { .name = "GPR Registers", .id = "1" }; + g_array_append_vals(mcdserver_state.reggroups, (gconstpointer)&group1, 1); + + mcd_reg_group_st group2 = { .name = "CP15 Registers", .id = "2" }; + g_array_append_vals(mcdserver_state.reggroups, (gconstpointer)&group2, 1); + } + else { + // we don't support other architectures + assert(1); + } + g_free(arch); + + // the mcdserver is set up and we return the handshake + mcd_put_packet("shaking your hand"); +} + void handle_query_system(GArray *params, void *user_ctx) { mcd_put_packet("qemu-system"); } @@ -988,7 +951,6 @@ void handle_core_open(GArray *params, void *user_ctx) { // select the the cpu as the current cpu for all request from the mcd interface mcdserver_state.c_cpu = cpu; - mcdserver_state.g_cpu = cpu; } @@ -1016,10 +978,6 @@ void handle_detach(GArray *params, void *user_ctx) { mcdserver_state.c_cpu = mcd_first_attached_cpu(); } - if (pid == mcd_get_cpu_pid(mcdserver_state.g_cpu)) { - mcdserver_state.g_cpu = mcd_first_attached_cpu(); - } - if (!mcdserver_state.c_cpu) { /* No more process attached */ mcd_disable_syscalls(); @@ -1035,7 +993,7 @@ void handle_query_trigger(GArray *params, void *user_ctx) { uint32_t action = (MCD_TRIG_ACTION_DBG_DEBUG); uint32_t nr_trigger = 4; - g_string_append_printf(mcdserver_state.str_buf, "nr=\"%d\",info=\"%d;%d;%d;\"", nr_trigger, type, option, action); + g_string_printf(mcdserver_state.str_buf, "nr=\"%d\",info=\"%d;%d;%d;\"", nr_trigger, type, option, action); mcd_put_strbuf(); } @@ -1045,3 +1003,65 @@ void mcd_continue(void) vm_start(); } } + +void handle_query_mem_spaces(GArray *params, void *user_ctx) { + // this returns the address spaces + // first we check if this is an arm architecture + // if it is arm we assume that if there are 2 address spaces, these are secure and non-secure (EL3 and EL0 for 64 bit) + CPUState *cpu = mcdserver_state.c_cpu; + CPUClass *cc = CPU_GET_CLASS(cpu); + + int nr_address_spaces = cpu->num_ases; + gchar *arch = cc->gdb_arch_name(cpu); + + if (strcmp(arch, "arm")==0) { + // we got secure and non-secure + g_string_printf(mcdserver_state.str_buf, "Non Secure=id:1;type:34;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); + g_string_append_printf(mcdserver_state.str_buf, "Physical (Non Secure)=id:2;type:18;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); + if (nr_address_spaces==2) { + g_string_append_printf(mcdserver_state.str_buf, "Secure=id:3;type:34;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); + g_string_append_printf(mcdserver_state.str_buf, "Physical (Secure)=id:4;type:18;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); + } + + // provide register spaces + // TODO: get dynamically how the per (CP15) space is called + g_string_append_printf(mcdserver_state.str_buf, "GPR Registers=id:5;type:1;bpm:64;i:1;e:1;min:0;max:-1;sao:0;."); + g_string_append_printf(mcdserver_state.str_buf, "CP15 Registers=id:6;type:1;bpm:32;i:1;e:1;min:0;max:-1;sao:0;."); //<-- per registers + //g_string_append_printf(mcdserver_state.str_buf, "CP14 Registers=type:1;bpm:32;i:1;e:1;min:0;max:-1;sao:0;."); // <-- debug registers + } + else { + // we don't support other architectures + assert(1); + } + g_free(arch); + mcd_put_strbuf(); +} + +void handle_query_reg_groups_f(GArray *params, void *user_ctx) { + // send the first reg group + mcd_reg_group_st group = g_array_index(mcdserver_state.reggroups, mcd_reg_group_st, 0); + g_string_printf(mcdserver_state.str_buf, "1!id=%s.name=%s.", group.id, group.name); + mcd_put_strbuf(); +} + +void handle_query_reg_groups_c(GArray *params, void *user_ctx) { + // this funcitons send all reg groups exept for the first + // 1. get parameter + int query_index = get_param(params, 0)->index_handle; + + // 2. check weather this was the last reg group + int nb_groups = mcdserver_state.reggroups->len; + if (query_index+1 == nb_groups) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); + } + else { + // provides + g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); + } + + // 3. send the correct reggroup + mcd_reg_group_st group = g_array_index(mcdserver_state.reggroups, mcd_reg_group_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "id=%s.name=%s.", group.id, group.name); + mcd_put_strbuf(); +} From patchwork Fri Oct 6 09:05:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844293 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dZ5YhVz1yqH for ; Fri, 6 Oct 2023 20:08:02 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogn1-00083C-8E; Fri, 06 Oct 2023 05:06:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmv-00082J-ES for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:25 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmr-0000tp-LB for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:24 -0400 Received: (qmail 19469 invoked by uid 484); 6 Oct 2023 09:06:19 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.071756 secs); 06 Oct 2023 09:06:19 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:18 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 06/29] query for registers added Date: Fri, 6 Oct 2023 11:05:47 +0200 Message-Id: <20231006090610.26171-7-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 55 +++++-- mcdstub/mcdstub.c | 320 ++++++++++++++++++++++++++++++++++++++--- target/arm/meson.build | 1 + 3 files changed, 344 insertions(+), 32 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 8df535e92a..45ba1ca8cb 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -8,6 +8,8 @@ #include "exec/cpu-common.h" #include "chardev/char.h" +// just used for the register xml files +#include "exec/gdbstub.h" /* xml_builtin */ #define MAX_PACKET_LENGTH 1024 @@ -19,6 +21,15 @@ #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 +// GDB stuff thats needed for GDB function, which we use +typedef struct GDBRegisterState { + int base_reg; + int num_regs; + gdb_get_reg_cb get_reg; + gdb_set_reg_cb set_reg; + const char *xml; + struct GDBRegisterState *next; +} GDBRegisterState; /* * struct for an MCD Process, each process can establish one connection @@ -75,10 +86,6 @@ enum RSState { RS_IDLE, RS_GETLINE, RS_DATAEND, - //RS_GETLINE_ESC, - //RS_GETLINE_RLE, - //RS_CHKSUM1, - //RS_CHKSUM2, }; typedef struct MCDState { @@ -103,6 +110,7 @@ typedef struct MCDState { // my stuff GArray *reggroups; + GArray *registers; } MCDState; /* lives in main mcdstub.c */ @@ -110,9 +118,34 @@ extern MCDState mcdserver_state; typedef struct mcd_reg_group_st { const char *name; - const char *id; + uint32_t id; } mcd_reg_group_st; +typedef struct xml_attrib { + char argument[64]; + char value[64]; +} xml_attrib; + +typedef struct mcd_reg_st { + // xml info + char name[64]; + char group[64]; + char type[64]; + uint32_t bitsize; + uint32_t id; + // mcd metadata + uint32_t mcd_reg_group_id; + uint32_t mcd_mem_space_id; + uint32_t mcd_reg_type; + uint32_t mcd_hw_thread_id; + // data for op-code + uint8_t cp; + uint8_t crn; + uint8_t crm; + uint8_t opc0; // <- might not be needed! + uint8_t opc1; + uint8_t opc2; +} mcd_reg_st; // Inline utility function, convert from int to hex and back @@ -139,12 +172,6 @@ static inline int tohex(int v) } } - -/*old functions -void mcd_init_mcdserver_state(void); -int mcd_open_tcp_socket(int tcp_port); -int mcd_extract_tcp_port_num(const char *in_string, char *out_string); -*/ #ifndef _WIN32 void mcd_sigterm_handler(int signal); #endif @@ -194,10 +221,16 @@ void mcd_continue(void); void handle_query_mem_spaces(GArray *params, void *user_ctx); void handle_query_reg_groups_f(GArray *params, void *user_ctx); void handle_query_reg_groups_c(GArray *params, void *user_ctx); +void handle_query_regs_f(GArray *params, void *user_ctx); +void handle_query_regs_c(GArray *params, void *user_ctx); void handle_init(GArray *params, void *user_ctx); +void parse_reg_xml(const char *xml, int size); /* sycall handling */ void mcd_syscall_reset(void); void mcd_disable_syscalls(void); +// helpers +int int_cmp(gconstpointer a, gconstpointer b); + #endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 9817f0893c..81026a42a1 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -8,7 +8,6 @@ #include "qemu/cutils.h" #include "qemu/module.h" #include "qemu/error-report.h" -//#include "trace.h" #include "exec/mcdstub.h" #include "mcdstub/syscalls.h" #include "hw/cpu/cluster.h" @@ -31,8 +30,10 @@ #include "chardev/char-fe.h" #include "monitor/monitor.h" -// just used for the xml_builtin stuff -//#include "exec/gdbstub.h" /* xml_builtin */ +//architecture specific stuff +#include "target/arm/mcdstub.h" + +// FIXME: delete the following line and check if it worked #include "hw/core/sysemu-cpu-ops.h" typedef struct { @@ -75,6 +76,15 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { .cmd = "reggroupc", .schema = "i", }, + { + .handler = handle_query_regs_f, + .cmd = "regf", + }, + { + .handler = handle_query_regs_c, + .cmd = "regc", + .schema = "i", + }, }; void mcd_init_mcdserver_state(void) @@ -494,21 +504,21 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) } } -int cmd_parse_params(const char *data, const char *schema, GArray *params) -{ +int cmd_parse_params(const char *data, const char *schema, GArray *params) { MCDCmdVariant this_param; + char data_buffer[64] = {0}; if (schema[0] == 's') { this_param.data = data; g_array_append_val(params, this_param); } else if (schema[0] == 'i') { - this_param.index_handle = atoi(data); - g_array_append_val(params, this_param); + strncat(data_buffer, data, strlen(data)); + this_param.index_handle = atoi(data_buffer); + g_array_append_val(params, this_param); } return 0; - } int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds) @@ -885,23 +895,248 @@ CPUState *find_cpu(uint32_t thread_id) return NULL; } + +void parse_reg_xml(const char *xml, int size) { + // iterates over the complete xml file + int i, j; + int still_to_skip = 0; + char argument[64] = {0}; + char value[64] = {0}; + bool is_reg = false; + bool is_argument = false; + bool is_value = false; + GArray *reg_data; + + char c; + char *c_ptr; + + xml_attrib attribute_j; + const char *argument_j; + const char *value_j; + + for (i = 0; i < size; i++) { + c = xml[i]; + c_ptr = &c; + + if (still_to_skip>0) { + // skip chars unwanted chars + still_to_skip --; + continue; + } + + if (strncmp(&xml[i], "", 2)==0) { + // end of register info + still_to_skip = 1; + is_reg = false; + + // create empty register + mcd_reg_st my_register = (const struct mcd_reg_st){ 0 }; + + // add found attribtues + for (j = 0; jlen; j++) { + attribute_j = g_array_index(reg_data, xml_attrib, j); + + argument_j = attribute_j.argument; + value_j = attribute_j.value; + + if (strcmp(argument_j, "name")==0) { + strcpy(my_register.name, value_j); + } + else if (strcmp(argument_j, "regnum")==0) { + my_register.id = atoi(value_j); + } + else if (strcmp(argument_j, "bitsize")==0) { + my_register.bitsize = atoi(value_j); + } + else if (strcmp(argument_j, "type")==0) { + strcpy(my_register.type, value_j); + } + else if (strcmp(argument_j, "group")==0) { + strcpy(my_register.group, value_j); + } + } + // store register + g_array_append_vals(mcdserver_state.registers, (gconstpointer)&my_register, 1); + // free memory + g_array_free(reg_data, false); + } + else { + // store info for register + switch (c) { + case ' ': + break; + case '=': + is_argument = false; + break; + case '"': + if (is_value) { + // end of value reached + is_value = false; + // store arg-val combo + xml_attrib current_attribute; + strcpy(current_attribute.argument, argument); + strcpy(current_attribute.value, value); + g_array_append_vals(reg_data, (gconstpointer)¤t_attribute, 1); + memset(argument, 0, sizeof(argument)); + memset(value, 0, sizeof(value)); + } + else { + //start of value + is_value = true; + } + break; + default: + if (is_argument) { + strncat(argument, c_ptr, 1); + } + else if (is_value) { + strncat(value, c_ptr, 1); + } + else { + is_argument = true; + strncat(argument, c_ptr, 1); + } + break; + } + } + } + } +} + +int int_cmp(gconstpointer a, gconstpointer b) { + int a_int = *(int*)a; + int b_int = *(int*)b; + if (a_int == b_int) { + return 0; + } + else { + return 1; + } +} + void handle_init(GArray *params, void *user_ctx) { CPUState *cpu = mcdserver_state.c_cpu; CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - // store reg groups + if (strcmp(arch, "arm")==0) { + // store reg groups + uint32_t current_group_id = 0; + // at the moment we just assume there are 3 spaces (gpr, per and debug) // TODO: this might cause a memory leak when called a second time -> maybe free the Garray first mcdserver_state.reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); - mcd_reg_group_st group1 = { .name = "GPR Registers", .id = "1" }; + // store the registers themselves + mcdserver_state.registers = g_array_new(false, true, sizeof(mcd_reg_st)); + GList *register_numbers = NULL; + + const char *xml_filename = NULL; + const char *xml_content = NULL; + const char *name = NULL; + int i; + + // 1. check out the core xml file + xml_filename = cc->gdb_core_xml_file; + + for (i = 0; ; i++) { + name = xml_builtin[i][0]; + if (!name || (strncmp(name, xml_filename, strlen(xml_filename)) == 0 && strlen(name) == strlen(xml_filename))) + break; + } + // without gpr registers we can do nothing + assert(name); + // add group for gpr registers + current_group_id = 1; + mcd_reg_group_st group1 = { .name = "GPR Registers", .id = current_group_id }; g_array_append_vals(mcdserver_state.reggroups, (gconstpointer)&group1, 1); - mcd_reg_group_st group2 = { .name = "CP15 Registers", .id = "2" }; - g_array_append_vals(mcdserver_state.reggroups, (gconstpointer)&group2, 1); + // parse xml + xml_content = xml_builtin[i][1]; + parse_reg_xml(xml_content, strlen(xml_content)); + + // 2. iterate over all other xml files + GDBRegisterState *r; + for (r = cpu->gdb_regs; r; r = r->next) { + xml_filename = r->xml; + xml_content = NULL; + + // first, check if this is a coprocessor xml + + // funciton call + xml_content = arm_mcd_get_dynamic_xml(cpu, xml_filename); + if (xml_content) { + if (strcmp(xml_filename, "system-registers.xml")==0) { + //these are the coprocessor register + current_group_id = 2; + mcd_reg_group_st group2 = { .name = "CP15 Registers", .id = current_group_id }; + g_array_append_vals(mcdserver_state.reggroups, (gconstpointer)&group2, 1); + } + + } + else { + // its not a coprocessor xml -> it is a static xml file + for (i = 0; ; i++) { + name = xml_builtin[i][0]; + if (!name || (strncmp(name, xml_filename, strlen(xml_filename)) == 0 && strlen(name) == strlen(xml_filename))) + break; + } + if (name) { + xml_content = xml_builtin[i][1]; + } + else { + printf("no data found for %s\n", xml_filename); + continue; + } + } + + // parse xml + parse_reg_xml(xml_content, strlen(xml_content)); + } + // go over the register array and collect all additional data + mcd_reg_st *current_register; + int id_neg_offset = 0; + int effective_id; + for (i = 0; i < mcdserver_state.registers->len; i++) { + current_register = &(g_array_index(mcdserver_state.registers, mcd_reg_st, i)); + // ad an id handle + if (current_register->id) { + // id is already in place + //FIXME: we are missing 10 registers (likely the FPA regs or sth) + int used_id = current_register->id; + register_numbers = g_list_append(register_numbers, &used_id); + id_neg_offset ++; + } + else { + effective_id = i - id_neg_offset; + if (g_list_find_custom(register_numbers, &effective_id, (GCompareFunc)int_cmp)!=NULL) { + id_neg_offset --; + } + current_register->id = i - id_neg_offset; + } + // sort into correct reg_group and according mem_space + if (strcmp(current_register->group, "cp_regs")==0) { + current_register->mcd_reg_group_id = 2; + current_register->mcd_mem_space_id = 6; + // get info for opcode + } + else { + // gpr register + current_register->mcd_reg_group_id = 1; + current_register->mcd_mem_space_id = 5; + } + } + // free memory + g_list_free(register_numbers); } else { // we don't support other architectures @@ -910,7 +1145,7 @@ void handle_init(GArray *params, void *user_ctx) { g_free(arch); // the mcdserver is set up and we return the handshake - mcd_put_packet("shaking your hand"); + mcd_put_packet("shaking your hand"); } void handle_query_system(GArray *params, void *user_ctx) { @@ -932,10 +1167,6 @@ void handle_query_cores(GArray *params, void *user_ctx) { CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - //const char *cpu_name = object_get_canonical_path_component(OBJECT(cpu)); - //int process_id = mcd_get_cpu_pid(cpu); - //int cpu_index = cpu->cpu_index; - //int cpu_cluster = cpu->cluster_index; int nr_cores = cpu->nr_cores; g_string_append_printf(mcdserver_state.str_buf, "device=\"qemu-%s-device\",core=\"%s\",nr_cores=\"%d\"", arch, cpu_model, nr_cores); @@ -1039,13 +1270,21 @@ void handle_query_mem_spaces(GArray *params, void *user_ctx) { void handle_query_reg_groups_f(GArray *params, void *user_ctx) { // send the first reg group + int nb_groups = mcdserver_state.reggroups->len; + if (nb_groups == 1) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); + } + else { + g_string_printf(mcdserver_state.str_buf, "1!"); + } mcd_reg_group_st group = g_array_index(mcdserver_state.reggroups, mcd_reg_group_st, 0); - g_string_printf(mcdserver_state.str_buf, "1!id=%s.name=%s.", group.id, group.name); + g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.", group.id, group.name); mcd_put_strbuf(); } void handle_query_reg_groups_c(GArray *params, void *user_ctx) { - // this funcitons send all reg groups exept for the first + // this funcitons send all reg groups except for the first // 1. get parameter int query_index = get_param(params, 0)->index_handle; @@ -1056,12 +1295,51 @@ void handle_query_reg_groups_c(GArray *params, void *user_ctx) { g_string_printf(mcdserver_state.str_buf, "0!"); } else { - // provides g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); } // 3. send the correct reggroup mcd_reg_group_st group = g_array_index(mcdserver_state.reggroups, mcd_reg_group_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "id=%s.name=%s.", group.id, group.name); + g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.", group.id, group.name); + mcd_put_strbuf(); +} + +void handle_query_regs_f(GArray *params, void *user_ctx) { + // send the first register + int nb_regs = mcdserver_state.registers->len; + if (nb_regs == 1) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); + } + else { + g_string_printf(mcdserver_state.str_buf, "1!"); + } + mcd_reg_st my_register = g_array_index(mcdserver_state.registers, mcd_reg_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.size=%d.reggroupid=%d.memspaceid=%d.type=%d.thread=%d.", + my_register.id, my_register.name, my_register.bitsize, my_register.mcd_reg_group_id, + my_register.mcd_mem_space_id, my_register.mcd_reg_type, my_register.mcd_hw_thread_id); + mcd_put_strbuf(); +} + +void handle_query_regs_c(GArray *params, void *user_ctx) { + // this funcitons send all registers except for the first + // 1. get parameter + int query_index = get_param(params, 0)->index_handle; + + // 2. check weather this was the last register + int nb_regs = mcdserver_state.registers->len; + if (query_index+1 == nb_regs) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); + } + else { + g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); + } + + // 3. send the correct register + mcd_reg_st my_register = g_array_index(mcdserver_state.registers, mcd_reg_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.size=%d.reggroupid=%d.memspaceid=%d.type=%d.thread=%d.", + my_register.id, my_register.name, my_register.bitsize, my_register.mcd_reg_group_id, + my_register.mcd_mem_space_id, my_register.mcd_reg_type, my_register.mcd_hw_thread_id); mcd_put_strbuf(); } diff --git a/target/arm/meson.build b/target/arm/meson.build index e645e456da..71ff10316f 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -3,6 +3,7 @@ arm_ss.add(files( 'cpu.c', 'debug_helper.c', 'gdbstub.c', + 'mcdstub.c', 'helper.c', 'vfp_helper.c', )) From patchwork Fri Oct 6 09:05:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844309 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22gq34Llz1yqF for ; Fri, 6 Oct 2023 20:09:59 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogn7-00087C-RO; Fri, 06 Oct 2023 05:06:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmy-00082u-Ja for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:29 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmu-0000ux-FB for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:27 -0400 Received: (qmail 19491 invoked by uid 484); 6 Oct 2023 09:06:20 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.083181 secs); 06 Oct 2023 09:06:20 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:19 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 07/29] query data preparation improved Date: Fri, 6 Oct 2023 11:05:48 +0200 Message-Id: <20231006090610.26171-8-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 35 +++- mcdstub/mcdstub.c | 382 ++++++++++++++++++++++---------------------- 2 files changed, 215 insertions(+), 202 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 45ba1ca8cb..2f9a768038 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -21,6 +21,11 @@ #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 +// schema defines +#define ARG_SCHEMA_QRY_HANDLE "q" +#define ARG_SCHEMA_STRING "s" +#define ARG_SCHEMA_CORE_NUM "c" + // GDB stuff thats needed for GDB function, which we use typedef struct GDBRegisterState { int base_reg; @@ -60,17 +65,16 @@ typedef enum MCDThreadIdKind { typedef union MCDCmdVariant { const char *data; - uint8_t opcode; - unsigned long val_ul; - unsigned long long val_ull; + struct { MCDThreadIdKind kind; uint32_t pid; uint32_t tid; } thread_id; - // used to synchronize stub and dll for functions with multiple packets - int index_handle; + int query_handle; + int cpu_id; + } MCDCmdVariant; #define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) @@ -109,6 +113,7 @@ typedef struct MCDState { int supported_sstep_flags; // my stuff + GArray *memspaces; GArray *reggroups; GArray *registers; } MCDState; @@ -116,6 +121,18 @@ typedef struct MCDState { /* lives in main mcdstub.c */ extern MCDState mcdserver_state; +typedef struct mcd_mem_space_st { + const char *name; + uint32_t id; + uint32_t type; + uint32_t bits_per_mau; + uint8_t invariance; + uint32_t endian; + uint64_t min_addr; + uint64_t max_addr; + uint32_t supported_access_options; +} mcd_mem_space_st; + typedef struct mcd_reg_group_st { const char *name; uint32_t id; @@ -213,19 +230,23 @@ void handle_query_cores(GArray *params, void *user_ctx); void handle_query_system(GArray *params, void *user_ctx); CPUState *get_first_cpu_in_process(MCDProcess *process); CPUState *find_cpu(uint32_t thread_id); -void handle_core_open(GArray *params, void *user_ctx); +void handle_open_core(GArray *params, void *user_ctx); void handle_query_reset(GArray *params, void *user_ctx); void handle_detach(GArray *params, void *user_ctx); void handle_query_trigger(GArray *params, void *user_ctx); void mcd_continue(void); -void handle_query_mem_spaces(GArray *params, void *user_ctx); void handle_query_reg_groups_f(GArray *params, void *user_ctx); void handle_query_reg_groups_c(GArray *params, void *user_ctx); +void handle_query_mem_spaces_f(GArray *params, void *user_ctx); +void handle_query_mem_spaces_c(GArray *params, void *user_ctx); void handle_query_regs_f(GArray *params, void *user_ctx); void handle_query_regs_c(GArray *params, void *user_ctx); void handle_init(GArray *params, void *user_ctx); void parse_reg_xml(const char *xml, int size); +// arm specific functions +void mcd_arm_store_mem_spaces(int nr_address_spaces); + /* sycall handling */ void mcd_syscall_reset(void); void mcd_disable_syscalls(void); diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 81026a42a1..b3ec3af543 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -2,6 +2,8 @@ * This is the main mcdstub. It needs to be complemented by other mcd stubs for each target. */ +#include "mcd_shared_defines.h" + //from original gdbstub.c #include "qemu/osdep.h" #include "qemu/ctype.h" @@ -64,8 +66,13 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { .cmd = "trigger", }, { - .handler = handle_query_mem_spaces, - .cmd = "memory", + .handler = handle_query_mem_spaces_f, + .cmd = "memoryf", + }, + { + .handler = handle_query_mem_spaces_c, + .cmd = "memoryc", + .schema = ARG_SCHEMA_QRY_HANDLE, }, { .handler = handle_query_reg_groups_f, @@ -74,7 +81,7 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { { .handler = handle_query_reg_groups_c, .cmd = "reggroupc", - .schema = "i", + .schema = ARG_SCHEMA_QRY_HANDLE, }, { .handler = handle_query_regs_f, @@ -83,7 +90,7 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { { .handler = handle_query_regs_c, .cmd = "regc", - .schema = "i", + .schema = ARG_SCHEMA_QRY_HANDLE, }, }; @@ -424,20 +431,19 @@ int mcd_handle_packet(const char *line_buf) static const MCDCmdParseEntry gen_query_cmd_desc = { .handler = handle_gen_query, .cmd = "q", - .schema = "s" + .schema = ARG_SCHEMA_STRING }; cmd_parser = &gen_query_cmd_desc; } break; case 'H': - //current alias for open core, later this will probably be a part of the 'i' requests { - static const MCDCmdParseEntry gen_core_open = { - .handler = handle_core_open, + static const MCDCmdParseEntry gen_open_core = { + .handler = handle_open_core, .cmd = "H", - .schema = "s" + .schema = ARG_SCHEMA_CORE_NUM }; - cmd_parser = &gen_core_open; + cmd_parser = &gen_open_core; } break; case 'D': @@ -508,13 +514,18 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) { MCDCmdVariant this_param; char data_buffer[64] = {0}; - if (schema[0] == 's') { + if (schema[0] == atoi(ARG_SCHEMA_STRING)) { this_param.data = data; g_array_append_val(params, this_param); } - else if (schema[0] == 'i') { + else if (schema[0] == atoi(ARG_SCHEMA_QRY_HANDLE)) { strncat(data_buffer, data, strlen(data)); - this_param.index_handle = atoi(data_buffer); + this_param.query_handle = atoi(data_buffer); + g_array_append_val(params, this_param); + } + else if (schema[0] == atoi(ARG_SCHEMA_CORE_NUM)) { + strncat(data_buffer, data, strlen(data)); + this_param.cpu_id = atoi(data_buffer); g_array_append_val(params, this_param); } @@ -618,97 +629,6 @@ void mcd_sigterm_handler(int signal) void mcd_vm_state_change(void *opaque, bool running, RunState state) { printf("this calls state_change\n"); - /* - CPUState *cpu = mcdserver_state.c_cpu; - g_autoptr(GString) buf = g_string_new(NULL); - g_autoptr(GString) tid = g_string_new(NULL); - const char *type; - int ret; - - if (running || mcdserver_state.state == RS_INACTIVE) { - return; - } - - //Is there a GDB syscall waiting to be sent? - if (gdb_handled_syscall()) { - return; - } - - if (cpu == NULL) { - //No process attached - return; - } - - gdb_append_thread_id(cpu, tid); - - switch (state) { - case RUN_STATE_DEBUG: - if (cpu->watchpoint_hit) { - switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { - case BP_MEM_READ: - type = "r"; - break; - case BP_MEM_ACCESS: - type = "a"; - break; - default: - type = ""; - break; - } - trace_gdbstub_hit_watchpoint(type, - gdb_get_cpu_index(cpu), - cpu->watchpoint_hit->vaddr); - g_string_printf(buf, "T%02xthread:%s;%swatch:%" VADDR_PRIx ";", - GDB_SIGNAL_TRAP, tid->str, type, - cpu->watchpoint_hit->vaddr); - cpu->watchpoint_hit = NULL; - goto send_packet; - } else { - trace_gdbstub_hit_break(); - } - tb_flush(cpu); - ret = GDB_SIGNAL_TRAP; - break; - case RUN_STATE_PAUSED: - trace_gdbstub_hit_paused(); - ret = GDB_SIGNAL_INT; - break; - case RUN_STATE_SHUTDOWN: - trace_gdbstub_hit_shutdown(); - ret = GDB_SIGNAL_QUIT; - break; - case RUN_STATE_IO_ERROR: - trace_gdbstub_hit_io_error(); - ret = GDB_SIGNAL_IO; - break; - case RUN_STATE_WATCHDOG: - trace_gdbstub_hit_watchdog(); - ret = GDB_SIGNAL_ALRM; - break; - case RUN_STATE_INTERNAL_ERROR: - trace_gdbstub_hit_internal_error(); - ret = GDB_SIGNAL_ABRT; - break; - case RUN_STATE_SAVE_VM: - case RUN_STATE_RESTORE_VM: - return; - case RUN_STATE_FINISH_MIGRATE: - ret = GDB_SIGNAL_XCPU; - break; - default: - trace_gdbstub_hit_unknown(state); - ret = GDB_SIGNAL_UNKNOWN; - break; - } - mcd_set_stop_cpu(cpu); - g_string_printf(buf, "T%02xthread:%s;", ret, tid->str); - -send_packet: - mcd_put_packet(buf->str); - - // disable single step if it was enabled - cpu_single_step(cpu, 0); -*/ } int mcd_put_packet(const char *buf) @@ -726,14 +646,6 @@ void mcd_put_strbuf(void) int mcd_put_packet_binary(const char *buf, int len, bool dump) { - //int csum, i; - //uint8_t footer[3]; - - //trace stuff - //if (dump && trace_event_get_state_backends(TRACE_GDBSTUB_IO_BINARYREPLY)) { - // hexdump(buf, len, trace_gdbstub_io_binaryreply); - //} - for(;;) { //super interesting if we want a chekcsum or something like that here!! g_byte_array_set_size(mcdserver_state.last_packet, 0); @@ -741,16 +653,7 @@ int mcd_put_packet_binary(const char *buf, int len, bool dump) g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) buf, len); g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "#", 1); g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "|", 1); - /* - csum = 0; - for(i = 0; i < len; i++) { - csum += buf[i]; - } - footer[0] = '#'; - footer[1] = tohex((csum >> 4) & 0xf); - footer[2] = tohex((csum) & 0xf); - g_byte_array_append(mcdserver_state.last_packet, footer, 3); - */ + mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); if (mcd_got_immediate_ack()) { @@ -1021,23 +924,145 @@ int int_cmp(gconstpointer a, gconstpointer b) { } } +void mcd_arm_store_mem_spaces(int nr_address_spaces) { + mcd_mem_space_st space1 = { + .name = "Non Secure", + .id = 1, + .type = 34, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space1, 1); + + mcd_mem_space_st space2 = { + .name = "Physical (Non Secure)", + .id = 2, + .type = 18, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space2, 1); + + if (nr_address_spaces==2) { + mcd_mem_space_st space3 = { + .name = "Secure", + .id = 3, + .type = 34, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space3, 1); + mcd_mem_space_st space4 = { + .name = "Physical (Secure)", + .id = 4, + .type = 18, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space4, 1); + } + // TODO: get dynamically how the per (CP15) space is called + mcd_mem_space_st space5 = { + .name = "GPR Registers", + .id = 5, + .type = 1, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space5, 1); + mcd_mem_space_st space6 = { + .name = "CP15 Registers", + .id = 6, + .type = 1, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space6, 1); +} + void handle_init(GArray *params, void *user_ctx) { - CPUState *cpu = mcdserver_state.c_cpu; + // the mcdserver is set up and we return the handshake + mcd_put_packet("shaking your hand"); +} + +void handle_query_system(GArray *params, void *user_ctx) { + mcd_put_packet("qemu-system"); +} + +void handle_query_cores(GArray *params, void *user_ctx) { + //TODO: add cluster support: in gdb each inferior (process) handles one cluster we might want to have sth similar here + + // get first cpu + CPUState *cpu = mcd_first_attached_cpu(); + if (!cpu) { + return; + } + + ObjectClass *oc = object_get_class(OBJECT(cpu)); + const char *cpu_model = object_class_get_name(oc); + + CPUClass *cc = CPU_GET_CLASS(cpu); + gchar *arch = cc->gdb_arch_name(cpu); + + int nr_cores = cpu->nr_cores; + + g_string_append_printf(mcdserver_state.str_buf, "device=\"qemu-%s-device\",core=\"%s\",nr_cores=\"%d\"", arch, cpu_model, nr_cores); + mcd_put_strbuf(); + g_free(arch); +} + +void handle_open_core(GArray *params, void *user_ctx) { + // get the cpu whith the given id + uint32_t cpu_id = get_param(params, 0)->cpu_id; + + CPUState *cpu = mcd_get_cpu(cpu_id); + CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); + // TODO: this might cause a memory leak when called a second time -> maybe free the Garray first + mcdserver_state.memspaces = g_array_new(false, true, sizeof(mcd_mem_space_st)); + mcdserver_state.reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); + mcdserver_state.registers = g_array_new(false, true, sizeof(mcd_reg_st)); + if (strcmp(arch, "arm")==0) { // store reg groups uint32_t current_group_id = 0; // at the moment we just assume there are 3 spaces (gpr, per and debug) - // TODO: this might cause a memory leak when called a second time -> maybe free the Garray first - mcdserver_state.reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); + + // store mem spaces + int nr_address_spaces = cpu->num_ases; + mcd_arm_store_mem_spaces(nr_address_spaces); + // mem spaces done + - // store the registers themselves - mcdserver_state.registers = g_array_new(false, true, sizeof(mcd_reg_st)); GList *register_numbers = NULL; const char *xml_filename = NULL; @@ -1140,49 +1165,9 @@ void handle_init(GArray *params, void *user_ctx) { } else { // we don't support other architectures - assert(1); + assert(0); } g_free(arch); - - // the mcdserver is set up and we return the handshake - mcd_put_packet("shaking your hand"); -} - -void handle_query_system(GArray *params, void *user_ctx) { - mcd_put_packet("qemu-system"); -} - -void handle_query_cores(GArray *params, void *user_ctx) { - //TODO: add cluster support: in gdb each inferior (process) handles one cluster we might want to have sth similar here - - // get first cpu - CPUState *cpu = mcd_first_attached_cpu(); - if (!cpu) { - return; - } - - ObjectClass *oc = object_get_class(OBJECT(cpu)); - const char *cpu_model = object_class_get_name(oc); - - CPUClass *cc = CPU_GET_CLASS(cpu); - gchar *arch = cc->gdb_arch_name(cpu); - - int nr_cores = cpu->nr_cores; - - g_string_append_printf(mcdserver_state.str_buf, "device=\"qemu-%s-device\",core=\"%s\",nr_cores=\"%d\"", arch, cpu_model, nr_cores); - mcd_put_strbuf(); - g_free(arch); -} - -void handle_core_open(GArray *params, void *user_ctx) { - // get the cpu whith the given id - uint32_t cpu_id = atoi(get_param(params, 0)->data); - - CPUState *cpu = mcd_get_cpu(cpu_id); - - // select the the cpu as the current cpu for all request from the mcd interface - mcdserver_state.c_cpu = cpu; - } void handle_query_reset(GArray *params, void *user_ctx) { @@ -1235,36 +1220,43 @@ void mcd_continue(void) } } -void handle_query_mem_spaces(GArray *params, void *user_ctx) { - // this returns the address spaces - // first we check if this is an arm architecture - // if it is arm we assume that if there are 2 address spaces, these are secure and non-secure (EL3 and EL0 for 64 bit) - CPUState *cpu = mcdserver_state.c_cpu; - CPUClass *cc = CPU_GET_CLASS(cpu); - - int nr_address_spaces = cpu->num_ases; - gchar *arch = cc->gdb_arch_name(cpu); +void handle_query_mem_spaces_f(GArray *params, void *user_ctx) { + // send the first mem space + int nb_groups = mcdserver_state.memspaces->len; + if (nb_groups == 1) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); + } + else { + g_string_printf(mcdserver_state.str_buf, "1!"); + } + mcd_mem_space_st space = g_array_index(mcdserver_state.memspaces, mcd_mem_space_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "name=%s.id=%d.type=%d.bpm=%d.i=%d.e=%d.min=%ld.max=%ld.sao=%d.", + space.name, space.id, space.type, space.bits_per_mau, space.invariance, space.endian, + space.min_addr, space.max_addr, space.supported_access_options); + mcd_put_strbuf(); +} - if (strcmp(arch, "arm")==0) { - // we got secure and non-secure - g_string_printf(mcdserver_state.str_buf, "Non Secure=id:1;type:34;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); - g_string_append_printf(mcdserver_state.str_buf, "Physical (Non Secure)=id:2;type:18;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); - if (nr_address_spaces==2) { - g_string_append_printf(mcdserver_state.str_buf, "Secure=id:3;type:34;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); - g_string_append_printf(mcdserver_state.str_buf, "Physical (Secure)=id:4;type:18;bpm:8;i:1;e:1;min:0;max:-1;sao:0;."); - } +void handle_query_mem_spaces_c(GArray *params, void *user_ctx) { + // this funcitons send all mem spaces except for the first + // 1. get parameter + int query_index = get_param(params, 0)->query_handle; - // provide register spaces - // TODO: get dynamically how the per (CP15) space is called - g_string_append_printf(mcdserver_state.str_buf, "GPR Registers=id:5;type:1;bpm:64;i:1;e:1;min:0;max:-1;sao:0;."); - g_string_append_printf(mcdserver_state.str_buf, "CP15 Registers=id:6;type:1;bpm:32;i:1;e:1;min:0;max:-1;sao:0;."); //<-- per registers - //g_string_append_printf(mcdserver_state.str_buf, "CP14 Registers=type:1;bpm:32;i:1;e:1;min:0;max:-1;sao:0;."); // <-- debug registers + // 2. check weather this was the last mem space + int nb_groups = mcdserver_state.memspaces->len; + if (query_index+1 == nb_groups) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); } else { - // we don't support other architectures - assert(1); + g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); } - g_free(arch); + + // 3. send the correct memspace + mcd_mem_space_st space = g_array_index(mcdserver_state.memspaces, mcd_mem_space_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "name=%s.id=%d.type=%d.bpm=%d.i=%d.e=%d.min=%ld.max=%ld.sao=%d.", + space.name, space.id, space.type, space.bits_per_mau, space.invariance, space.endian, + space.min_addr, space.max_addr, space.supported_access_options); mcd_put_strbuf(); } @@ -1286,7 +1278,7 @@ void handle_query_reg_groups_f(GArray *params, void *user_ctx) { void handle_query_reg_groups_c(GArray *params, void *user_ctx) { // this funcitons send all reg groups except for the first // 1. get parameter - int query_index = get_param(params, 0)->index_handle; + int query_index = get_param(params, 0)->query_handle; // 2. check weather this was the last reg group int nb_groups = mcdserver_state.reggroups->len; @@ -1324,7 +1316,7 @@ void handle_query_regs_f(GArray *params, void *user_ctx) { void handle_query_regs_c(GArray *params, void *user_ctx) { // this funcitons send all registers except for the first // 1. get parameter - int query_index = get_param(params, 0)->index_handle; + int query_index = get_param(params, 0)->query_handle; // 2. check weather this was the last register int nb_regs = mcdserver_state.registers->len; From patchwork Fri Oct 6 09:05:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844308 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22gn5442z20Vp for ; Fri, 6 Oct 2023 20:09:57 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogn5-00085Z-Tr; Fri, 06 Oct 2023 05:06:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmz-00082v-8D for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:29 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmv-0000vv-9Q for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:29 -0400 Received: (qmail 19513 invoked by uid 484); 6 Oct 2023 09:06:22 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.071708 secs); 06 Oct 2023 09:06:22 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:21 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 08/29] shared header file added, used for TCP packet data Date: Fri, 6 Oct 2023 11:05:49 +0200 Message-Id: <20231006090610.26171-9-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 4 +- mcdstub/mcd_shared_defines.h | 24 ++++++++++++ mcdstub/mcdstub.c | 72 ++++++++++++++++++------------------ 3 files changed, 62 insertions(+), 38 deletions(-) create mode 100644 mcdstub/mcd_shared_defines.h diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 2f9a768038..4c79ff7674 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -22,9 +22,9 @@ #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 // schema defines -#define ARG_SCHEMA_QRY_HANDLE "q" +#define ARG_SCHEMA_QRYHANDLE "q" #define ARG_SCHEMA_STRING "s" -#define ARG_SCHEMA_CORE_NUM "c" +#define ARG_SCHEMA_CORENUM "c" // GDB stuff thats needed for GDB function, which we use typedef struct GDBRegisterState { diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h new file mode 100644 index 0000000000..6a2abfb1bc --- /dev/null +++ b/mcdstub/mcd_shared_defines.h @@ -0,0 +1,24 @@ +// this file is shared between the mcd dll and the mcd stub. it has to be kept exectly the same! + +#ifndef MCD_SHARED_DEFINES +#define MCD_SHARED_DEFINES + +// tcp characters +#define TCP_CHAR_INIT 'i' +#define TCP_CHAR_GO 'c' +#define TCP_CHAR_QUERY 'q' +#define TCP_CHAR_OPEN_CORE 'H' +#define TCP_CHAR_DETACH 'D' +#define TCP_CHAR_KILLQEMU 'k' + +// tcp protocol chars +#define TCP_ACKNOWLEDGED '+' +#define TCP_NOT_ACKNOWLEDGED '-' +#define TCP_COMMAND_START '$' +#define TCP_COMMAND_END '#' +#define TCP_WAS_LAST '|' +#define TCP_WAS_NOT_LAST '~' + + + +#endif \ No newline at end of file diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index b3ec3af543..a4841cf7d3 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -72,7 +72,7 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { { .handler = handle_query_mem_spaces_c, .cmd = "memoryc", - .schema = ARG_SCHEMA_QRY_HANDLE, + .schema = ARG_SCHEMA_QRYHANDLE, }, { .handler = handle_query_reg_groups_f, @@ -81,7 +81,7 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { { .handler = handle_query_reg_groups_c, .cmd = "reggroupc", - .schema = ARG_SCHEMA_QRY_HANDLE, + .schema = ARG_SCHEMA_QRYHANDLE, }, { .handler = handle_query_regs_f, @@ -90,7 +90,7 @@ static const MCDCmdParseEntry mcd_gen_query_table[] = { { .handler = handle_query_regs_c, .cmd = "regc", - .schema = ARG_SCHEMA_QRY_HANDLE, + .schema = ARG_SCHEMA_QRYHANDLE, }, }; @@ -303,22 +303,22 @@ void mcd_read_byte(uint8_t ch) if (mcdserver_state.last_packet->len) { /* Waiting for a response to the last packet. If we see the start of a new command then abandon the previous response. */ - if (ch == '-') { + if (ch == TCP_NOT_ACKNOWLEDGED) { //the previous packet was not akcnowledged //trace_gdbstub_err_got_nack(); //we are resending the last packet mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); } - else if (ch == '+') { + else if (ch == TCP_ACKNOWLEDGED) { //the previous packet was acknowledged //trace_gdbstub_io_got_ack(); } - if (ch == '+' || ch == '$') { + if (ch == TCP_ACKNOWLEDGED || ch == TCP_COMMAND_START) { //either acknowledged or a new communication starts -> we discard previous communication g_byte_array_set_size(mcdserver_state.last_packet, 0); } - if (ch != '$') { + if (ch != TCP_COMMAND_START) { // we only continue if we are processing a new commant. otherwise we skip to ne next character in the packet which sould be a $ return; } @@ -331,7 +331,7 @@ void mcd_read_byte(uint8_t ch) else { switch(mcdserver_state.state) { case RS_IDLE: - if (ch == '$') { + if (ch == TCP_COMMAND_START) { /* start of command packet */ mcdserver_state.line_buf_index = 0; mcdserver_state.line_sum = 0; @@ -343,7 +343,7 @@ void mcd_read_byte(uint8_t ch) } break; case RS_GETLINE: - if (ch == '#') { + if (ch == TCP_COMMAND_END) { /* end of command, start of checksum*/ mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0; //mcdserver_state.line_sum += ch; @@ -365,24 +365,24 @@ void mcd_read_byte(uint8_t ch) // we are now done with copying the data and in the suffix of the packet // TODO: maybe wanna implement a checksum or sth like the gdb protocol has - if (ch == '~') { + if (ch == TCP_WAS_NOT_LAST) { // ~ indicates that there is an additional package coming //acknowledged -> send + - reply = '+'; + reply = TCP_ACKNOWLEDGED; mcd_put_buffer(&reply, 1); mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); } - else if (ch == '|') { + else if (ch == TCP_WAS_LAST) { //acknowledged -> send + // | indicates that there is no additional package coming - reply = '+'; + reply = TCP_ACKNOWLEDGED; mcd_put_buffer(&reply, 1); mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); } else { //trace_gdbstub_err_checksum_incorrect(mcdserver_state.line_sum, mcdserver_state.line_csum); //not acknowledged -> send - - reply = '-'; + reply = TCP_NOT_ACKNOWLEDGED; mcd_put_buffer(&reply, 1); //waiting for package to get resent mcdserver_state.state = RS_IDLE; @@ -400,58 +400,58 @@ int mcd_handle_packet(const char *line_buf) const MCDCmdParseEntry *cmd_parser = NULL; switch (line_buf[0]) { - case 'i': + case TCP_CHAR_INIT: // handshake and lookup initialization { - static const MCDCmdParseEntry continue_cmd_desc = { + static MCDCmdParseEntry init_cmd_desc = { .handler = handle_init, - .cmd = "i", }; - cmd_parser = &continue_cmd_desc; + init_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_INIT, '\0' }; + cmd_parser = &init_cmd_desc; } break; - case 'c': + case TCP_CHAR_GO: // go command { - static const MCDCmdParseEntry continue_cmd_desc = { + static MCDCmdParseEntry go_cmd_desc = { .handler = handle_continue, - .cmd = "c", }; - cmd_parser = &continue_cmd_desc; + go_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_GO, '\0' }; + cmd_parser = &go_cmd_desc; } break; - case 'k': + case TCP_CHAR_KILLQEMU: // kill qemu completely error_report("QEMU: Terminated via MCDstub"); mcd_exit(0); exit(0); - case 'q': + case TCP_CHAR_QUERY: //query inquiry { - static const MCDCmdParseEntry gen_query_cmd_desc = { + static MCDCmdParseEntry query_cmd_desc = { .handler = handle_gen_query, - .cmd = "q", .schema = ARG_SCHEMA_STRING }; - cmd_parser = &gen_query_cmd_desc; + query_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_QUERY, '\0' }; + cmd_parser = &query_cmd_desc; } break; - case 'H': + case TCP_CHAR_OPEN_CORE: { - static const MCDCmdParseEntry gen_open_core = { + static MCDCmdParseEntry gen_open_core = { .handler = handle_open_core, - .cmd = "H", - .schema = ARG_SCHEMA_CORE_NUM + .schema = ARG_SCHEMA_CORENUM }; + gen_open_core.cmd = (char[2]) { (char) TCP_CHAR_OPEN_CORE, '\0' }; cmd_parser = &gen_open_core; } break; - case 'D': + case TCP_CHAR_DETACH: { - static const MCDCmdParseEntry detach_cmd_desc = { + static MCDCmdParseEntry detach_cmd_desc = { .handler = handle_detach, - .cmd = "D", }; + detach_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_DETACH, '\0' }; cmd_parser = &detach_cmd_desc; } break; @@ -518,12 +518,12 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) { this_param.data = data; g_array_append_val(params, this_param); } - else if (schema[0] == atoi(ARG_SCHEMA_QRY_HANDLE)) { + else if (schema[0] == atoi(ARG_SCHEMA_QRYHANDLE)) { strncat(data_buffer, data, strlen(data)); this_param.query_handle = atoi(data_buffer); g_array_append_val(params, this_param); } - else if (schema[0] == atoi(ARG_SCHEMA_CORE_NUM)) { + else if (schema[0] == atoi(ARG_SCHEMA_CORENUM)) { strncat(data_buffer, data, strlen(data)); this_param.cpu_id = atoi(data_buffer); g_array_append_val(params, this_param); From patchwork Fri Oct 6 09:05:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844313 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22ld4cDmz1yq9 for ; Fri, 6 Oct 2023 20:13:17 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogn8-00087A-41; Fri, 06 Oct 2023 05:06:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogn1-00083j-H1 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:32 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmw-0000wB-Jj for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:31 -0400 Received: (qmail 19535 invoked by uid 484); 6 Oct 2023 09:06:23 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.07364 secs); 06 Oct 2023 09:06:23 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:22 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 09/29] memory and register query data now stored per core Date: Fri, 6 Oct 2023 11:05:50 +0200 Message-Id: <20231006090610.26171-10-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 63 +++- mcdstub/mcd_shared_defines.h | 43 ++- mcdstub/mcdstub.c | 693 ++++++++++++++++++++++------------- 3 files changed, 533 insertions(+), 266 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 4c79ff7674..a4d49a4a84 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -8,6 +8,7 @@ #include "exec/cpu-common.h" #include "chardev/char.h" +#include "hw/core/cpu.h" // just used for the register xml files #include "exec/gdbstub.h" /* xml_builtin */ @@ -22,9 +23,22 @@ #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 // schema defines -#define ARG_SCHEMA_QRYHANDLE "q" -#define ARG_SCHEMA_STRING "s" -#define ARG_SCHEMA_CORENUM "c" +#define ARG_SCHEMA_QRYHANDLE 'q' +#define ARG_SCHEMA_STRING 's' +#define ARG_SCHEMA_CORENUM 'c' + +// resets +#define RESET_SYSTEM "full_system_reset" +#define RESET_GPR "gpr_reset" +#define RESET_MEMORY "memory_reset" + +// more +#define QUERY_TOTAL_NUMBER 11 //FIXME: set this to a usefull value in the end +#define CMD_SCHEMA_LENGTH 2 +#define MCD_MAX_CORES 128 +#define MCD_SYSTEM_NAME "qemu-system" +// tcp query packet values templates +#define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" // GDB stuff thats needed for GDB function, which we use typedef struct GDBRegisterState { @@ -52,8 +66,7 @@ typedef void (*MCDCmdHandler)(GArray *params, void *user_ctx); typedef struct MCDCmdParseEntry { MCDCmdHandler handler; const char *cmd; - bool cmd_startswith; - const char *schema; + char schema[CMD_SCHEMA_LENGTH]; } MCDCmdParseEntry; typedef enum MCDThreadIdKind { @@ -92,6 +105,13 @@ enum RSState { RS_DATAEND, }; +typedef struct mcd_trigger_st { + uint32_t type; + uint32_t option; + uint32_t action; + uint32_t nr_trigger; +} mcd_trigger_st; + typedef struct MCDState { bool init; /* have we been initialised? */ CPUState *c_cpu; /* current CPU for everything */ @@ -113,9 +133,13 @@ typedef struct MCDState { int supported_sstep_flags; // my stuff - GArray *memspaces; - GArray *reggroups; - GArray *registers; + uint32_t query_cpu_id; + GList *all_memspaces; + GList *all_reggroups; + GList *all_registers; + GArray *resets; + mcd_trigger_st trigger; + MCDCmdParseEntry mcd_query_cmds_table[QUERY_TOTAL_NUMBER]; } MCDState; /* lives in main mcdstub.c */ @@ -164,6 +188,11 @@ typedef struct mcd_reg_st { uint8_t opc2; } mcd_reg_st; +typedef struct mcd_reset_st { + const char *name; + uint8_t id; +} mcd_reset_st; + // Inline utility function, convert from int to hex and back @@ -194,6 +223,9 @@ void mcd_sigterm_handler(int signal); #endif void mcd_init_mcdserver_state(void); +void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table); +int init_resets(GArray* resets); +int init_trigger(mcd_trigger_st* trigger); void reset_mcdserver_state(void); void create_processes(MCDState *s); void mcd_create_default_process(MCDState *s); @@ -231,8 +263,10 @@ void handle_query_system(GArray *params, void *user_ctx); CPUState *get_first_cpu_in_process(MCDProcess *process); CPUState *find_cpu(uint32_t thread_id); void handle_open_core(GArray *params, void *user_ctx); -void handle_query_reset(GArray *params, void *user_ctx); -void handle_detach(GArray *params, void *user_ctx); +void handle_query_reset_f(GArray *params, void *user_ctx); +void handle_query_reset_c(GArray *params, void *user_ctx); +void handle_close_server(GArray *params, void *user_ctx); +void handle_close_core(GArray *params, void *user_ctx); void handle_query_trigger(GArray *params, void *user_ctx); void mcd_continue(void); void handle_query_reg_groups_f(GArray *params, void *user_ctx); @@ -241,11 +275,14 @@ void handle_query_mem_spaces_f(GArray *params, void *user_ctx); void handle_query_mem_spaces_c(GArray *params, void *user_ctx); void handle_query_regs_f(GArray *params, void *user_ctx); void handle_query_regs_c(GArray *params, void *user_ctx); -void handle_init(GArray *params, void *user_ctx); -void parse_reg_xml(const char *xml, int size); +void handle_open_server(GArray *params, void *user_ctx); +void parse_reg_xml(const char *xml, int size, GArray* registers); // arm specific functions -void mcd_arm_store_mem_spaces(int nr_address_spaces); +int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces); +int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray* reggroups, GArray* registers, int* current_group_id); +int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray* registers, int* current_group_id); +int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers); /* sycall handling */ void mcd_syscall_reset(void); diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 6a2abfb1bc..e0b27ce5e6 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -3,12 +3,13 @@ #ifndef MCD_SHARED_DEFINES #define MCD_SHARED_DEFINES -// tcp characters -#define TCP_CHAR_INIT 'i' +// tcp data characters +#define TCP_CHAR_OPEN_SERVER 'I' +#define TCP_CHAR_OPEN_CORE 'i' #define TCP_CHAR_GO 'c' #define TCP_CHAR_QUERY 'q' -#define TCP_CHAR_OPEN_CORE 'H' -#define TCP_CHAR_DETACH 'D' +#define TCP_CHAR_CLOSE_SERVER 'D' +#define TCP_CHAR_CLOSE_CORE 'd' #define TCP_CHAR_KILLQEMU 'k' // tcp protocol chars @@ -18,7 +19,39 @@ #define TCP_COMMAND_END '#' #define TCP_WAS_LAST '|' #define TCP_WAS_NOT_LAST '~' +#define TCP_HANDSHAKE_SUCCESS "shaking your hand" +// tcp query arguments +#define QUERY_FIRST "f" +#define QUERY_CONSEQUTIVE "c" +#define QUERY_ARG_SYSTEM "system" +#define QUERY_ARG_CORES "cores" +#define QUERY_ARG_RESET "reset" +#define QUERY_ARG_TRIGGER "trigger" +#define QUERY_ARG_MEMORY "memory" +#define QUERY_ARG_REGGROUP "reggroup" +#define QUERY_ARG_REG "reg" -#endif \ No newline at end of file +// tcp query packet argument list +#define TCP_ARGUMENT_NAME "name" +#define TCP_ARGUMENT_ID "id" +#define TCP_ARGUMENT_TYPE "type" +#define TCP_ARGUMENT_BITS_PER_MAU "bpm" +#define TCP_ARGUMENT_INVARIANCE "i" +#define TCP_ARGUMENT_ENDIAN "e" +#define TCP_ARGUMENT_MIN "min" +#define TCP_ARGUMENT_MAX "max" +#define TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS "sao" +#define TCP_ARGUMENT_REGGROUPID "reggroupid" +#define TCP_ARGUMENT_MEMSPACEID "memspaceid" +#define TCP_ARGUMENT_SIZE "size" +#define TCP_ARGUMENT_THREAD "thread" +#define TCP_ARGUMENT_DEVICE "device" +#define TCP_ARGUMENT_CORE "core" +#define TCP_ARGUMENT_AMOUNT_CORE "nr_cores" +#define TCP_ARGUMENT_AMOUNT_TRIGGER "nr_trigger" +#define TCP_ARGUMENT_OPTION "option" +#define TCP_ARGUMENT_ACTION "action" + +#endif diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index a4841cf7d3..a0c4c2794f 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -27,7 +27,6 @@ #include "exec/tb-flush.h" #include "sysemu/cpus.h" #include "sysemu/replay.h" -#include "hw/core/cpu.h" #include "chardev/char.h" #include "chardev/char-fe.h" #include "monitor/monitor.h" @@ -47,53 +46,6 @@ MCDSystemState mcdserver_system_state; MCDState mcdserver_state; -static const MCDCmdParseEntry mcd_gen_query_table[] = { - // this is a list of all query commands. it gets iterated over only the handler of the matching command will get executed - { - .handler = handle_query_system, - .cmd = "system", - }, - { - .handler = handle_query_cores, - .cmd = "cores", - }, - { - .handler = handle_query_reset, - .cmd = "reset", - }, - { - .handler = handle_query_trigger, - .cmd = "trigger", - }, - { - .handler = handle_query_mem_spaces_f, - .cmd = "memoryf", - }, - { - .handler = handle_query_mem_spaces_c, - .cmd = "memoryc", - .schema = ARG_SCHEMA_QRYHANDLE, - }, - { - .handler = handle_query_reg_groups_f, - .cmd = "reggroupf", - }, - { - .handler = handle_query_reg_groups_c, - .cmd = "reggroupc", - .schema = ARG_SCHEMA_QRYHANDLE, - }, - { - .handler = handle_query_regs_f, - .cmd = "regf", - }, - { - .handler = handle_query_regs_c, - .cmd = "regc", - .schema = ARG_SCHEMA_QRYHANDLE, - }, -}; - void mcd_init_mcdserver_state(void) { g_assert(!mcdserver_state.init); @@ -113,6 +65,97 @@ void mcd_init_mcdserver_state(void) mcdserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; mcdserver_state.sstep_flags &= mcdserver_state.supported_sstep_flags; + + // init query table + init_query_cmds_table(mcdserver_state.mcd_query_cmds_table); +} + +void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { + // initalizes a list of all query commands + int cmd_number = 0; + + MCDCmdParseEntry query_system = { + .handler = handle_query_system, + .cmd = QUERY_ARG_SYSTEM, + }; + mcd_query_cmds_table[cmd_number] = query_system; + cmd_number++; + + MCDCmdParseEntry query_cores = { + .handler = handle_query_cores, + .cmd = QUERY_ARG_CORES, + }; + mcd_query_cmds_table[cmd_number] = query_cores; + cmd_number++; + + MCDCmdParseEntry query_reset_f = { + .handler = handle_query_reset_f, + .cmd = QUERY_ARG_RESET QUERY_FIRST, + }; + mcd_query_cmds_table[cmd_number] = query_reset_f; + cmd_number++; + + MCDCmdParseEntry query_reset_c = { + .handler = handle_query_reset_c, + .cmd = QUERY_ARG_RESET QUERY_CONSEQUTIVE, + }; + strcpy(query_reset_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_reset_c; + cmd_number++; + + MCDCmdParseEntry query_trigger = { + .handler = handle_query_trigger, + .cmd = QUERY_ARG_TRIGGER, + }; + mcd_query_cmds_table[cmd_number] = query_trigger; + cmd_number++; + + MCDCmdParseEntry query_mem_spaces_f = { + .handler = handle_query_mem_spaces_f, + .cmd = QUERY_ARG_MEMORY QUERY_FIRST, + }; + strcpy(query_mem_spaces_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_mem_spaces_f; + cmd_number++; + + MCDCmdParseEntry query_mem_spaces_c = { + .handler = handle_query_mem_spaces_c, + .cmd = QUERY_ARG_MEMORY QUERY_CONSEQUTIVE, + }; + strcpy(query_mem_spaces_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_mem_spaces_c; + cmd_number++; + + MCDCmdParseEntry query_reg_groups_f = { + .handler = handle_query_reg_groups_f, + .cmd = QUERY_ARG_REGGROUP QUERY_FIRST, + }; + strcpy(query_reg_groups_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_reg_groups_f; + cmd_number++; + + MCDCmdParseEntry query_reg_groups_c = { + .handler = handle_query_reg_groups_c, + .cmd = QUERY_ARG_REGGROUP QUERY_CONSEQUTIVE, + }; + strcpy(query_reg_groups_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_reg_groups_c; + cmd_number++; + + MCDCmdParseEntry query_regs_f = { + .handler = handle_query_regs_f, + .cmd = QUERY_ARG_REG QUERY_FIRST, + }; + strcpy(query_regs_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_regs_f; + cmd_number++; + + MCDCmdParseEntry query_regs_c = { + .handler = handle_query_regs_c, + .cmd = QUERY_ARG_REG QUERY_CONSEQUTIVE, + }; + strcpy(query_regs_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + mcd_query_cmds_table[cmd_number] = query_regs_c; } void reset_mcdserver_state(void) @@ -400,14 +443,14 @@ int mcd_handle_packet(const char *line_buf) const MCDCmdParseEntry *cmd_parser = NULL; switch (line_buf[0]) { - case TCP_CHAR_INIT: + case TCP_CHAR_OPEN_SERVER: // handshake and lookup initialization { - static MCDCmdParseEntry init_cmd_desc = { - .handler = handle_init, + static MCDCmdParseEntry open_server_cmd_desc = { + .handler = handle_open_server, }; - init_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_INIT, '\0' }; - cmd_parser = &init_cmd_desc; + open_server_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_OPEN_SERVER, '\0' }; + cmd_parser = &open_server_cmd_desc; } break; case TCP_CHAR_GO: @@ -430,29 +473,39 @@ int mcd_handle_packet(const char *line_buf) { static MCDCmdParseEntry query_cmd_desc = { .handler = handle_gen_query, - .schema = ARG_SCHEMA_STRING }; query_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_QUERY, '\0' }; + strcpy(query_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_STRING, '\0' }); cmd_parser = &query_cmd_desc; } break; case TCP_CHAR_OPEN_CORE: { - static MCDCmdParseEntry gen_open_core = { + static MCDCmdParseEntry open_core_cmd_desc = { .handler = handle_open_core, - .schema = ARG_SCHEMA_CORENUM }; - gen_open_core.cmd = (char[2]) { (char) TCP_CHAR_OPEN_CORE, '\0' }; - cmd_parser = &gen_open_core; + open_core_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_OPEN_CORE, '\0' }; + strcpy(open_core_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser = &open_core_cmd_desc; } break; - case TCP_CHAR_DETACH: + case TCP_CHAR_CLOSE_SERVER: { - static MCDCmdParseEntry detach_cmd_desc = { - .handler = handle_detach, + static MCDCmdParseEntry close_server_cmd_desc = { + .handler = handle_close_server, }; - detach_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_DETACH, '\0' }; - cmd_parser = &detach_cmd_desc; + close_server_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_CLOSE_SERVER, '\0' }; + cmd_parser = &close_server_cmd_desc; + } + break; + case TCP_CHAR_CLOSE_CORE: + { + static MCDCmdParseEntry close_core_cmd_desc = { + .handler = handle_close_core, + }; + close_core_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_CLOSE_CORE, '\0' }; + strcpy(close_core_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser = &close_core_cmd_desc; } break; default: @@ -488,8 +541,8 @@ void handle_gen_query(GArray *params, void *user_ctx) } //now iterate over all possible query functions and execute the right one if (process_string_cmd(NULL, get_param(params, 0)->data, - mcd_gen_query_table, - ARRAY_SIZE(mcd_gen_query_table))) { + mcdserver_state.mcd_query_cmds_table, + ARRAY_SIZE(mcdserver_state.mcd_query_cmds_table))) { mcd_put_packet(""); } } @@ -514,16 +567,16 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) { MCDCmdVariant this_param; char data_buffer[64] = {0}; - if (schema[0] == atoi(ARG_SCHEMA_STRING)) { + if (schema[0] == ARG_SCHEMA_STRING) { this_param.data = data; g_array_append_val(params, this_param); } - else if (schema[0] == atoi(ARG_SCHEMA_QRYHANDLE)) { + else if (schema[0] == ARG_SCHEMA_QRYHANDLE) { strncat(data_buffer, data, strlen(data)); this_param.query_handle = atoi(data_buffer); g_array_append_val(params, this_param); } - else if (schema[0] == atoi(ARG_SCHEMA_CORENUM)) { + else if (schema[0] == ARG_SCHEMA_CORENUM) { strncat(data_buffer, data, strlen(data)); this_param.cpu_id = atoi(data_buffer); g_array_append_val(params, this_param); @@ -799,7 +852,7 @@ CPUState *find_cpu(uint32_t thread_id) } -void parse_reg_xml(const char *xml, int size) { +void parse_reg_xml(const char *xml, int size, GArray* registers) { // iterates over the complete xml file int i, j; int still_to_skip = 0; @@ -866,7 +919,7 @@ void parse_reg_xml(const char *xml, int size) { } } // store register - g_array_append_vals(mcdserver_state.registers, (gconstpointer)&my_register, 1); + g_array_append_vals(registers, (gconstpointer)&my_register, 1); // free memory g_array_free(reg_data, false); } @@ -924,7 +977,9 @@ int int_cmp(gconstpointer a, gconstpointer b) { } } -void mcd_arm_store_mem_spaces(int nr_address_spaces) { +int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces) { + int nr_address_spaces = cpu->num_ases; + mcd_mem_space_st space1 = { .name = "Non Secure", .id = 1, @@ -936,7 +991,7 @@ void mcd_arm_store_mem_spaces(int nr_address_spaces) { .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space1, 1); + g_array_append_vals(memspaces, (gconstpointer)&space1, 1); mcd_mem_space_st space2 = { .name = "Physical (Non Secure)", @@ -949,7 +1004,7 @@ void mcd_arm_store_mem_spaces(int nr_address_spaces) { .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space2, 1); + g_array_append_vals(memspaces, (gconstpointer)&space2, 1); if (nr_address_spaces==2) { mcd_mem_space_st space3 = { @@ -963,7 +1018,7 @@ void mcd_arm_store_mem_spaces(int nr_address_spaces) { .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space3, 1); + g_array_append_vals(memspaces, (gconstpointer)&space3, 1); mcd_mem_space_st space4 = { .name = "Physical (Secure)", .id = 4, @@ -975,7 +1030,7 @@ void mcd_arm_store_mem_spaces(int nr_address_spaces) { .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space4, 1); + g_array_append_vals(memspaces, (gconstpointer)&space4, 1); } // TODO: get dynamically how the per (CP15) space is called mcd_mem_space_st space5 = { @@ -989,7 +1044,7 @@ void mcd_arm_store_mem_spaces(int nr_address_spaces) { .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space5, 1); + g_array_append_vals(memspaces, (gconstpointer)&space5, 1); mcd_mem_space_st space6 = { .name = "CP15 Registers", .id = 6, @@ -1001,16 +1056,43 @@ void mcd_arm_store_mem_spaces(int nr_address_spaces) { .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(mcdserver_state.memspaces, (gconstpointer)&space6, 1); + g_array_append_vals(memspaces, (gconstpointer)&space6, 1); + + return 0; +} + +int init_resets(GArray* resets) { + mcd_reset_st system_reset = { .id = 0, .name = RESET_SYSTEM}; + mcd_reset_st gpr_reset = { .id = 1, .name = RESET_GPR}; + mcd_reset_st memory_reset = { .id = 2, .name = RESET_MEMORY}; + g_array_append_vals(resets, (gconstpointer)&system_reset, 1); + g_array_append_vals(resets, (gconstpointer)&gpr_reset, 1); + g_array_append_vals(resets, (gconstpointer)&memory_reset, 1); + return 0; } -void handle_init(GArray *params, void *user_ctx) { - // the mcdserver is set up and we return the handshake - mcd_put_packet("shaking your hand"); +int init_trigger(mcd_trigger_st* trigger) { + trigger->type = (MCD_TRIG_TYPE_IP | MCD_TRIG_TYPE_READ | MCD_TRIG_TYPE_WRITE | MCD_TRIG_TYPE_RW); + trigger->option = (MCD_TRIG_OPT_DATA_IS_CONDITION); + trigger->action = (MCD_TRIG_ACTION_DBG_DEBUG); + trigger->nr_trigger = 4; + return 0; +} + +void handle_open_server(GArray *params, void *user_ctx) { + // initialize some core-independent data + int return_value = 0; + mcdserver_state.resets = g_array_new(false, true, sizeof(mcd_reset_st)); + return_value = init_resets(mcdserver_state.resets); + if (return_value!=0) assert(0); + return_value = init_trigger(&mcdserver_state.trigger); + if (return_value!=0) assert(0); + + mcd_put_packet(TCP_HANDSHAKE_SUCCESS); } void handle_query_system(GArray *params, void *user_ctx) { - mcd_put_packet("qemu-system"); + mcd_put_packet(MCD_SYSTEM_NAME); } void handle_query_cores(GArray *params, void *user_ctx) { @@ -1030,138 +1112,179 @@ void handle_query_cores(GArray *params, void *user_ctx) { int nr_cores = cpu->nr_cores; - g_string_append_printf(mcdserver_state.str_buf, "device=\"qemu-%s-device\",core=\"%s\",nr_cores=\"%d\"", arch, cpu_model, nr_cores); + char device_name[] = DEVICE_NAME_TEMPLATE(arch); + g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%s.%s=%d.", + TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_ARGUMENT_AMOUNT_CORE, nr_cores); mcd_put_strbuf(); g_free(arch); } -void handle_open_core(GArray *params, void *user_ctx) { - // get the cpu whith the given id - uint32_t cpu_id = get_param(params, 0)->cpu_id; - - CPUState *cpu = mcd_get_cpu(cpu_id); - - CPUClass *cc = CPU_GET_CLASS(cpu); - - gchar *arch = cc->gdb_arch_name(cpu); - - // TODO: this might cause a memory leak when called a second time -> maybe free the Garray first - mcdserver_state.memspaces = g_array_new(false, true, sizeof(mcd_mem_space_st)); - mcdserver_state.reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); - mcdserver_state.registers = g_array_new(false, true, sizeof(mcd_reg_st)); - - - if (strcmp(arch, "arm")==0) { - // store reg groups - uint32_t current_group_id = 0; - - // at the moment we just assume there are 3 spaces (gpr, per and debug) - - // store mem spaces - int nr_address_spaces = cpu->num_ases; - mcd_arm_store_mem_spaces(nr_address_spaces); - // mem spaces done - - - GList *register_numbers = NULL; +int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray* reggroups, GArray* registers, int* current_group_id) { + const char *xml_filename = NULL; + const char *current_xml_filename = NULL; + const char *xml_content = NULL; + int i = 0; + + // 1. get correct file + xml_filename = cc->gdb_core_xml_file; + for (i = 0; ; i++) { + current_xml_filename = xml_builtin[i][0]; + if (!current_xml_filename || (strncmp(current_xml_filename, xml_filename, strlen(xml_filename)) == 0 + && strlen(current_xml_filename) == strlen(xml_filename))) + break; + } + // without gpr registers we can do nothing + if (!current_xml_filename) { + return -1; + } - const char *xml_filename = NULL; - const char *xml_content = NULL; - const char *name = NULL; - int i; + // 2. add group for gpr registers + mcd_reg_group_st gprregs = { .name = "GPR Registers", .id = *current_group_id }; + g_array_append_vals(reggroups, (gconstpointer)&gprregs, 1); + *current_group_id = *current_group_id + 1; - // 1. check out the core xml file - xml_filename = cc->gdb_core_xml_file; + // 3. parse xml + xml_content = xml_builtin[i][1]; + parse_reg_xml(xml_content, strlen(xml_content), registers); + return 0; +} - for (i = 0; ; i++) { - name = xml_builtin[i][0]; - if (!name || (strncmp(name, xml_filename, strlen(xml_filename)) == 0 && strlen(name) == strlen(xml_filename))) +int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray* registers, int* current_group_id) { + const char *xml_filename = NULL; + const char *current_xml_filename = NULL; + const char *xml_content = NULL; + int i = 0; + + // iterate over all gdb xml files + GDBRegisterState *r; + for (r = cpu->gdb_regs; r; r = r->next) { + xml_filename = r->xml; + xml_content = NULL; + + // 1. get xml content + xml_content = arm_mcd_get_dynamic_xml(cpu, xml_filename); + if (xml_content) { + if (strcmp(xml_filename, "system-registers.xml")==0) { + // these are the coprocessor register + mcd_reg_group_st corprocessorregs = { .name = "CP15 Registers", .id = *current_group_id }; + g_array_append_vals(reggroups, (gconstpointer)&corprocessorregs, 1); + *current_group_id = *current_group_id + 1; + } + } + else { + // its not a coprocessor xml -> it is a static xml file + for (i = 0; ; i++) { + current_xml_filename = xml_builtin[i][0]; + if (!current_xml_filename || (strncmp(current_xml_filename, xml_filename, strlen(xml_filename)) == 0 + && strlen(current_xml_filename) == strlen(xml_filename))) break; } - // without gpr registers we can do nothing - assert(name); - // add group for gpr registers - current_group_id = 1; - mcd_reg_group_st group1 = { .name = "GPR Registers", .id = current_group_id }; - g_array_append_vals(mcdserver_state.reggroups, (gconstpointer)&group1, 1); - - // parse xml - xml_content = xml_builtin[i][1]; - parse_reg_xml(xml_content, strlen(xml_content)); - - // 2. iterate over all other xml files - GDBRegisterState *r; - for (r = cpu->gdb_regs; r; r = r->next) { - xml_filename = r->xml; - xml_content = NULL; - - // first, check if this is a coprocessor xml - - // funciton call - xml_content = arm_mcd_get_dynamic_xml(cpu, xml_filename); - if (xml_content) { - if (strcmp(xml_filename, "system-registers.xml")==0) { - //these are the coprocessor register - current_group_id = 2; - mcd_reg_group_st group2 = { .name = "CP15 Registers", .id = current_group_id }; - g_array_append_vals(mcdserver_state.reggroups, (gconstpointer)&group2, 1); - } - + if (current_xml_filename) { + xml_content = xml_builtin[i][1]; } else { - // its not a coprocessor xml -> it is a static xml file - for (i = 0; ; i++) { - name = xml_builtin[i][0]; - if (!name || (strncmp(name, xml_filename, strlen(xml_filename)) == 0 && strlen(name) == strlen(xml_filename))) - break; - } - if (name) { - xml_content = xml_builtin[i][1]; - } - else { - printf("no data found for %s\n", xml_filename); - continue; - } + printf("no data found for %s\n", xml_filename); + continue; } + } + // 2. parse xml + parse_reg_xml(xml_content, strlen(xml_content), registers); + } + return 0; +} - // parse xml - parse_reg_xml(xml_content, strlen(xml_content)); +int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers) { + GList *register_numbers = NULL; + mcd_reg_st *current_register; + int i = 0; + int id_neg_offset = 0; + int effective_id = 0; + + // iterate over all registers + for (i = 0; i < registers->len; i++) { + current_register = &(g_array_index(registers, mcd_reg_st, i)); + // 1. ad the id + if (current_register->id) { + // id is already in place + // NOTE: qemu doesn't emulate the FPA regs (so we are missing the indices 16 to 24) + int used_id = current_register->id; + register_numbers = g_list_append(register_numbers, &used_id); + id_neg_offset ++; } - // go over the register array and collect all additional data - mcd_reg_st *current_register; - int id_neg_offset = 0; - int effective_id; - for (i = 0; i < mcdserver_state.registers->len; i++) { - current_register = &(g_array_index(mcdserver_state.registers, mcd_reg_st, i)); - // ad an id handle - if (current_register->id) { - // id is already in place - //FIXME: we are missing 10 registers (likely the FPA regs or sth) - int used_id = current_register->id; - register_numbers = g_list_append(register_numbers, &used_id); - id_neg_offset ++; - } - else { - effective_id = i - id_neg_offset; - if (g_list_find_custom(register_numbers, &effective_id, (GCompareFunc)int_cmp)!=NULL) { - id_neg_offset --; - } - current_register->id = i - id_neg_offset; - } - // sort into correct reg_group and according mem_space - if (strcmp(current_register->group, "cp_regs")==0) { - current_register->mcd_reg_group_id = 2; - current_register->mcd_mem_space_id = 6; - // get info for opcode - } - else { - // gpr register - current_register->mcd_reg_group_id = 1; - current_register->mcd_mem_space_id = 5; + else { + effective_id = i - id_neg_offset; + if (g_list_find_custom(register_numbers, &effective_id, (GCompareFunc)int_cmp)!=NULL) { + id_neg_offset --; } + current_register->id = i - id_neg_offset; + } + // 2. add mcd_reg_group_id and mcd_mem_space_id + if (strcmp(current_register->group, "cp_regs")==0) { + // coprocessor registers + current_register->mcd_reg_group_id = 2; + current_register->mcd_mem_space_id = 6; + // TODO: get info for opcode + } + else { + // gpr register + current_register->mcd_reg_group_id = 1; + current_register->mcd_mem_space_id = 5; + } + } + g_list_free(register_numbers); + return 0; +} + +void handle_open_core(GArray *params, void *user_ctx) { + // get the cpu whith the given id + uint32_t cpu_id = get_param(params, 0)->cpu_id; + CPUState *cpu = mcd_get_cpu(cpu_id); + CPUClass *cc = CPU_GET_CLASS(cpu); + gchar *arch = cc->gdb_arch_name(cpu); + int return_value = 0; + + // prepare data strucutures + GArray* memspaces = g_array_new(false, true, sizeof(mcd_mem_space_st)); + GArray* reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); + GArray* registers = g_array_new(false, true, sizeof(mcd_reg_st)); + + if (strcmp(arch, "arm")==0) { + // TODO: make group and memspace ids dynamic + int current_group_id = 1; + // 1. store mem spaces + return_value = mcd_arm_store_mem_spaces(cpu, memspaces); + if (return_value!=0) assert(0); + // 2. parse core xml + return_value = mcd_arm_parse_core_xml_file(cc, reggroups, registers, ¤t_group_id); + if (return_value!=0) assert(0); + // 3. parse other xmls + return_value = mcd_arm_parse_general_xml_files(cpu, reggroups, registers, ¤t_group_id); + if (return_value!=0) assert(0); + // 4. add additional data the the regs from the xmls + return_value = mcd_arm_get_additional_register_info(reggroups, registers); + if (return_value!=0) assert(0); + // 5. store all found data + if (g_list_nth(mcdserver_state.all_memspaces, cpu_id)) { + GList* memspaces_ptr = g_list_nth(mcdserver_state.all_memspaces, cpu_id); + memspaces_ptr->data = memspaces; + } + else { + mcdserver_state.all_memspaces = g_list_insert(mcdserver_state.all_memspaces, memspaces, cpu_id); + } + if (g_list_nth(mcdserver_state.all_reggroups, cpu_id)) { + GList* reggroups_ptr = g_list_nth(mcdserver_state.all_reggroups, cpu_id); + reggroups_ptr->data = reggroups; + } + else { + mcdserver_state.all_reggroups = g_list_insert(mcdserver_state.all_reggroups, reggroups, cpu_id); + } + if (g_list_nth(mcdserver_state.all_registers, cpu_id)) { + GList* registers_ptr = g_list_nth(mcdserver_state.all_registers, cpu_id); + registers_ptr->data = registers; + } + else { + mcdserver_state.all_registers = g_list_insert(mcdserver_state.all_registers, registers, cpu_id); } - // free memory - g_list_free(register_numbers); } else { // we don't support other architectures @@ -1170,30 +1293,77 @@ void handle_open_core(GArray *params, void *user_ctx) { g_free(arch); } -void handle_query_reset(GArray *params, void *user_ctx) { +void handle_query_reset_f(GArray *params, void *user_ctx) { // resetting has to be done over a monitor (look ar Rcmd) so we tell MCD that we can reset but this still need to be implemented - // we only support one reset over this monitor and that would be a fully "system_restart" - mcd_put_packet("nr=\"3\",info=\"0,full_system_reset;1,gpr_reset;2,memory_reset;\""); + // we only support one reset over this monitor and that would be a full "system_restart" + // reset options are the same for every cpu! + + // 1. check length + int nb_resets = mcdserver_state.resets->len; + if (nb_resets == 1) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); + } + else { + g_string_printf(mcdserver_state.str_buf, "1!"); + } + // 2. send data + mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + mcd_put_strbuf(); + // TODO: we still need to implement the gpr and memory reset here! +} + +void handle_query_reset_c(GArray *params, void *user_ctx) { + // reset options are the same for every cpu! + int query_index = get_param(params, 0)->query_handle; + + // 1. check weather this was the last mem space + int nb_groups = mcdserver_state.resets->len; + if (query_index+1 == nb_groups) { + // indicates this is the last packet + g_string_printf(mcdserver_state.str_buf, "0!"); + } + else { + g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); + } + + // 2. send data + mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + mcd_put_strbuf(); // TODO: we still need to implement the gpr and memory reset here! } -void handle_detach(GArray *params, void *user_ctx) { +void handle_close_core(GArray *params, void *user_ctx) { + // free memory for correct core + uint32_t cpu_id = get_param(params, 0)->cpu_id; + GArray* memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + g_array_free(memspaces, TRUE); + GArray* reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + g_array_free(reggroups, TRUE); + GArray* registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + g_array_free(registers, TRUE); +} + +void handle_close_server(GArray *params, void *user_ctx) { uint32_t pid = 1; MCDProcess *process = mcd_get_process(pid); - // 1. cleanup - // gdb_process_breakpoint_remove_all(process); + // 1. free memory + // TODO: do this only if there are no processes attached anymore! + g_list_free(mcdserver_state.all_memspaces); + g_list_free(mcdserver_state.all_reggroups); + g_list_free(mcdserver_state.all_registers); + g_array_free(mcdserver_state.resets, TRUE); // 2. detach process->attached = false; - // reset current cpus - // TODO: if we don't use c_cpu we can delete this - // this also checks to only reset THIS process we also probably don't need this since we only got one process! + // 3. reset process if (pid == mcd_get_cpu_pid(mcdserver_state.c_cpu)) { mcdserver_state.c_cpu = mcd_first_attached_cpu(); } - if (!mcdserver_state.c_cpu) { /* No more process attached */ mcd_disable_syscalls(); @@ -1202,14 +1372,10 @@ void handle_detach(GArray *params, void *user_ctx) { } void handle_query_trigger(GArray *params, void *user_ctx) { - // set the type, option and action bitmask and send it - - uint32_t type = (MCD_TRIG_TYPE_IP | MCD_TRIG_TYPE_READ | MCD_TRIG_TYPE_WRITE | MCD_TRIG_TYPE_RW); - uint32_t option = (MCD_TRIG_OPT_DATA_IS_CONDITION); - uint32_t action = (MCD_TRIG_ACTION_DBG_DEBUG); - uint32_t nr_trigger = 4; - - g_string_printf(mcdserver_state.str_buf, "nr=\"%d\",info=\"%d;%d;%d;\"", nr_trigger, type, option, action); + mcd_trigger_st trigger = mcdserver_state.trigger; + g_string_printf(mcdserver_state.str_buf, "%s=%d.%s=%d.%s=%d.%s=%d.", + TCP_ARGUMENT_AMOUNT_TRIGGER, trigger.nr_trigger, TCP_ARGUMENT_TYPE, trigger.type, + TCP_ARGUMENT_OPTION, trigger.option, TCP_ARGUMENT_ACTION, trigger.action); mcd_put_strbuf(); } @@ -1221,8 +1387,13 @@ void mcd_continue(void) } void handle_query_mem_spaces_f(GArray *params, void *user_ctx) { - // send the first mem space - int nb_groups = mcdserver_state.memspaces->len; + // 1. get correct memspaces and set the query_cpu + uint32_t cpu_id = get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id = cpu_id; + GArray* memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + + // 2. check length + int nb_groups = memspaces->len; if (nb_groups == 1) { // indicates this is the last packet g_string_printf(mcdserver_state.str_buf, "0!"); @@ -1230,20 +1401,26 @@ void handle_query_mem_spaces_f(GArray *params, void *user_ctx) { else { g_string_printf(mcdserver_state.str_buf, "1!"); } - mcd_mem_space_st space = g_array_index(mcdserver_state.memspaces, mcd_mem_space_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "name=%s.id=%d.type=%d.bpm=%d.i=%d.e=%d.min=%ld.max=%ld.sao=%d.", - space.name, space.id, space.type, space.bits_per_mau, space.invariance, space.endian, - space.min_addr, space.max_addr, space.supported_access_options); + + // 3. send data + mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", + TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, space.id, TCP_ARGUMENT_TYPE, space.type, + TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, TCP_ARGUMENT_ENDIAN, space.endian, + TCP_ARGUMENT_MIN, space.min_addr, TCP_ARGUMENT_MAX, space.max_addr, + TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_options); mcd_put_strbuf(); } void handle_query_mem_spaces_c(GArray *params, void *user_ctx) { // this funcitons send all mem spaces except for the first - // 1. get parameter + // 1. get parameter and memspace int query_index = get_param(params, 0)->query_handle; + uint32_t cpu_id = mcdserver_state.query_cpu_id; + GArray* memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); // 2. check weather this was the last mem space - int nb_groups = mcdserver_state.memspaces->len; + int nb_groups = memspaces->len; if (query_index+1 == nb_groups) { // indicates this is the last packet g_string_printf(mcdserver_state.str_buf, "0!"); @@ -1253,16 +1430,23 @@ void handle_query_mem_spaces_c(GArray *params, void *user_ctx) { } // 3. send the correct memspace - mcd_mem_space_st space = g_array_index(mcdserver_state.memspaces, mcd_mem_space_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "name=%s.id=%d.type=%d.bpm=%d.i=%d.e=%d.min=%ld.max=%ld.sao=%d.", - space.name, space.id, space.type, space.bits_per_mau, space.invariance, space.endian, - space.min_addr, space.max_addr, space.supported_access_options); + mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", + TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, space.id, TCP_ARGUMENT_TYPE, space.type, + TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, TCP_ARGUMENT_ENDIAN, space.endian, + TCP_ARGUMENT_MIN, space.min_addr, TCP_ARGUMENT_MAX, space.max_addr, + TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_options); mcd_put_strbuf(); } void handle_query_reg_groups_f(GArray *params, void *user_ctx) { - // send the first reg group - int nb_groups = mcdserver_state.reggroups->len; + // 1. get correct reggroups and set the query_cpu + uint32_t cpu_id = get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id = cpu_id; + GArray* reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + + // 2. check length + int nb_groups = reggroups->len; if (nb_groups == 1) { // indicates this is the last packet g_string_printf(mcdserver_state.str_buf, "0!"); @@ -1270,18 +1454,21 @@ void handle_query_reg_groups_f(GArray *params, void *user_ctx) { else { g_string_printf(mcdserver_state.str_buf, "1!"); } - mcd_reg_group_st group = g_array_index(mcdserver_state.reggroups, mcd_reg_group_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.", group.id, group.name); + // 3. send data + mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); mcd_put_strbuf(); } void handle_query_reg_groups_c(GArray *params, void *user_ctx) { // this funcitons send all reg groups except for the first - // 1. get parameter + // 1. get parameter and memspace int query_index = get_param(params, 0)->query_handle; + uint32_t cpu_id = mcdserver_state.query_cpu_id; + GArray* reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); // 2. check weather this was the last reg group - int nb_groups = mcdserver_state.reggroups->len; + int nb_groups = reggroups->len; if (query_index+1 == nb_groups) { // indicates this is the last packet g_string_printf(mcdserver_state.str_buf, "0!"); @@ -1291,14 +1478,19 @@ void handle_query_reg_groups_c(GArray *params, void *user_ctx) { } // 3. send the correct reggroup - mcd_reg_group_st group = g_array_index(mcdserver_state.reggroups, mcd_reg_group_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.", group.id, group.name); + mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); mcd_put_strbuf(); } void handle_query_regs_f(GArray *params, void *user_ctx) { - // send the first register - int nb_regs = mcdserver_state.registers->len; + // 1. get correct registers and set the query_cpu + uint32_t cpu_id = get_param(params, 0)->cpu_id; + mcdserver_state.query_cpu_id = cpu_id; + GArray* registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + + // 2. check length + int nb_regs = registers->len; if (nb_regs == 1) { // indicates this is the last packet g_string_printf(mcdserver_state.str_buf, "0!"); @@ -1306,20 +1498,24 @@ void handle_query_regs_f(GArray *params, void *user_ctx) { else { g_string_printf(mcdserver_state.str_buf, "1!"); } - mcd_reg_st my_register = g_array_index(mcdserver_state.registers, mcd_reg_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.size=%d.reggroupid=%d.memspaceid=%d.type=%d.thread=%d.", - my_register.id, my_register.name, my_register.bitsize, my_register.mcd_reg_group_id, - my_register.mcd_mem_space_id, my_register.mcd_reg_type, my_register.mcd_hw_thread_id); + // 3. send data + mcd_reg_st my_register = g_array_index(registers, mcd_reg_st, 0); + g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", + TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, + TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, + TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); mcd_put_strbuf(); } void handle_query_regs_c(GArray *params, void *user_ctx) { - // this funcitons send all registers except for the first - // 1. get parameter + // this funcitons send all reg groups except for the first + // 1. get parameter and registers int query_index = get_param(params, 0)->query_handle; + uint32_t cpu_id = mcdserver_state.query_cpu_id; + GArray* registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); // 2. check weather this was the last register - int nb_regs = mcdserver_state.registers->len; + int nb_regs = registers->len; if (query_index+1 == nb_regs) { // indicates this is the last packet g_string_printf(mcdserver_state.str_buf, "0!"); @@ -1329,9 +1525,10 @@ void handle_query_regs_c(GArray *params, void *user_ctx) { } // 3. send the correct register - mcd_reg_st my_register = g_array_index(mcdserver_state.registers, mcd_reg_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "id=%d.name=%s.size=%d.reggroupid=%d.memspaceid=%d.type=%d.thread=%d.", - my_register.id, my_register.name, my_register.bitsize, my_register.mcd_reg_group_id, - my_register.mcd_mem_space_id, my_register.mcd_reg_type, my_register.mcd_hw_thread_id); + mcd_reg_st my_register = g_array_index(registers, mcd_reg_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", + TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, + TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, + TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); mcd_put_strbuf(); } From patchwork Fri Oct 6 09:05:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844312 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22ld5GDsz1yqH for ; Fri, 6 Oct 2023 20:13:17 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogn8-00087I-F9; Fri, 06 Oct 2023 05:06:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogn6-00086X-3r for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:36 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogmy-0000wT-EQ for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:35 -0400 Received: (qmail 19558 invoked by uid 484); 6 Oct 2023 09:06:25 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 4e-06 secs); 06 Oct 2023 09:06:25 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:23 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 10/29] handler for resets added Date: Fri, 6 Oct 2023 11:05:51 +0200 Message-Id: <20231006090610.26171-11-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 14 ++++---- mcdstub/mcd_shared_defines.h | 4 +++ mcdstub/mcdstub.c | 65 ++++++++++++++++++++++++++++-------- 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index a4d49a4a84..0de8d8fd07 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -25,6 +25,7 @@ // schema defines #define ARG_SCHEMA_QRYHANDLE 'q' #define ARG_SCHEMA_STRING 's' +#define ARG_SCHEMA_INT 'd' #define ARG_SCHEMA_CORENUM 'c' // resets @@ -34,8 +35,8 @@ // more #define QUERY_TOTAL_NUMBER 11 //FIXME: set this to a usefull value in the end -#define CMD_SCHEMA_LENGTH 2 -#define MCD_MAX_CORES 128 +#define CMD_SCHEMA_LENGTH 3 +#define MAX_SCHEMA_ARGS CMD_SCHEMA_LENGTH-1 #define MCD_SYSTEM_NAME "qemu-system" // tcp query packet values templates #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" @@ -77,17 +78,17 @@ typedef enum MCDThreadIdKind { } MCDThreadIdKind; typedef union MCDCmdVariant { - const char *data; + const char *data; + int data_int; + int query_handle; + int cpu_id; struct { MCDThreadIdKind kind; uint32_t pid; uint32_t tid; } thread_id; - int query_handle; - int cpu_id; - } MCDCmdVariant; #define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) @@ -277,6 +278,7 @@ void handle_query_regs_f(GArray *params, void *user_ctx); void handle_query_regs_c(GArray *params, void *user_ctx); void handle_open_server(GArray *params, void *user_ctx); void parse_reg_xml(const char *xml, int size, GArray* registers); +void handle_reset(GArray *params, void *user_ctx); // arm specific functions int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces); diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index e0b27ce5e6..7e96129cdf 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -11,6 +11,7 @@ #define TCP_CHAR_CLOSE_SERVER 'D' #define TCP_CHAR_CLOSE_CORE 'd' #define TCP_CHAR_KILLQEMU 'k' +#define TCP_CHAR_RESET 'r' // tcp protocol chars #define TCP_ACKNOWLEDGED '+' @@ -54,4 +55,7 @@ #define TCP_ARGUMENT_OPTION "option" #define TCP_ARGUMENT_ACTION "action" +// for packets sent to qemu +#define ARGUMENT_SEPARATOR ';' + #endif diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index a0c4c2794f..85e0c3a219 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -508,6 +508,16 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &close_core_cmd_desc; } break; + case TCP_CHAR_RESET: + { + static MCDCmdParseEntry reset_cmd_desc = { + .handler = handle_reset, + }; + reset_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_RESET, '\0' }; + strcpy(reset_cmd_desc.schema, (char[3]) { (char) ARG_SCHEMA_INT, ARG_SCHEMA_INT, '\0' }); + cmd_parser = &reset_cmd_desc; + } + break; default: // could not perform the command (because its unknown) mcd_put_packet(""); @@ -564,24 +574,42 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) } int cmd_parse_params(const char *data, const char *schema, GArray *params) { - MCDCmdVariant this_param; - + char data_buffer[64] = {0}; - if (schema[0] == ARG_SCHEMA_STRING) { - this_param.data = data; - g_array_append_val(params, this_param); - } - else if (schema[0] == ARG_SCHEMA_QRYHANDLE) { - strncat(data_buffer, data, strlen(data)); - this_param.query_handle = atoi(data_buffer); - g_array_append_val(params, this_param); + char *separator = strchr(data_buffer, ARGUMENT_SEPARATOR); + int seperator_index = (int)(separator - data); + + if (separator) { + // we got two arguments + strncpy(data_buffer, data, seperator_index); } - else if (schema[0] == ARG_SCHEMA_CORENUM) { - strncat(data_buffer, data, strlen(data)); - this_param.cpu_id = atoi(data_buffer); - g_array_append_val(params, this_param); + else { + strncpy(data_buffer, data, strlen(data)); } + for (int i = 0; idata_int; + int bool_halt_after_reset = get_param(params, 1)->data_int; + if (reset_id>=0 && bool_halt_after_reset) { + //fun for the compiler + } + +} From patchwork Fri Oct 6 09:05:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844288 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22d36JT6z1yqF for ; Fri, 6 Oct 2023 20:07:35 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognF-00089F-QJ; Fri, 06 Oct 2023 05:06:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognD-00088e-NS for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:43 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogn8-0000wf-Fa for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:43 -0400 Received: (qmail 19580 invoked by uid 484); 6 Oct 2023 09:06:26 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.082053 secs); 06 Oct 2023 09:06:26 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:25 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 11/29] query for the VM state added Date: Fri, 6 Oct 2023 11:05:52 +0200 Message-Id: <20231006090610.26171-12-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 54 ++++++++- mcdstub/mcd_shared_defines.h | 13 ++ mcdstub/mcdstub.c | 229 ++++++++++++++++++++++++++++------- 3 files changed, 249 insertions(+), 47 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 0de8d8fd07..2c64cfc0f9 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -22,6 +22,21 @@ #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 +typedef uint32_t mcd_core_event_et; +enum { + MCD_CORE_EVENT_NONE = 0x00000000, /**< No since the last poll. */ + MCD_CORE_EVENT_MEMORY_CHANGE = 0x00000001, /**< Memory content has changed. */ + MCD_CORE_EVENT_REGISTER_CHANGE = 0x00000002, /**< Register contents have changed. */ + MCD_CORE_EVENT_TRACE_CHANGE = 0x00000004, /**< Trace contents or states have changed. */ + MCD_CORE_EVENT_TRIGGER_CHANGE = 0x00000008, /**< Triggers or trigger states have changed. */ + MCD_CORE_EVENT_STOPPED = 0x00000010, /**< Target was stopped at least once since the last poll, + it may already be running again. */ + MCD_CORE_EVENT_CHL_PENDING = 0x00000020, /**< A target communication channel request from the target + is pending. */ + MCD_CORE_EVENT_CUSTOM_LO = 0x00010000, /**< Begin Range: User defined core events. */ + MCD_CORE_EVENT_CUSTOM_HI = 0x40000000, /**< End Range: User defined core events. */ +}; + // schema defines #define ARG_SCHEMA_QRYHANDLE 'q' #define ARG_SCHEMA_STRING 's' @@ -34,13 +49,25 @@ #define RESET_MEMORY "memory_reset" // more -#define QUERY_TOTAL_NUMBER 11 //FIXME: set this to a usefull value in the end -#define CMD_SCHEMA_LENGTH 3 -#define MAX_SCHEMA_ARGS CMD_SCHEMA_LENGTH-1 +#define QUERY_TOTAL_NUMBER 12 //FIXME: set this to a usefull value in the end +#define CMD_SCHEMA_LENGTH 2 #define MCD_SYSTEM_NAME "qemu-system" // tcp query packet values templates #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" +// state strings +#define STATE_STR_UNKNOWN(d) "cpu " #d " in unknown state" +#define STATE_STR_DEBUG(d) "cpu " #d " in debug state" +#define STATE_STR_RUNNING(d) "cpu " #d " running" +#define STATE_STR_HALTED(d) "cpu " #d " currently halted" +#define STATE_STR_INIT_HALTED "vm halted since boot" +#define STATE_STR_INIT_RUNNING "vm running since boot" +#define STATE_STR_BREAK_HW "stopped beacuse of HW breakpoint" +#define STATE_STR_BREAK_READ(d) "stopped beacuse of read access at " #d +#define STATE_STR_BREAK_WRITE(d) "stopped beacuse of write access at " #d +#define STATE_STR_BREAK_RW(d) "stopped beacuse of read or write access at " #d +#define STATE_STR_BREAK_UNKNOWN "stopped for unknown reason" + // GDB stuff thats needed for GDB function, which we use typedef struct GDBRegisterState { int base_reg; @@ -113,6 +140,16 @@ typedef struct mcd_trigger_st { uint32_t nr_trigger; } mcd_trigger_st; +typedef struct mcd_cpu_state_st { + const char *state; + bool memory_changed; + bool registers_changed; + bool target_was_stopped; + uint32_t trig_id; + const char *stop_str; + const char *info_str; +} mcd_cpu_state_st; + typedef struct MCDState { bool init; /* have we been initialised? */ CPUState *c_cpu; /* current CPU for everything */ @@ -134,12 +171,15 @@ typedef struct MCDState { int supported_sstep_flags; // my stuff + RunState vm_current_state; + RunState vm_previous_state; uint32_t query_cpu_id; GList *all_memspaces; GList *all_reggroups; GList *all_registers; GArray *resets; mcd_trigger_st trigger; + mcd_cpu_state_st cpu_state; MCDCmdParseEntry mcd_query_cmds_table[QUERY_TOTAL_NUMBER]; } MCDState; @@ -254,9 +294,9 @@ void mcd_exit(int code); void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd); int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds); int cmd_parse_params(const char *data, const char *schema, GArray *params); -void handle_continue(GArray *params, void *user_ctx); +void handle_vm_start(GArray *params, void *user_ctx); +void handle_vm_stop(GArray *params, void *user_ctx); void handle_gen_query(GArray *params, void *user_ctx); -void mcd_append_thread_id(CPUState *cpu, GString *buf); int mcd_get_cpu_index(CPUState *cpu); CPUState* mcd_get_cpu(uint32_t i_cpu_index); void handle_query_cores(GArray *params, void *user_ctx); @@ -269,7 +309,8 @@ void handle_query_reset_c(GArray *params, void *user_ctx); void handle_close_server(GArray *params, void *user_ctx); void handle_close_core(GArray *params, void *user_ctx); void handle_query_trigger(GArray *params, void *user_ctx); -void mcd_continue(void); +void mcd_vm_start(void); +void mcd_vm_stop(void); void handle_query_reg_groups_f(GArray *params, void *user_ctx); void handle_query_reg_groups_c(GArray *params, void *user_ctx); void handle_query_mem_spaces_f(GArray *params, void *user_ctx); @@ -279,6 +320,7 @@ void handle_query_regs_c(GArray *params, void *user_ctx); void handle_open_server(GArray *params, void *user_ctx); void parse_reg_xml(const char *xml, int size, GArray* registers); void handle_reset(GArray *params, void *user_ctx); +void handle_query_state(GArray *params, void *user_ctx); // arm specific functions int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces); diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 7e96129cdf..8cec2e9f23 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -7,6 +7,7 @@ #define TCP_CHAR_OPEN_SERVER 'I' #define TCP_CHAR_OPEN_CORE 'i' #define TCP_CHAR_GO 'c' +#define TCP_CHAR_BREAK 'b' #define TCP_CHAR_QUERY 'q' #define TCP_CHAR_CLOSE_SERVER 'D' #define TCP_CHAR_CLOSE_CORE 'd' @@ -33,6 +34,7 @@ #define QUERY_ARG_MEMORY "memory" #define QUERY_ARG_REGGROUP "reggroup" #define QUERY_ARG_REG "reg" +#define QUERY_ARG_STATE "state" // tcp query packet argument list #define TCP_ARGUMENT_NAME "name" @@ -48,6 +50,11 @@ #define TCP_ARGUMENT_MEMSPACEID "memspaceid" #define TCP_ARGUMENT_SIZE "size" #define TCP_ARGUMENT_THREAD "thread" +#define TCP_ARGUMENT_TRIGGER_ID "trig_id" +#define TCP_ARGUMENT_STOP_STRING "stop_str" +#define TCP_ARGUMENT_INFO_STRING "info_str" +#define TCP_ARGUMENT_STATE "state" +#define TCP_ARGUMENT_EVENT "event" #define TCP_ARGUMENT_DEVICE "device" #define TCP_ARGUMENT_CORE "core" #define TCP_ARGUMENT_AMOUNT_CORE "nr_cores" @@ -58,4 +65,10 @@ // for packets sent to qemu #define ARGUMENT_SEPARATOR ';' +// core states +#define CORE_STATE_RUNNING "running" +#define CORE_STATE_HALTED "halted" +#define CORE_STATE_DEBUG "debug" +#define CORE_STATE_UNKNOWN "unknown" + #endif diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 85e0c3a219..dc40a68338 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -68,6 +68,13 @@ void mcd_init_mcdserver_state(void) // init query table init_query_cmds_table(mcdserver_state.mcd_query_cmds_table); + + // at this time the cpu hans't been started! -> set cpu_state + mcd_cpu_state_st cpu_state = { + .state = CORE_STATE_HALTED, + .info_str = STATE_STR_INIT_HALTED, + }; + mcdserver_state.cpu_state = cpu_state; } void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { @@ -156,6 +163,14 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { }; strcpy(query_regs_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); mcd_query_cmds_table[cmd_number] = query_regs_c; + cmd_number++; + + MCDCmdParseEntry query_state = { + .handler = handle_query_state, + .cmd = QUERY_ARG_STATE, + }; + strcpy(query_state.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + mcd_query_cmds_table[cmd_number] = query_state; } void reset_mcdserver_state(void) @@ -336,6 +351,7 @@ void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) for (i = 0; i < size; i++) { mcd_read_byte(buf[i]); + if (buf[i]==0) break; } } @@ -366,12 +382,12 @@ void mcd_read_byte(uint8_t ch) return; } } - if (runstate_is_running()) { + //if (runstate_is_running()) { /* when the CPU is running, we cannot do anything except stop it when receiving a char */ - vm_stop(RUN_STATE_PAUSED); - } - else { + //vm_stop(RUN_STATE_PAUSED); + //} + //else { switch(mcdserver_state.state) { case RS_IDLE: if (ch == TCP_COMMAND_START) { @@ -434,7 +450,7 @@ void mcd_read_byte(uint8_t ch) default: abort(); } - } + //} } int mcd_handle_packet(const char *line_buf) @@ -457,12 +473,22 @@ int mcd_handle_packet(const char *line_buf) // go command { static MCDCmdParseEntry go_cmd_desc = { - .handler = handle_continue, + .handler = handle_vm_start, }; go_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_GO, '\0' }; cmd_parser = &go_cmd_desc; } break; + case TCP_CHAR_BREAK: + // go command + { + static MCDCmdParseEntry break_cmd_desc = { + .handler = handle_vm_stop, + }; + break_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_BREAK, '\0' }; + cmd_parser = &break_cmd_desc; + } + break; case TCP_CHAR_KILLQEMU: // kill qemu completely error_report("QEMU: Terminated via MCDstub"); @@ -514,7 +540,7 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_reset, }; reset_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_RESET, '\0' }; - strcpy(reset_cmd_desc.schema, (char[3]) { (char) ARG_SCHEMA_INT, ARG_SCHEMA_INT, '\0' }); + strcpy(reset_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_INT, '\0' }); cmd_parser = &reset_cmd_desc; } break; @@ -532,16 +558,14 @@ int mcd_handle_packet(const char *line_buf) return RS_IDLE; } -void handle_continue(GArray *params, void *user_ctx) -{ - /* - if (params->len) { - gdb_set_cpu_pc(get_param(params, 0)->val_ull); - } +void handle_vm_start(GArray *params, void *user_ctx) { + // todo add partial restart with arguments and so on + mcd_vm_start(); +} - mcdserver_state.signal = 0; - gdb_continue(); - */ +void handle_vm_stop(GArray *params, void *user_ctx) { + // todo add partial stop with arguments and so on + mcd_vm_stop(); } void handle_gen_query(GArray *params, void *user_ctx) @@ -576,7 +600,7 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) int cmd_parse_params(const char *data, const char *schema, GArray *params) { char data_buffer[64] = {0}; - char *separator = strchr(data_buffer, ARGUMENT_SEPARATOR); + char *separator = strchr(data, ARGUMENT_SEPARATOR); int seperator_index = (int)(separator - data); if (separator) { @@ -586,25 +610,29 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) { else { strncpy(data_buffer, data, strlen(data)); } - for (int i = 0; ischema) { + if (strlen(cmd->schema)) { // this only gets the data from data beginning after the command name if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, params)) { return -1; @@ -679,7 +707,7 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event) s->c_cpu = mcd_first_attached_cpu(); - vm_stop(RUN_STATE_PAUSED); + //vm_stop(RUN_STATE_PAUSED); //TODO: this might not be necessary //replay_gdb_attached(); //gdb_has_xml = false; @@ -709,14 +737,98 @@ void mcd_sigterm_handler(int signal) void mcd_vm_state_change(void *opaque, bool running, RunState state) { - printf("this calls state_change\n"); + CPUState *cpu = mcdserver_state.c_cpu; + + // update cpu state + mcdserver_state.vm_previous_state = mcdserver_state.vm_current_state; + mcdserver_state.vm_current_state = state; + + if (mcdserver_state.state == RS_INACTIVE) { + return; + } + + if (cpu == NULL) { + if (running) { + // this is the case if qemu starts the vm before any mcd is connected + const char *mcd_state; + mcd_state = CORE_STATE_RUNNING; + const char *info_str; + info_str = STATE_STR_INIT_RUNNING; + mcdserver_state.cpu_state.state = mcd_state; + mcdserver_state.cpu_state.state = info_str; + } + return; + } + + const char *mcd_state; + const char *stop_str; + const char *info_str; + uint32_t trig_id = 0; + switch (state) { + case RUN_STATE_RUNNING: + mcd_state = CORE_STATE_RUNNING; + info_str = STATE_STR_RUNNING(cpu->cpu_index); + stop_str = ""; + break; + case RUN_STATE_DEBUG: + mcd_state = CORE_STATE_DEBUG; + info_str = STATE_STR_DEBUG(cpu->cpu_index); + if (cpu->watchpoint_hit) { + switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { + case BP_MEM_READ: + trig_id = MCD_TRIG_TYPE_READ; + stop_str = STATE_STR_BREAK_READ(cpu->watchpoint_hit->hitaddr); + break; + case BP_MEM_WRITE: + trig_id = MCD_TRIG_TYPE_WRITE; + stop_str = STATE_STR_BREAK_WRITE(cpu->watchpoint_hit->hitaddr); + break; + case BP_MEM_ACCESS: + trig_id = MCD_TRIG_TYPE_RW; + stop_str = STATE_STR_BREAK_RW(cpu->watchpoint_hit->hitaddr); + break; + default: + break; + stop_str = STATE_STR_BREAK_UNKNOWN; + } + cpu->watchpoint_hit = NULL; + } else { + // "hardware" breakpoint hit! + trig_id = MCD_TRIG_TYPE_IP; + stop_str = STATE_STR_BREAK_HW; + tb_flush(cpu); + } + break; + case RUN_STATE_PAUSED: + info_str = STATE_STR_HALTED(cpu->cpu_index); + mcd_state = CORE_STATE_HALTED; + stop_str = ""; + break; + case RUN_STATE_WATCHDOG: + info_str = STATE_STR_UNKNOWN(cpu->cpu_index); + mcd_state = CORE_STATE_UNKNOWN; + stop_str = ""; + printf("runstate watchdog hit\n"); + break; + default: + info_str = STATE_STR_UNKNOWN(cpu->cpu_index); + mcd_state = CORE_STATE_UNKNOWN; + stop_str = ""; + // we don't care; + break; + } + + mcdserver_state.cpu_state.state = mcd_state; + mcdserver_state.cpu_state.trig_id = trig_id; + mcdserver_state.cpu_state.stop_str = stop_str; + mcdserver_state.cpu_state.info_str = info_str; + + /* disable single step if it was enabled */ + cpu_single_step(cpu, 0); } int mcd_put_packet(const char *buf) { - //tracing - //trace_gdbstub_io_reply(buf); - return mcd_put_packet_binary(buf, strlen(buf), false); } @@ -1267,6 +1379,7 @@ void handle_open_core(GArray *params, void *user_ctx) { // get the cpu whith the given id uint32_t cpu_id = get_param(params, 0)->cpu_id; CPUState *cpu = mcd_get_cpu(cpu_id); + mcdserver_state.c_cpu = cpu; CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); int return_value = 0; @@ -1318,6 +1431,7 @@ void handle_open_core(GArray *params, void *user_ctx) { // we don't support other architectures assert(0); } + g_free(arch); } @@ -1367,10 +1481,13 @@ void handle_close_core(GArray *params, void *user_ctx) { // free memory for correct core uint32_t cpu_id = get_param(params, 0)->cpu_id; GArray* memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcdserver_state.all_memspaces = g_list_remove(mcdserver_state.all_memspaces, memspaces); g_array_free(memspaces, TRUE); GArray* reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + mcdserver_state.all_reggroups = g_list_remove(mcdserver_state.all_reggroups, reggroups); g_array_free(reggroups, TRUE); GArray* registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + mcdserver_state.all_registers = g_list_remove(mcdserver_state.all_registers, registers); g_array_free(registers, TRUE); } @@ -1395,7 +1512,7 @@ void handle_close_server(GArray *params, void *user_ctx) { if (!mcdserver_state.c_cpu) { /* No more process attached */ mcd_disable_syscalls(); - mcd_continue(); + mcd_vm_start(); } } @@ -1407,13 +1524,19 @@ void handle_query_trigger(GArray *params, void *user_ctx) { mcd_put_strbuf(); } -void mcd_continue(void) -{ - if (!runstate_needs_reset()) { +void mcd_vm_start(void) { + if (!runstate_needs_reset() && !runstate_is_running()) { vm_start(); } } +void mcd_vm_stop(void) { + if (runstate_is_running()) { + //might want to have DEBUG state here but idk + vm_stop(RUN_STATE_PAUSED); + } +} + void handle_query_mem_spaces_f(GArray *params, void *user_ctx) { // 1. get correct memspaces and set the query_cpu uint32_t cpu_id = get_param(params, 0)->cpu_id; @@ -1563,9 +1686,33 @@ void handle_query_regs_c(GArray *params, void *user_ctx) { void handle_reset(GArray *params, void *user_ctx) { int reset_id = get_param(params, 0)->data_int; - int bool_halt_after_reset = get_param(params, 1)->data_int; - if (reset_id>=0 && bool_halt_after_reset) { + //int bool_halt_after_reset = get_param(params, 1)->data_int; + if (reset_id>=0) { //fun for the compiler } - +} + +void handle_query_state(GArray *params, void *user_ctx) { + // send state from correct core + //uint32_t cpu_id = get_param(params, 0)->cpu_id; + // get state info + mcd_cpu_state_st state_info = mcdserver_state.cpu_state; + mcd_core_event_et event = MCD_CORE_EVENT_NONE; + if (state_info.memory_changed) { + event = event | MCD_CORE_EVENT_MEMORY_CHANGE; + state_info.memory_changed = false; + } + if (state_info.registers_changed) { + event = event | MCD_CORE_EVENT_REGISTER_CHANGE; + state_info.registers_changed = false; + } + if (state_info.target_was_stopped) { + event = event | MCD_CORE_EVENT_STOPPED; + state_info.target_was_stopped = false; + } + // send data + g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.%s=%d.%s=%d.%s=%s.%s=%s.", TCP_ARGUMENT_STATE, state_info.state, + TCP_ARGUMENT_EVENT, event, TCP_ARGUMENT_THREAD, 0, TCP_ARGUMENT_TRIGGER_ID, state_info.trig_id, + TCP_ARGUMENT_STOP_STRING, state_info.stop_str, TCP_ARGUMENT_INFO_STRING, state_info.info_str); + mcd_put_strbuf(); } From patchwork Fri Oct 6 09:05:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844295 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dw3Rwvz1yqF for ; Fri, 6 Oct 2023 20:08:20 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognG-00089P-OD; Fri, 06 Oct 2023 05:06:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognE-00088l-90 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:44 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognA-0000x6-WE for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:44 -0400 Received: (qmail 19601 invoked by uid 484); 6 Oct 2023 09:06:27 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.072201 secs); 06 Oct 2023 09:06:27 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:27 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 12/29] handler for reading registers added Date: Fri, 6 Oct 2023 11:05:53 +0200 Message-Id: <20231006090610.26171-13-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 11 ++- mcdstub/mcd_shared_defines.h | 7 ++ mcdstub/mcdstub.c | 129 +++++++++++++++++++++++++++++++++++ target/arm/mcdstub.c | 75 ++++++++++++++++++++ target/arm/mcdstub.h | 7 ++ 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 target/arm/mcdstub.c create mode 100644 target/arm/mcdstub.h diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 2c64cfc0f9..a85173d0d1 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -41,6 +41,7 @@ enum { #define ARG_SCHEMA_QRYHANDLE 'q' #define ARG_SCHEMA_STRING 's' #define ARG_SCHEMA_INT 'd' +#define ARG_SCHEMA_UINT32_T 'l' #define ARG_SCHEMA_CORENUM 'c' // resets @@ -50,7 +51,7 @@ enum { // more #define QUERY_TOTAL_NUMBER 12 //FIXME: set this to a usefull value in the end -#define CMD_SCHEMA_LENGTH 2 +#define CMD_SCHEMA_LENGTH 3 #define MCD_SYSTEM_NAME "qemu-system" // tcp query packet values templates #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" @@ -108,6 +109,7 @@ typedef union MCDCmdVariant { const char *data; int data_int; + uint64_t data_uint64_t; int query_handle; int cpu_id; struct { @@ -321,6 +323,12 @@ void handle_open_server(GArray *params, void *user_ctx); void parse_reg_xml(const char *xml, int size, GArray* registers); void handle_reset(GArray *params, void *user_ctx); void handle_query_state(GArray *params, void *user_ctx); +void handle_read_register(GArray *params, void *user_ctx); +void handle_write_register(GArray *params, void *user_ctx); +void handle_read_memory(GArray *params, void *user_ctx); +void handle_write_memory(GArray *params, void *user_ctx); +int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); +int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); // arm specific functions int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces); @@ -334,5 +342,6 @@ void mcd_disable_syscalls(void); // helpers int int_cmp(gconstpointer a, gconstpointer b); +void mcd_memtohex(GString *buf, const uint8_t *mem, int len); #endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 8cec2e9f23..47d5d46af3 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -13,6 +13,10 @@ #define TCP_CHAR_CLOSE_CORE 'd' #define TCP_CHAR_KILLQEMU 'k' #define TCP_CHAR_RESET 'r' +#define TCP_CHAR_READ_REGISTER 'p' +#define TCP_CHAR_WRITE_REGISTER 'P' +#define TCP_CHAR_READ_MEMORY 'm' +#define TCP_CHAR_WRITE_MEMORY 'M' // tcp protocol chars #define TCP_ACKNOWLEDGED '+' @@ -22,6 +26,8 @@ #define TCP_WAS_LAST '|' #define TCP_WAS_NOT_LAST '~' #define TCP_HANDSHAKE_SUCCESS "shaking your hand" +#define TCP_EXECUTION_SUCCESS "success" +#define TCP_EXECUTION_ERROR "" // tcp query arguments #define QUERY_FIRST "f" @@ -38,6 +44,7 @@ // tcp query packet argument list #define TCP_ARGUMENT_NAME "name" +#define TCP_ARGUMENT_DATA "data" #define TCP_ARGUMENT_ID "id" #define TCP_ARGUMENT_TYPE "type" #define TCP_ARGUMENT_BITS_PER_MAU "bpm" diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index dc40a68338..21e9159876 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -544,6 +544,46 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &reset_cmd_desc; } break; + case TCP_CHAR_READ_REGISTER: + { + static MCDCmdParseEntry read_reg_cmd_desc = { + .handler = handle_read_register, + }; + read_reg_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_READ_REGISTER, '\0' }; + strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + cmd_parser = &read_reg_cmd_desc; + } + break; + case TCP_CHAR_WRITE_REGISTER: + { + static MCDCmdParseEntry write_reg_cmd_desc = { + .handler = handle_write_register, + }; + write_reg_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_WRITE_REGISTER, '\0' }; + strcpy(write_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + cmd_parser = &write_reg_cmd_desc; + } + break; + case TCP_CHAR_READ_MEMORY: + { + static MCDCmdParseEntry read_mem_cmd_desc = { + .handler = handle_read_memory, + }; + read_mem_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_READ_MEMORY, '\0' }; + strcpy(read_mem_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + cmd_parser = &read_mem_cmd_desc; + } + break; + case TCP_CHAR_WRITE_MEMORY: + { + static MCDCmdParseEntry write_mem_cmd_desc = { + .handler = handle_write_memory, + }; + write_mem_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_WRITE_MEMORY, '\0' }; + strcpy(write_mem_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + cmd_parser = &write_mem_cmd_desc; + } + break; default: // could not perform the command (because its unknown) mcd_put_packet(""); @@ -597,6 +637,18 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) } } +uint64_t atouint64_t(const char* in) { + uint64_t res = 0; + for (int i = 0; i < strlen(in); ++i) + { + const char c = in[i]; + res *= 10; + res += c - '0'; + } + + return res; +} + int cmd_parse_params(const char *data, const char *schema, GArray *params) { char data_buffer[64] = {0}; @@ -621,6 +673,10 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) { this_param.data_int = atoi(data_buffer); g_array_append_val(params, this_param); break; + case ARG_SCHEMA_UINT32_T: + this_param.data_int = atoi(data_buffer); + g_array_append_val(params, this_param); + break; case ARG_SCHEMA_QRYHANDLE: this_param.query_handle = atoi(data_buffer); g_array_append_val(params, this_param); @@ -1716,3 +1772,76 @@ void handle_query_state(GArray *params, void *user_ctx) { TCP_ARGUMENT_STOP_STRING, state_info.stop_str, TCP_ARGUMENT_INFO_STRING, state_info.info_str); mcd_put_strbuf(); } + +int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) { + CPUClass *cc = CPU_GET_CLASS(cpu); + gchar *arch = cc->gdb_arch_name(cpu); + if (strcmp(arch, "arm")==0) { + g_free(arch); + return arm_mcd_read_register(cpu, buf, reg); + } + else { + g_free(arch); + return 0; + } +} + +void mcd_memtohex(GString *buf, const uint8_t *mem, int len) { + int i, c; + for(i = 0; i < len; i++) { + c = mem[i]; + g_string_append_c(buf, tohex(c >> 4)); + g_string_append_c(buf, tohex(c & 0xf)); + } + g_string_append_c(buf, '\0'); +} + +void handle_read_register(GArray *params, void *user_ctx) { + uint32_t cpu_id = get_param(params, 0)->cpu_id; + int reg_num = get_param(params, 1)->data_int; + int reg_size; + + CPUState *cpu = mcd_get_cpu(cpu_id); + + reg_size = mcd_read_register(cpu, mcdserver_state.mem_buf, reg_num); + mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, reg_size); + //g_string_printf(mcdserver_state.str_buf, "%s=%d;%d.%s=%d.", + // TCP_ARGUMENT_DATA, *mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->data[1], TCP_ARGUMENT_SIZE, reg_size); + mcd_put_strbuf(); +} + +void handle_write_register(GArray *params, void *user_ctx) { + +} + +int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) +{ + CPUClass *cc; + //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); + cc = CPU_GET_CLASS(cpu); + if (cc->memory_rw_debug) { + // TODO: check out the difference between those two calls + return cc->memory_rw_debug(cpu, addr, buf, len, false); + } + + return cpu_memory_rw_debug(cpu, addr, buf, len, false); +} + +void handle_read_memory(GArray *params, void *user_ctx) { + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint64_t mem_address = get_param(params, 1)->data_uint64_t; + int len = get_param(params, 2)->data_int; + + CPUState *cpu = mcd_get_cpu(cpu_id); + if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf, len)!=0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } + else { + mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, len); + mcd_put_strbuf(); + } +} + +void handle_write_memory(GArray *params, void *user_ctx) { + +} diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c new file mode 100644 index 0000000000..dc36a79a70 --- /dev/null +++ b/target/arm/mcdstub.c @@ -0,0 +1,75 @@ +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/mcdstub.h" +#include "sysemu/tcg.h" +#include "internals.h" +#include "cpregs.h" +#include "mcdstub.h" + +static inline int mcd_get_reg32(GByteArray *buf, uint32_t val) +{ + //FIXME: move this to a separate file + // convert endianess if necessary + uint32_t to_long = tswap32(val); + g_byte_array_append(buf, (uint8_t *) &to_long, 4); + return 4; +} + +static inline int mcd_get_zeroes(GByteArray *array, size_t len) +{ + //FIXME: move this to a separate file + guint oldlen = array->len; + g_byte_array_set_size(array, oldlen + len); + memset(array->data + oldlen, 0, len); + + return len; +} + +const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname) +{ + ARMCPU *cpu = ARM_CPU(cs); + + if (strcmp(xmlname, "system-registers.xml") == 0) { + return cpu->dyn_sysreg_xml.desc; + } else if (strcmp(xmlname, "sve-registers.xml") == 0) { + return cpu->dyn_svereg_xml.desc; + } else if (strcmp(xmlname, "arm-m-system.xml") == 0) { + return cpu->dyn_m_systemreg_xml.desc; +#ifndef CONFIG_USER_ONLY + } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) { + return cpu->dyn_m_secextreg_xml.desc; +#endif + } + return NULL; +} + +int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) { + //CPUClass *cc = CPU_GET_CLASS(cpu); + //CPUArchState *env = cpu->env_ptr; + + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + if (n < 16) { + /* Core integer register. */ + return mcd_get_reg32(mem_buf, env->regs[n]); + } + if (n < 24) { + // TODO: these numbers don't match mine + return mcd_get_zeroes(mem_buf, 12); + } + switch (n) { + case 24: + // TODO: these numbers don't match mine + return mcd_get_reg32(mem_buf, 0); + case 25: + /* CPSR, or XPSR for M-profile */ + if (arm_feature(env, ARM_FEATURE_M)) { + return mcd_get_reg32(mem_buf, xpsr_read(env)); + } else { + return mcd_get_reg32(mem_buf, cpsr_read(env)); + } + } + //TODO: add funcitons for regs with higher numbers (including cp_regs) + return 0; +} \ No newline at end of file diff --git a/target/arm/mcdstub.h b/target/arm/mcdstub.h new file mode 100644 index 0000000000..d61028c7f4 --- /dev/null +++ b/target/arm/mcdstub.h @@ -0,0 +1,7 @@ +#ifndef ARM_MCDSTUB_H +#define ARM_MCDSTUB_H + +const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname); +int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n); + +#endif /* ARM_MCDSTUB_H */ From patchwork Fri Oct 6 09:05:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844286 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22cx1Zsqz1yqF for ; Fri, 6 Oct 2023 20:07:29 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognO-0008AT-RY; Fri, 06 Oct 2023 05:06:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognH-00089c-Em for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:48 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognE-0000xq-2Y for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:47 -0400 Received: (qmail 19664 invoked by uid 484); 6 Oct 2023 09:06:31 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.244089 secs); 06 Oct 2023 09:06:31 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:28 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 13/29] handler for reading memory added Date: Fri, 6 Oct 2023 11:05:54 +0200 Message-Id: <20231006090610.26171-14-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/internals.h | 9 ++- mcdstub/mcd_shared_defines.h | 2 +- mcdstub/mcdstub.c | 124 +++++++++++++++++++++++------------ 3 files changed, 89 insertions(+), 46 deletions(-) diff --git a/mcdstub/internals.h b/mcdstub/internals.h index a85173d0d1..871a58f8ea 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -41,8 +41,9 @@ enum { #define ARG_SCHEMA_QRYHANDLE 'q' #define ARG_SCHEMA_STRING 's' #define ARG_SCHEMA_INT 'd' -#define ARG_SCHEMA_UINT32_T 'l' +#define ARG_SCHEMA_UINT64_T 'l' #define ARG_SCHEMA_CORENUM 'c' +#define ARG_SCHEMA_HEXDATA 'h' // resets #define RESET_SYSTEM "full_system_reset" @@ -51,7 +52,7 @@ enum { // more #define QUERY_TOTAL_NUMBER 12 //FIXME: set this to a usefull value in the end -#define CMD_SCHEMA_LENGTH 3 +#define CMD_SCHEMA_LENGTH 5 #define MCD_SYSTEM_NAME "qemu-system" // tcp query packet values templates #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" @@ -106,7 +107,6 @@ typedef enum MCDThreadIdKind { } MCDThreadIdKind; typedef union MCDCmdVariant { - const char *data; int data_int; uint64_t data_uint64_t; @@ -329,6 +329,7 @@ void handle_read_memory(GArray *params, void *user_ctx); void handle_write_memory(GArray *params, void *user_ctx); int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); +int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); // arm specific functions int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces); @@ -343,5 +344,7 @@ void mcd_disable_syscalls(void); // helpers int int_cmp(gconstpointer a, gconstpointer b); void mcd_memtohex(GString *buf, const uint8_t *mem, int len); +void mcd_hextomem(GByteArray *mem, const char *buf, int len); +uint64_t atouint64_t(const char* in); #endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 47d5d46af3..f2f4d31335 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -27,7 +27,7 @@ #define TCP_WAS_NOT_LAST '~' #define TCP_HANDSHAKE_SUCCESS "shaking your hand" #define TCP_EXECUTION_SUCCESS "success" -#define TCP_EXECUTION_ERROR "" +#define TCP_EXECUTION_ERROR "error" // tcp query arguments #define QUERY_FIRST "f" diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 21e9159876..88f321a068 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -465,7 +465,7 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry open_server_cmd_desc = { .handler = handle_open_server, }; - open_server_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_OPEN_SERVER, '\0' }; + open_server_cmd_desc.cmd = (char[2]) { TCP_CHAR_OPEN_SERVER, '\0' }; cmd_parser = &open_server_cmd_desc; } break; @@ -475,7 +475,7 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry go_cmd_desc = { .handler = handle_vm_start, }; - go_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_GO, '\0' }; + go_cmd_desc.cmd = (char[2]) { TCP_CHAR_GO, '\0' }; cmd_parser = &go_cmd_desc; } break; @@ -485,7 +485,7 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry break_cmd_desc = { .handler = handle_vm_stop, }; - break_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_BREAK, '\0' }; + break_cmd_desc.cmd = (char[2]) { TCP_CHAR_BREAK, '\0' }; cmd_parser = &break_cmd_desc; } break; @@ -500,8 +500,8 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry query_cmd_desc = { .handler = handle_gen_query, }; - query_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_QUERY, '\0' }; - strcpy(query_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_STRING, '\0' }); + query_cmd_desc.cmd = (char[2]) { TCP_CHAR_QUERY, '\0' }; + strcpy(query_cmd_desc.schema, (char[2]) { ARG_SCHEMA_STRING, '\0' }); cmd_parser = &query_cmd_desc; } break; @@ -510,8 +510,8 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry open_core_cmd_desc = { .handler = handle_open_core, }; - open_core_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_OPEN_CORE, '\0' }; - strcpy(open_core_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + open_core_cmd_desc.cmd = (char[2]) { TCP_CHAR_OPEN_CORE, '\0' }; + strcpy(open_core_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &open_core_cmd_desc; } break; @@ -520,7 +520,7 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry close_server_cmd_desc = { .handler = handle_close_server, }; - close_server_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_CLOSE_SERVER, '\0' }; + close_server_cmd_desc.cmd = (char[2]) { TCP_CHAR_CLOSE_SERVER, '\0' }; cmd_parser = &close_server_cmd_desc; } break; @@ -529,8 +529,8 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry close_core_cmd_desc = { .handler = handle_close_core, }; - close_core_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_CLOSE_CORE, '\0' }; - strcpy(close_core_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + close_core_cmd_desc.cmd = (char[2]) { TCP_CHAR_CLOSE_CORE, '\0' }; + strcpy(close_core_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &close_core_cmd_desc; } break; @@ -539,8 +539,8 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry reset_cmd_desc = { .handler = handle_reset, }; - reset_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_RESET, '\0' }; - strcpy(reset_cmd_desc.schema, (char[2]) { (char) ARG_SCHEMA_INT, '\0' }); + reset_cmd_desc.cmd = (char[2]) { TCP_CHAR_RESET, '\0' }; + strcpy(reset_cmd_desc.schema, (char[2]) { ARG_SCHEMA_INT, '\0' }); cmd_parser = &reset_cmd_desc; } break; @@ -549,7 +549,7 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry read_reg_cmd_desc = { .handler = handle_read_register, }; - read_reg_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_READ_REGISTER, '\0' }; + read_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_READ_REGISTER, '\0' }; strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); cmd_parser = &read_reg_cmd_desc; } @@ -559,7 +559,7 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry write_reg_cmd_desc = { .handler = handle_write_register, }; - write_reg_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_WRITE_REGISTER, '\0' }; + write_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_WRITE_REGISTER, '\0' }; strcpy(write_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); cmd_parser = &write_reg_cmd_desc; } @@ -569,8 +569,8 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry read_mem_cmd_desc = { .handler = handle_read_memory, }; - read_mem_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_READ_MEMORY, '\0' }; - strcpy(read_mem_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + read_mem_cmd_desc.cmd = (char[2]) { TCP_CHAR_READ_MEMORY, '\0' }; + strcpy(read_mem_cmd_desc.schema, (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, '\0' }); cmd_parser = &read_mem_cmd_desc; } break; @@ -579,8 +579,8 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry write_mem_cmd_desc = { .handler = handle_write_memory, }; - write_mem_cmd_desc.cmd = (char[2]) { (char) TCP_CHAR_WRITE_MEMORY, '\0' }; - strcpy(write_mem_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + write_mem_cmd_desc.cmd = (char[2]) { TCP_CHAR_WRITE_MEMORY, '\0' }; + strcpy(write_mem_cmd_desc.schema, (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); cmd_parser = &write_mem_cmd_desc; } break; @@ -652,29 +652,43 @@ uint64_t atouint64_t(const char* in) { int cmd_parse_params(const char *data, const char *schema, GArray *params) { char data_buffer[64] = {0}; - char *separator = strchr(data, ARGUMENT_SEPARATOR); - int seperator_index = (int)(separator - data); - - if (separator) { - // we got two arguments - strncpy(data_buffer, data, seperator_index); - } - else { - strncpy(data_buffer, data, strlen(data)); - } + const char *remaining_data = data; + for (int i = 0; icpu_id; int reg_num = get_param(params, 1)->data_int; @@ -1805,8 +1824,6 @@ void handle_read_register(GArray *params, void *user_ctx) { reg_size = mcd_read_register(cpu, mcdserver_state.mem_buf, reg_num); mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, reg_size); - //g_string_printf(mcdserver_state.str_buf, "%s=%d;%d.%s=%d.", - // TCP_ARGUMENT_DATA, *mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->data[1], TCP_ARGUMENT_SIZE, reg_size); mcd_put_strbuf(); } @@ -1814,8 +1831,7 @@ void handle_write_register(GArray *params, void *user_ctx) { } -int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) -{ +int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { CPUClass *cc; //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); cc = CPU_GET_CLASS(cpu); @@ -1827,21 +1843,45 @@ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) return cpu_memory_rw_debug(cpu, addr, buf, len, false); } +int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { + CPUClass *cc; + //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); + cc = CPU_GET_CLASS(cpu); + if (cc->memory_rw_debug) { + // TODO: check out the difference between those two calls + return cc->memory_rw_debug(cpu, addr, buf, len, true); + } + + return cpu_memory_rw_debug(cpu, addr, buf, len, true); +} + void handle_read_memory(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; uint64_t mem_address = get_param(params, 1)->data_uint64_t; int len = get_param(params, 2)->data_int; CPUState *cpu = mcd_get_cpu(cpu_id); - if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf, len)!=0) { + g_byte_array_set_size(mcdserver_state.mem_buf, len); + if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len)!=0) { mcd_put_packet(TCP_EXECUTION_ERROR); } else { - mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, len); + mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len); mcd_put_strbuf(); } } void handle_write_memory(GArray *params, void *user_ctx) { + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint64_t mem_address = get_param(params, 1)->data_uint64_t; + int len = get_param(params, 2)->data_int; + CPUState *cpu = mcd_get_cpu(cpu_id); + mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, len); + if (mcd_write_memory(cpu, mem_address, mcdserver_state.mem_buf->data, len)!=0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } + else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } } From patchwork Fri Oct 6 09:05:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844285 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22cf097Vz1yqF for ; Fri, 6 Oct 2023 20:07:13 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognP-0008Db-6e; Fri, 06 Oct 2023 05:06:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognK-00089p-DB for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:50 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognF-0000yK-U2 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:50 -0400 Received: (qmail 19699 invoked by uid 484); 6 Oct 2023 09:06:33 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.162807 secs); 06 Oct 2023 09:06:33 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:31 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 14/29] handler for single step added Date: Fri, 6 Oct 2023 11:05:55 +0200 Message-Id: <20231006090610.26171-15-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- include/exec/mcdstub.h | 6 +- include/mcdstub/syscalls.h | 4 +- mcdstub/internals.h | 77 +++---- mcdstub/mcd_shared_defines.h | 3 +- mcdstub/mcdstub.c | 428 ++++++++++++++--------------------- softmmu/cpus.c | 2 +- target/arm/mcdstub.c | 66 +++++- target/arm/mcdstub.h | 1 + 8 files changed, 269 insertions(+), 318 deletions(-) diff --git a/include/exec/mcdstub.h b/include/exec/mcdstub.h index abf7beb634..132f32417c 100644 --- a/include/exec/mcdstub.h +++ b/include/exec/mcdstub.h @@ -3,10 +3,8 @@ #define DEFAULT_MCDSTUB_PORT "1235" #define TYPE_CHARDEV_MCD "chardev-mcd" -#define MX_INPUT_LENGTH 9 -#define MCD_TCP_DATALEN 80 -/* MCD breakpoint/watchpoint types */ +// breakpoint defines #define MCD_BREAKPOINT_SW 0 #define MCD_BREAKPOINT_HW 1 #define MCD_WATCHPOINT_WRITE 2 @@ -16,8 +14,6 @@ /** * mcd_tcp_server_start: start the tcp server to connect via mcd * @device: connection spec for mcd - * - * This is a TCP port */ int mcdserver_start(const char *device); diff --git a/include/mcdstub/syscalls.h b/include/mcdstub/syscalls.h index 1f86634140..92ae7f4e77 100644 --- a/include/mcdstub/syscalls.h +++ b/include/mcdstub/syscalls.h @@ -1,5 +1,5 @@ -#ifndef _SYSCALLS_H_ -#define _SYSCALLS_H_ +#ifndef _MCD_SYSCALLS_H_ +#define _MCD_SYSCALLS_H_ typedef void (*gdb_syscall_complete_cb)(CPUState *cpu, uint64_t ret, int err); diff --git a/mcdstub/internals.h b/mcdstub/internals.h index 871a58f8ea..0afab434ce 100644 --- a/mcdstub/internals.h +++ b/mcdstub/internals.h @@ -1,8 +1,3 @@ -/* - * this header includes a lookup table for the transmitted messages over the tcp connection to trace32, - * as well as function declarations for all functios used inside the mcdstub - */ - #ifndef MCDSTUB_INTERNALS_H #define MCDSTUB_INTERNALS_H @@ -10,19 +5,33 @@ #include "chardev/char.h" #include "hw/core/cpu.h" // just used for the register xml files -#include "exec/gdbstub.h" /* xml_builtin */ +#include "exec/gdbstub.h" #define MAX_PACKET_LENGTH 1024 // trigger defines -#define MCD_TRIG_TYPE_IP 0x00000001 -#define MCD_TRIG_TYPE_READ 0x00000002 -#define MCD_TRIG_TYPE_WRITE 0x00000004 -#define MCD_TRIG_TYPE_RW 0x00000008 #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 +typedef uint32_t mcd_trig_type_et; +// TODO: replace mcd defines with custom layer +enum { + MCD_TRIG_TYPE_UNDEFINED = 0x00000000, /**< Undefined trigger type. */ + MCD_TRIG_TYPE_IP = 0x00000001, /**< Trigger on a changing instruction pointer. */ + MCD_TRIG_TYPE_READ = 0x00000002, /**< Trigger on a read data access to a specific address or address range. */ + MCD_TRIG_TYPE_WRITE = 0x00000004, /**< Trigger on a write data access to a specific address or address range. */ + MCD_TRIG_TYPE_RW = 0x00000008, /**< Trigger on a read or a write data access to a specific address or + address range. */ + MCD_TRIG_TYPE_NOCYCLE = 0x00000010, /**< Trigger on core information other than an IP or data compare trigger. */ + MCD_TRIG_TYPE_TRIG_BUS = 0x00000020, /**< Trigger on a trigger bus combination. */ + MCD_TRIG_TYPE_COUNTER = 0x00000040, /**< Trigger on an elapsed trigger counter. */ + MCD_TRIG_TYPE_CUSTOM = 0x00000080, /**< Custom trigger using standard format as defined by \ref mcd_trig_custom_st. */ + MCD_TRIG_TYPE_CUSTOM_LO = 0x00010000, /**< Begin Range: User defined trigger types. */ + MCD_TRIG_TYPE_CUSTOM_HI = 0x40000000, /**< End Range: User defined trigger types. */ +}; + typedef uint32_t mcd_core_event_et; +// TODO: replace mcd defines with custom layer enum { MCD_CORE_EVENT_NONE = 0x00000000, /**< No since the last poll. */ MCD_CORE_EVENT_MEMORY_CHANGE = 0x00000001, /**< Memory content has changed. */ @@ -50,10 +59,11 @@ enum { #define RESET_GPR "gpr_reset" #define RESET_MEMORY "memory_reset" -// more -#define QUERY_TOTAL_NUMBER 12 //FIXME: set this to a usefull value in the end +// misc +#define QUERY_TOTAL_NUMBER 12 #define CMD_SCHEMA_LENGTH 5 #define MCD_SYSTEM_NAME "qemu-system" + // tcp query packet values templates #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" @@ -65,13 +75,14 @@ enum { #define STATE_STR_INIT_HALTED "vm halted since boot" #define STATE_STR_INIT_RUNNING "vm running since boot" #define STATE_STR_BREAK_HW "stopped beacuse of HW breakpoint" +#define STATE_STEP_PERFORMED "stopped beacuse of single step" #define STATE_STR_BREAK_READ(d) "stopped beacuse of read access at " #d #define STATE_STR_BREAK_WRITE(d) "stopped beacuse of write access at " #d #define STATE_STR_BREAK_RW(d) "stopped beacuse of read or write access at " #d #define STATE_STR_BREAK_UNKNOWN "stopped for unknown reason" -// GDB stuff thats needed for GDB function, which we use typedef struct GDBRegisterState { + // needed for the used gdb functions int base_reg; int num_regs; gdb_get_reg_cb get_reg; @@ -80,12 +91,7 @@ typedef struct GDBRegisterState { struct GDBRegisterState *next; } GDBRegisterState; -/* - * struct for an MCD Process, each process can establish one connection - */ - typedef struct MCDProcess { - //this is a relict from the gdb process, we might be able to delete this uint32_t pid; bool attached; @@ -99,35 +105,16 @@ typedef struct MCDCmdParseEntry { char schema[CMD_SCHEMA_LENGTH]; } MCDCmdParseEntry; -typedef enum MCDThreadIdKind { - GDB_ONE_THREAD = 0, - GDB_ALL_THREADS, /* One process, all threads */ - GDB_ALL_PROCESSES, - GDB_READ_THREAD_ERR -} MCDThreadIdKind; - typedef union MCDCmdVariant { const char *data; int data_int; uint64_t data_uint64_t; int query_handle; int cpu_id; - struct { - MCDThreadIdKind kind; - uint32_t pid; - uint32_t tid; - } thread_id; - } MCDCmdVariant; #define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) - -/* - * not sure for what this is used exactly - */ - - enum RSState { RS_INACTIVE, RS_IDLE, @@ -162,19 +149,14 @@ typedef struct MCDState { int line_csum; /* checksum at the end of the packet */ GByteArray *last_packet; int signal; - //the next one is about stub compatibility and we should be able to assume this is true anyway - //bool multiprocess; + MCDProcess *processes; int process_num; GString *str_buf; GByteArray *mem_buf; - // maybe we don't need those flags int sstep_flags; int supported_sstep_flags; - // my stuff - RunState vm_current_state; - RunState vm_previous_state; uint32_t query_cpu_id; GList *all_memspaces; GList *all_reggroups; @@ -236,9 +218,6 @@ typedef struct mcd_reset_st { uint8_t id; } mcd_reset_st; -// Inline utility function, convert from int to hex and back - - static inline int fromhex(int v) { if (v >= '0' && v <= '9') { @@ -283,7 +262,6 @@ int mcd_put_packet(const char *buf); int mcd_put_packet_binary(const char *buf, int len, bool dump); bool mcd_got_immediate_ack(void); void mcd_put_buffer(const uint8_t *buf, int len); -void mcd_set_stop_cpu(CPUState *cpu); MCDProcess *mcd_get_cpu_process(CPUState *cpu); uint32_t mcd_get_cpu_pid(CPUState *cpu); MCDProcess *mcd_get_process(uint32_t pid); @@ -297,6 +275,7 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd); int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds); int cmd_parse_params(const char *data, const char *schema, GArray *params); void handle_vm_start(GArray *params, void *user_ctx); +void handle_vm_step(GArray *params, void *user_ctx); void handle_vm_stop(GArray *params, void *user_ctx); void handle_gen_query(GArray *params, void *user_ctx); int mcd_get_cpu_index(CPUState *cpu); @@ -312,6 +291,7 @@ void handle_close_server(GArray *params, void *user_ctx); void handle_close_core(GArray *params, void *user_ctx); void handle_query_trigger(GArray *params, void *user_ctx); void mcd_vm_start(void); +int mcd_vm_sstep(CPUState *cpu); void mcd_vm_stop(void); void handle_query_reg_groups_f(GArray *params, void *user_ctx); void handle_query_reg_groups_c(GArray *params, void *user_ctx); @@ -328,6 +308,7 @@ void handle_write_register(GArray *params, void *user_ctx); void handle_read_memory(GArray *params, void *user_ctx); void handle_write_memory(GArray *params, void *user_ctx); int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); +int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg); int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); @@ -337,7 +318,7 @@ int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray* reggroups, GArray* registe int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray* registers, int* current_group_id); int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers); -/* sycall handling */ +// sycall handling void mcd_syscall_reset(void); void mcd_disable_syscalls(void); diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index f2f4d31335..311d24e12f 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -6,7 +6,8 @@ // tcp data characters #define TCP_CHAR_OPEN_SERVER 'I' #define TCP_CHAR_OPEN_CORE 'i' -#define TCP_CHAR_GO 'c' +#define TCP_CHAR_GO 'C' +#define TCP_CHAR_STEP 'c' #define TCP_CHAR_BREAK 'b' #define TCP_CHAR_QUERY 'q' #define TCP_CHAR_CLOSE_SERVER 'D' diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 88f321a068..d65b0a54d2 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -1,10 +1,9 @@ /* - * This is the main mcdstub. It needs to be complemented by other mcd stubs for each target. + * This is the main mcdstub. */ #include "mcd_shared_defines.h" -//from original gdbstub.c #include "qemu/osdep.h" #include "qemu/ctype.h" #include "qemu/cutils.h" @@ -14,15 +13,12 @@ #include "mcdstub/syscalls.h" #include "hw/cpu/cluster.h" #include "hw/boards.h" - #include "sysemu/hw_accel.h" #include "sysemu/runstate.h" #include "exec/replay-core.h" #include "exec/hwaddr.h" - #include "internals.h" -//from original softmmu.c (minus what was already here) #include "qapi/error.h" #include "exec/tb-flush.h" #include "sysemu/cpus.h" @@ -31,7 +27,7 @@ #include "chardev/char-fe.h" #include "monitor/monitor.h" -//architecture specific stuff +// architecture specific stubs #include "target/arm/mcdstub.h" // FIXME: delete the following line and check if it worked @@ -39,7 +35,6 @@ typedef struct { CharBackend chr; - //Chardev *mon_chr; } MCDSystemState; MCDSystemState mcdserver_system_state; @@ -60,8 +55,6 @@ void mcd_init_mcdserver_state(void) * By default try to use no IRQs and no timers while single * stepping so as to make single stepping like a typical ICE HW step. */ - // TODO: - // this is weird and we might not actually need it after all mcdserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; mcdserver_state.sstep_flags &= mcdserver_state.supported_sstep_flags; @@ -106,7 +99,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_reset_c, .cmd = QUERY_ARG_RESET QUERY_CONSEQUTIVE, }; - strcpy(query_reset_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + strcpy(query_reset_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); mcd_query_cmds_table[cmd_number] = query_reset_c; cmd_number++; @@ -121,7 +114,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_mem_spaces_f, .cmd = QUERY_ARG_MEMORY QUERY_FIRST, }; - strcpy(query_mem_spaces_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + strcpy(query_mem_spaces_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); mcd_query_cmds_table[cmd_number] = query_mem_spaces_f; cmd_number++; @@ -129,7 +122,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_mem_spaces_c, .cmd = QUERY_ARG_MEMORY QUERY_CONSEQUTIVE, }; - strcpy(query_mem_spaces_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + strcpy(query_mem_spaces_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); mcd_query_cmds_table[cmd_number] = query_mem_spaces_c; cmd_number++; @@ -137,7 +130,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_reg_groups_f, .cmd = QUERY_ARG_REGGROUP QUERY_FIRST, }; - strcpy(query_reg_groups_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + strcpy(query_reg_groups_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); mcd_query_cmds_table[cmd_number] = query_reg_groups_f; cmd_number++; @@ -145,7 +138,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_reg_groups_c, .cmd = QUERY_ARG_REGGROUP QUERY_CONSEQUTIVE, }; - strcpy(query_reg_groups_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + strcpy(query_reg_groups_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); mcd_query_cmds_table[cmd_number] = query_reg_groups_c; cmd_number++; @@ -153,7 +146,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_regs_f, .cmd = QUERY_ARG_REG QUERY_FIRST, }; - strcpy(query_regs_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + strcpy(query_regs_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); mcd_query_cmds_table[cmd_number] = query_regs_f; cmd_number++; @@ -161,7 +154,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_regs_c, .cmd = QUERY_ARG_REG QUERY_CONSEQUTIVE, }; - strcpy(query_regs_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHANDLE, '\0' }); + strcpy(query_regs_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\0' }); mcd_query_cmds_table[cmd_number] = query_regs_c; cmd_number++; @@ -169,7 +162,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { .handler = handle_query_state, .cmd = QUERY_ARG_STATE, }; - strcpy(query_state.schema, (char[2]) { (char) ARG_SCHEMA_CORENUM, '\0' }); + strcpy(query_state.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); mcd_query_cmds_table[cmd_number] = query_state; } @@ -258,12 +251,8 @@ int pid_order(const void *a, const void *b) int mcdserver_start(const char *device) { - //might wann add tracing later (no idea for what this is used) - //trace_gdbstub_op_start(device); - char mcdstub_device_name[128]; Chardev *chr = NULL; - //Chardev *mon_chr; if (!first_cpu) { error_report("mcdstub: meaningless to attach to a " @@ -271,7 +260,6 @@ int mcdserver_start(const char *device) return -1; } - // if (!mcd_supports_guest_debug()) { error_report("mcdstub: current accelerator doesn't " "support guest debugging"); @@ -282,7 +270,7 @@ int mcdserver_start(const char *device) return -1; } - //if device == default -> set device = tcp::1235 + // if device == default -> set device = tcp::1235 if (strcmp(device, "default") == 0) { device = "tcp::1235"; } @@ -303,7 +291,6 @@ int mcdserver_start(const char *device) sigaction(SIGINT, &act, NULL); } #endif - chr = qemu_chr_new_noreplay("mcd", device, true, NULL); if (!chr) { return -1; @@ -314,13 +301,8 @@ int mcdserver_start(const char *device) mcd_init_mcdserver_state(); qemu_add_vm_change_state_handler(mcd_vm_state_change, NULL); - - /* Initialize a monitor terminal for mcd */ - //mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_MCD, NULL, NULL, &error_abort); - //monitor_init_hmp(mon_chr, false, &error_abort); } else { qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); - //mon_chr = mcdserver_system_state.mon_chr; reset_mcdserver_state(); } @@ -334,7 +316,6 @@ int mcdserver_start(const char *device) NULL, &mcdserver_state, NULL, true); } mcdserver_state.state = chr ? RS_IDLE : RS_INACTIVE; - //mcdserver_system_state.mon_chr = mon_chr; mcd_syscall_reset(); return 0; @@ -360,107 +341,80 @@ void mcd_read_byte(uint8_t ch) uint8_t reply; if (mcdserver_state.last_packet->len) { - /* Waiting for a response to the last packet. If we see the start - of a new command then abandon the previous response. */ if (ch == TCP_NOT_ACKNOWLEDGED) { - //the previous packet was not akcnowledged - //trace_gdbstub_err_got_nack(); - //we are resending the last packet + // the previous packet was not akcnowledged mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); } else if (ch == TCP_ACKNOWLEDGED) { - //the previous packet was acknowledged - //trace_gdbstub_io_got_ack(); + // the previous packet was acknowledged } if (ch == TCP_ACKNOWLEDGED || ch == TCP_COMMAND_START) { - //either acknowledged or a new communication starts -> we discard previous communication + // either acknowledged or a new communication starts -> discard previous packet g_byte_array_set_size(mcdserver_state.last_packet, 0); } if (ch != TCP_COMMAND_START) { - // we only continue if we are processing a new commant. otherwise we skip to ne next character in the packet which sould be a $ + // skip to the next char return; } } - //if (runstate_is_running()) { - /* when the CPU is running, we cannot do anything except stop - it when receiving a char */ - //vm_stop(RUN_STATE_PAUSED); - //} - //else { - switch(mcdserver_state.state) { - case RS_IDLE: - if (ch == TCP_COMMAND_START) { - /* start of command packet */ - mcdserver_state.line_buf_index = 0; - mcdserver_state.line_sum = 0; - mcdserver_state.state = RS_GETLINE; - } - else { - //new communication has to start with a $ - //trace_gdbstub_err_garbage(ch); - } - break; - case RS_GETLINE: - if (ch == TCP_COMMAND_END) { - /* end of command, start of checksum*/ - mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0; - //mcdserver_state.line_sum += ch; - mcdserver_state.state = RS_DATAEND; - } - else if (mcdserver_state.line_buf_index >= sizeof(mcdserver_state.line_buf) - 1) { - //the input string is too long for the linebuffer! - //trace_gdbstub_err_overrun(); - mcdserver_state.state = RS_IDLE; - } - else { - /* unescaped command character */ - //this means the character is part of the real content fo the packet and we copy it to the line_buf - mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = ch; - mcdserver_state.line_sum += ch; - } - break; - case RS_DATAEND: - // we are now done with copying the data and in the suffix of the packet - // TODO: maybe wanna implement a checksum or sth like the gdb protocol has - - if (ch == TCP_WAS_NOT_LAST) { - // ~ indicates that there is an additional package coming - //acknowledged -> send + - reply = TCP_ACKNOWLEDGED; - mcd_put_buffer(&reply, 1); - mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); - } - else if (ch == TCP_WAS_LAST) { - //acknowledged -> send + - // | indicates that there is no additional package coming - reply = TCP_ACKNOWLEDGED; - mcd_put_buffer(&reply, 1); - mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); - } - else { - //trace_gdbstub_err_checksum_incorrect(mcdserver_state.line_sum, mcdserver_state.line_csum); - //not acknowledged -> send - - reply = TCP_NOT_ACKNOWLEDGED; - mcd_put_buffer(&reply, 1); - //waiting for package to get resent - mcdserver_state.state = RS_IDLE; - } - break; - default: - abort(); + + switch(mcdserver_state.state) { + case RS_IDLE: + if (ch == TCP_COMMAND_START) { + // start of command packet + mcdserver_state.line_buf_index = 0; + mcdserver_state.line_sum = 0; + mcdserver_state.state = RS_GETLINE; + } + break; + case RS_GETLINE: + if (ch == TCP_COMMAND_END) { + // end of command + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0; + mcdserver_state.state = RS_DATAEND; + } + else if (mcdserver_state.line_buf_index >= sizeof(mcdserver_state.line_buf) - 1) { + // the input string is too long for the linebuffer! + mcdserver_state.state = RS_IDLE; + } + else { + // copy the content to the line_buf + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = ch; + mcdserver_state.line_sum += ch; + } + break; + case RS_DATAEND: + if (ch == TCP_WAS_NOT_LAST) { + reply = TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); + } + else if (ch == TCP_WAS_LAST) { + reply = TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); } - //} + else { + // not acknowledged! + reply = TCP_NOT_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + // waiting for package to get resent + mcdserver_state.state = RS_IDLE; + } + break; + default: + abort(); + } } int mcd_handle_packet(const char *line_buf) { - // decides what function (handler) to call depending on what the first character in the line_buf is! + // decides what function (handler) to call depending on the first character in the line_buf const MCDCmdParseEntry *cmd_parser = NULL; switch (line_buf[0]) { case TCP_CHAR_OPEN_SERVER: - // handshake and lookup initialization { static MCDCmdParseEntry open_server_cmd_desc = { .handler = handle_open_server, @@ -470,7 +424,6 @@ int mcd_handle_packet(const char *line_buf) } break; case TCP_CHAR_GO: - // go command { static MCDCmdParseEntry go_cmd_desc = { .handler = handle_vm_start, @@ -479,8 +432,17 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &go_cmd_desc; } break; + case TCP_CHAR_STEP: + { + static MCDCmdParseEntry step_cmd_desc = { + .handler = handle_vm_step, + }; + step_cmd_desc.cmd = (char[2]) { TCP_CHAR_STEP, '\0' }; + strcpy(step_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + cmd_parser = &step_cmd_desc; + } + break; case TCP_CHAR_BREAK: - // go command { static MCDCmdParseEntry break_cmd_desc = { .handler = handle_vm_stop, @@ -495,7 +457,6 @@ int mcd_handle_packet(const char *line_buf) mcd_exit(0); exit(0); case TCP_CHAR_QUERY: - //query inquiry { static MCDCmdParseEntry query_cmd_desc = { .handler = handle_gen_query, @@ -550,7 +511,7 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_read_register, }; read_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_READ_REGISTER, '\0' }; - strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, '\0' }); cmd_parser = &read_reg_cmd_desc; } break; @@ -560,7 +521,7 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_write_register, }; write_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_WRITE_REGISTER, '\0' }; - strcpy(write_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, '\0' }); + strcpy(write_reg_cmd_desc.schema, (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); cmd_parser = &write_reg_cmd_desc; } break; @@ -585,13 +546,13 @@ int mcd_handle_packet(const char *line_buf) } break; default: - // could not perform the command (because its unknown) + // command not supported mcd_put_packet(""); break; } if (cmd_parser) { - // now parse commands and run the selected function (handler) + // parse commands and run the selected handler function run_cmd_parser(line_buf, cmd_parser); } @@ -599,21 +560,29 @@ int mcd_handle_packet(const char *line_buf) } void handle_vm_start(GArray *params, void *user_ctx) { - // todo add partial restart with arguments and so on + // TODO: add partial restart with arguments and so on mcd_vm_start(); } +void handle_vm_step(GArray *params, void *user_ctx) { + // TODO: add partial restart with arguments and so on + uint32_t cpu_id = get_param(params, 0)->cpu_id; + + CPUState *cpu = mcd_get_cpu(cpu_id); + mcd_vm_sstep(cpu); +} + + void handle_vm_stop(GArray *params, void *user_ctx) { - // todo add partial stop with arguments and so on + // TODO: add partial stop with arguments and so on mcd_vm_stop(); } -void handle_gen_query(GArray *params, void *user_ctx) -{ +void handle_gen_query(GArray *params, void *user_ctx) { if (!params->len) { return; } - //now iterate over all possible query functions and execute the right one + // iterate over all possible query functions and execute the right one if (process_string_cmd(NULL, get_param(params, 0)->data, mcdserver_state.mcd_query_cmds_table, ARRAY_SIZE(mcdserver_state.mcd_query_cmds_table))) { @@ -621,8 +590,7 @@ void handle_gen_query(GArray *params, void *user_ctx) } } -void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) -{ +void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) { if (!data) { return; } @@ -630,8 +598,6 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) g_string_set_size(mcdserver_state.str_buf, 0); g_byte_array_set_size(mcdserver_state.mem_buf, 0); - /* In case there was an error during the command parsing we must - * send a NULL packet to indicate the command is not supported */ if (process_string_cmd(NULL, data, cmd, 1)) { mcd_put_packet(""); } @@ -655,11 +621,11 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) { const char *remaining_data = data; for (int i = 0; ihandler && cmd->cmd); - // if data and command are different continue + // continue if data and command are different if (strncmp(data, cmd->cmd, strlen(cmd->cmd))) { continue; } - // if a schema is provided we need to extract parameters from the data string if (strlen(cmd->schema)) { - // this only gets the data from data beginning after the command name + // extract data for parameters if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, params)) { return -1; } } - // the correct handler function is called + // call handler cmd->handler(params, user_ctx); return 0; } @@ -741,25 +703,16 @@ int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry return -1; } -void mcd_exit(int code) -{ - char buf[4]; - +void mcd_exit(int code) { + // terminate qemu if (!mcdserver_state.init) { return; } - //trace_gdbstub_op_exiting((uint8_t)code); - - //need to check what is sent here and dapt it to my needs - snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code); - mcd_put_packet(buf); - qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); } -void mcd_chr_event(void *opaque, QEMUChrEvent event) -{ +void mcd_chr_event(void *opaque, QEMUChrEvent event) { int i; MCDState *s = (MCDState *) opaque; @@ -771,19 +724,13 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event) } s->c_cpu = mcd_first_attached_cpu(); - - //vm_stop(RUN_STATE_PAUSED); - //TODO: this might not be necessary - //replay_gdb_attached(); - //gdb_has_xml = false; break; default: break; } } -bool mcd_supports_guest_debug(void) -{ +bool mcd_supports_guest_debug(void) { const AccelOpsClass *ops = cpus_get_accel(); if (ops->supports_guest_debug) { return ops->supports_guest_debug(); @@ -792,29 +739,23 @@ bool mcd_supports_guest_debug(void) } #ifndef _WIN32 -void mcd_sigterm_handler(int signal) -{ +void mcd_sigterm_handler(int signal) { if (runstate_is_running()) { vm_stop(RUN_STATE_PAUSED); } } #endif -void mcd_vm_state_change(void *opaque, bool running, RunState state) -{ +void mcd_vm_state_change(void *opaque, bool running, RunState state) { CPUState *cpu = mcdserver_state.c_cpu; - // update cpu state - mcdserver_state.vm_previous_state = mcdserver_state.vm_current_state; - mcdserver_state.vm_current_state = state; - if (mcdserver_state.state == RS_INACTIVE) { return; } if (cpu == NULL) { if (running) { - // this is the case if qemu starts the vm before any mcd is connected + // this is the case if qemu starts the vm before a mcd client is connected const char *mcd_state; mcd_state = CORE_STATE_RUNNING; const char *info_str; @@ -857,8 +798,13 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) stop_str = STATE_STR_BREAK_UNKNOWN; } cpu->watchpoint_hit = NULL; - } else { - // "hardware" breakpoint hit! + } + else if (cpu->singlestep_enabled){ + // we land here when a single step is performed + cpu_single_step(cpu, 0); + stop_str = STATE_STEP_PERFORMED; + } + else { trig_id = MCD_TRIG_TYPE_IP; stop_str = STATE_STR_BREAK_HW; tb_flush(cpu); @@ -870,47 +816,40 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) stop_str = ""; break; case RUN_STATE_WATCHDOG: + printf("runstate watchdog hit\n"); info_str = STATE_STR_UNKNOWN(cpu->cpu_index); mcd_state = CORE_STATE_UNKNOWN; stop_str = ""; - printf("runstate watchdog hit\n"); break; default: info_str = STATE_STR_UNKNOWN(cpu->cpu_index); mcd_state = CORE_STATE_UNKNOWN; stop_str = ""; - // we don't care; break; } + // set state for c_cpu mcdserver_state.cpu_state.state = mcd_state; mcdserver_state.cpu_state.trig_id = trig_id; mcdserver_state.cpu_state.stop_str = stop_str; mcdserver_state.cpu_state.info_str = info_str; - - /* disable single step if it was enabled */ - cpu_single_step(cpu, 0); } -int mcd_put_packet(const char *buf) -{ +int mcd_put_packet(const char *buf) { return mcd_put_packet_binary(buf, strlen(buf), false); } -void mcd_put_strbuf(void) -{ +void mcd_put_strbuf(void) { mcd_put_packet(mcdserver_state.str_buf->str); } -int mcd_put_packet_binary(const char *buf, int len, bool dump) -{ +int mcd_put_packet_binary(const char *buf, int len, bool dump) { for(;;) { - //super interesting if we want a chekcsum or something like that here!! g_byte_array_set_size(mcdserver_state.last_packet, 0); - g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "$", 1); + g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_COMMAND_START, '\0' }, 1); g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) buf, len); - g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "#", 1); - g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) "|", 1); + g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_COMMAND_END, '\0' }, 1); + g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_WAS_LAST, '\0' }, 1); mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); @@ -921,53 +860,28 @@ int mcd_put_packet_binary(const char *buf, int len, bool dump) return 0; } -bool mcd_got_immediate_ack(void) -{ +bool mcd_got_immediate_ack(void) { return true; } -void mcd_put_buffer(const uint8_t *buf, int len) -{ - /* - * XXX this blocks entire thread. Rewrite to use - * qemu_chr_fe_write and background I/O callbacks - */ +void mcd_put_buffer(const uint8_t *buf, int len) { qemu_chr_fe_write_all(&mcdserver_system_state.chr, buf, len); } -void mcd_set_stop_cpu(CPUState *cpu) -{ - MCDProcess *p = mcd_get_cpu_process(cpu); - - if (!p->attached) { - /* - * Having a stop CPU corresponding to a process that is not attached - * confuses GDB. So we ignore the request. - */ - return; - } - //FIXME: we probably can delete this because in the opern_core function we set these two anyway - mcdserver_state.c_cpu = cpu; -} - -MCDProcess *mcd_get_cpu_process(CPUState *cpu) -{ +MCDProcess *mcd_get_cpu_process(CPUState *cpu) { return mcd_get_process(mcd_get_cpu_pid(cpu)); } -uint32_t mcd_get_cpu_pid(CPUState *cpu) -{ +uint32_t mcd_get_cpu_pid(CPUState *cpu) { if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) { - /* Return the default process' PID */ + // Return the default process' PID int index = mcdserver_state.process_num - 1; return mcdserver_state.processes[index].pid; } - // TODO: maybe +1 because we start numbering at 1 return cpu->cluster_index + 1; } -MCDProcess *mcd_get_process(uint32_t pid) -{ +MCDProcess *mcd_get_process(uint32_t pid) { int i; if (!pid) { @@ -997,8 +911,7 @@ CPUState* mcd_get_cpu(uint32_t i_cpu_index) { return cpu; } -CPUState *mcd_first_attached_cpu(void) -{ +CPUState *mcd_first_attached_cpu(void) { CPUState *cpu = first_cpu; MCDProcess *process = mcd_get_cpu_process(cpu); @@ -1009,8 +922,7 @@ CPUState *mcd_first_attached_cpu(void) return cpu; } -CPUState *mcd_next_attached_cpu(CPUState *cpu) -{ +CPUState *mcd_next_attached_cpu(CPUState *cpu) { cpu = CPU_NEXT(cpu); while (cpu) { @@ -1024,14 +936,11 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu) return cpu; } -int mcd_get_cpu_index(CPUState *cpu) -{ - // TODO: maybe plus 1 because we start numbering at 1 +int mcd_get_cpu_index(CPUState *cpu) { return cpu->cpu_index + 1; } -CPUState *get_first_cpu_in_process(MCDProcess *process) -{ +CPUState *get_first_cpu_in_process(MCDProcess *process) { CPUState *cpu; CPU_FOREACH(cpu) { @@ -1043,8 +952,7 @@ CPUState *get_first_cpu_in_process(MCDProcess *process) return NULL; } -CPUState *find_cpu(uint32_t thread_id) -{ +CPUState *find_cpu(uint32_t thread_id) { CPUState *cpu; CPU_FOREACH(cpu) { @@ -1080,7 +988,7 @@ void parse_reg_xml(const char *xml, int size, GArray* registers) { c_ptr = &c; if (still_to_skip>0) { - // skip chars unwanted chars + // skip unwanted chars still_to_skip --; continue; } @@ -1172,9 +1080,7 @@ void parse_reg_xml(const char *xml, int size, GArray* registers) { } int int_cmp(gconstpointer a, gconstpointer b) { - int a_int = *(int*)a; - int b_int = *(int*)b; - if (a_int == b_int) { + if (*(int*)a == *(int*)b) { return 0; } else { @@ -1285,7 +1191,7 @@ int init_trigger(mcd_trigger_st* trigger) { } void handle_open_server(GArray *params, void *user_ctx) { - // initialize some core-independent data + // initialize core-independent data int return_value = 0; mcdserver_state.resets = g_array_new(false, true, sizeof(mcd_reset_st)); return_value = init_resets(mcdserver_state.resets); @@ -1301,8 +1207,6 @@ void handle_query_system(GArray *params, void *user_ctx) { } void handle_query_cores(GArray *params, void *user_ctx) { - //TODO: add cluster support: in gdb each inferior (process) handles one cluster we might want to have sth similar here - // get first cpu CPUState *cpu = mcd_first_attached_cpu(); if (!cpu) { @@ -1316,10 +1220,9 @@ void handle_query_cores(GArray *params, void *user_ctx) { gchar *arch = cc->gdb_arch_name(cpu); int nr_cores = cpu->nr_cores; - char device_name[] = DEVICE_NAME_TEMPLATE(arch); g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%s.%s=%d.", - TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_ARGUMENT_AMOUNT_CORE, nr_cores); + TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_ARGUMENT_AMOUNT_CORE, nr_cores); mcd_put_strbuf(); g_free(arch); } @@ -1441,7 +1344,6 @@ int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers) { } void handle_open_core(GArray *params, void *user_ctx) { - // get the cpu whith the given id uint32_t cpu_id = get_param(params, 0)->cpu_id; CPUState *cpu = mcd_get_cpu(cpu_id); mcdserver_state.c_cpu = cpu; @@ -1501,9 +1403,7 @@ void handle_open_core(GArray *params, void *user_ctx) { } void handle_query_reset_f(GArray *params, void *user_ctx) { - // resetting has to be done over a monitor (look ar Rcmd) so we tell MCD that we can reset but this still need to be implemented - // we only support one reset over this monitor and that would be a full "system_restart" - // reset options are the same for every cpu! + // TODO: vull reset over the qemu monitor // 1. check length int nb_resets = mcdserver_state.resets->len; @@ -1518,7 +1418,6 @@ void handle_query_reset_f(GArray *params, void *user_ctx) { mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, 0); g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); - // TODO: we still need to implement the gpr and memory reset here! } void handle_query_reset_c(GArray *params, void *user_ctx) { @@ -1539,7 +1438,6 @@ void handle_query_reset_c(GArray *params, void *user_ctx) { mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, query_index); g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); - // TODO: we still need to implement the gpr and memory reset here! } void handle_close_core(GArray *params, void *user_ctx) { @@ -1575,7 +1473,7 @@ void handle_close_server(GArray *params, void *user_ctx) { mcdserver_state.c_cpu = mcd_first_attached_cpu(); } if (!mcdserver_state.c_cpu) { - /* No more process attached */ + // no more processes attached mcd_disable_syscalls(); mcd_vm_start(); } @@ -1595,10 +1493,15 @@ void mcd_vm_start(void) { } } +int mcd_vm_sstep(CPUState *cpu) { + cpu_single_step(mcdserver_state.c_cpu, mcdserver_state.sstep_flags); + mcd_vm_start(); + return 0; +} + void mcd_vm_stop(void) { if (runstate_is_running()) { - //might want to have DEBUG state here but idk - vm_stop(RUN_STATE_PAUSED); + vm_stop(RUN_STATE_DEBUG); } } @@ -1724,7 +1627,7 @@ void handle_query_regs_f(GArray *params, void *user_ctx) { } void handle_query_regs_c(GArray *params, void *user_ctx) { - // this funcitons send all reg groups except for the first + // this funcitons send all regs except for the first // 1. get parameter and registers int query_index = get_param(params, 0)->query_handle; uint32_t cpu_id = mcdserver_state.query_cpu_id; @@ -1750,16 +1653,12 @@ void handle_query_regs_c(GArray *params, void *user_ctx) { } void handle_reset(GArray *params, void *user_ctx) { - int reset_id = get_param(params, 0)->data_int; - //int bool_halt_after_reset = get_param(params, 1)->data_int; - if (reset_id>=0) { - //fun for the compiler - } + //int reset_id = get_param(params, 0)->data_int; + // TODO: implement resets } void handle_query_state(GArray *params, void *user_ctx) { - // send state from correct core - //uint32_t cpu_id = get_param(params, 0)->cpu_id; + // TODO: multicore support // get state info mcd_cpu_state_st state_info = mcdserver_state.cpu_state; mcd_core_event_et event = MCD_CORE_EVENT_NONE; @@ -1795,6 +1694,19 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) { } } +int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg) { + CPUClass *cc = CPU_GET_CLASS(cpu); + gchar *arch = cc->gdb_arch_name(cpu); + if (strcmp(arch, "arm")==0) { + g_free(arch); + return arm_mcd_write_register(cpu, buf, reg); + } + else { + g_free(arch); + return 0; + } +} + void mcd_memtohex(GString *buf, const uint8_t *mem, int len) { int i, c; for(i = 0; i < len; i++) { @@ -1817,18 +1729,28 @@ void mcd_hextomem(GByteArray *mem, const char *buf, int len) { void handle_read_register(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; - int reg_num = get_param(params, 1)->data_int; + uint64_t reg_num = get_param(params, 1)->data_int; int reg_size; CPUState *cpu = mcd_get_cpu(cpu_id); - reg_size = mcd_read_register(cpu, mcdserver_state.mem_buf, reg_num); - mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, reg_size); + mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, reg_size); mcd_put_strbuf(); } void handle_write_register(GArray *params, void *user_ctx) { + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint64_t reg_num = get_param(params, 1)->data_int; + uint32_t reg_size = get_param(params, 2)->data_int; + CPUState *cpu = mcd_get_cpu(cpu_id); + mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, reg_size); + if (mcd_write_register(cpu, mcdserver_state.mem_buf, reg_num)==0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } + else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } } int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { @@ -1836,7 +1758,6 @@ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); cc = CPU_GET_CLASS(cpu); if (cc->memory_rw_debug) { - // TODO: check out the difference between those two calls return cc->memory_rw_debug(cpu, addr, buf, len, false); } @@ -1848,7 +1769,6 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); cc = CPU_GET_CLASS(cpu); if (cc->memory_rw_debug) { - // TODO: check out the difference between those two calls return cc->memory_rw_debug(cpu, addr, buf, len, true); } diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 0848e0dbdb..6a1c969f3b 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -306,7 +306,7 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - gdb_set_stop_cpu(cpu); + //gdb_set_stop_cpu(cpu); qemu_system_debug_request(); cpu->stopped = true; } diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index dc36a79a70..27e1a13b69 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -8,7 +8,7 @@ static inline int mcd_get_reg32(GByteArray *buf, uint32_t val) { - //FIXME: move this to a separate file + //TODO: move this to a separate file // convert endianess if necessary uint32_t to_long = tswap32(val); g_byte_array_append(buf, (uint8_t *) &to_long, 4); @@ -17,7 +17,7 @@ static inline int mcd_get_reg32(GByteArray *buf, uint32_t val) static inline int mcd_get_zeroes(GByteArray *array, size_t len) { - //FIXME: move this to a separate file + //TODO: move this to a separate file guint oldlen = array->len; g_byte_array_set_size(array, oldlen + len); memset(array->data + oldlen, 0, len); @@ -44,9 +44,6 @@ const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname) } int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) { - //CPUClass *cc = CPU_GET_CLASS(cpu); - //CPUArchState *env = cpu->env_ptr; - ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; @@ -70,6 +67,61 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) { return mcd_get_reg32(mem_buf, cpsr_read(env)); } } - //TODO: add funcitons for regs with higher numbers (including cp_regs) + //TODO: add funcitons for the remaining regs (including cp_regs) + return 0; +} + +int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) { + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + uint32_t tmp; + + tmp = ldl_p(mem_buf); + tmp = *((uint32_t*)mem_buf->data); + + /* + * Mask out low bits of PC to workaround gdb bugs. + * This avoids an assert in thumb_tr_translate_insn, because it is + * architecturally impossible to misalign the pc. + * This will probably cause problems if we ever implement the + * Jazelle DBX extensions. + */ + if (n == 15) { + tmp &= ~1; + } + + if (n < 16) { + /* Core integer register. */ + if (n == 13 && arm_feature(env, ARM_FEATURE_M)) { + /* M profile SP low bits are always 0 */ + tmp &= ~3; + } + env->regs[n] = tmp; + return 4; + } + if (n < 24) { /* 16-23 */ + /* FPA registers (ignored). */ + return 4; + } + switch (n) { + case 24: + /* FPA status register (ignored). */ + return 4; + case 25: + /* CPSR, or XPSR for M-profile */ + if (arm_feature(env, ARM_FEATURE_M)) { + /* + * Don't allow writing to XPSR.Exception as it can cause + * a transition into or out of handler mode (it's not + * writable via the MSR insn so this is a reasonable + * restriction). Other fields are safe to update. + */ + xpsr_write(env, tmp, ~XPSR_EXCP); + } else { + cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); + } + return 4; + } + //TODO: add funcitons for the remaining regs (including cp_regs) return 0; -} \ No newline at end of file +} diff --git a/target/arm/mcdstub.h b/target/arm/mcdstub.h index d61028c7f4..28c7f2baec 100644 --- a/target/arm/mcdstub.h +++ b/target/arm/mcdstub.h @@ -3,5 +3,6 @@ const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname); int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n); +int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n); #endif /* ARM_MCDSTUB_H */ From patchwork Fri Oct 6 09:05:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844290 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dL4Tlvz1yqF for ; Fri, 6 Oct 2023 20:07:50 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognf-0008Mh-DD; Fri, 06 Oct 2023 05:07:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognN-0008AQ-4d for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:54 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognI-0000yv-Js for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:52 -0400 Received: (qmail 19721 invoked by uid 484); 6 Oct 2023 09:06:35 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.152078 secs); 06 Oct 2023 09:06:35 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:33 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 15/29] adapting to the qemu coding style Date: Fri, 6 Oct 2023 11:05:56 +0200 Message-Id: <20231006090610.26171-16-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- gdbstub/gdbstub.c | 2 +- include/exec/mcdstub.h | 3 +- include/mcdstub/syscalls.h | 2 +- mcdstub/mcd_shared_defines.h | 17 +- mcdstub/mcd_softmmu.c | 171 ----- mcdstub/mcd_syscalls.c | 7 +- mcdstub/mcd_tcp_server.c | 95 --- mcdstub/mcdstub.c | 1037 ++++++++++++++++------------ mcdstub/{internals.h => mcdstub.h} | 102 +-- mcdstub/meson.build | 16 +- softmmu/cpus.c | 2 +- softmmu/vl.c | 4 +- target/arm/mcdstub.c | 24 +- 13 files changed, 684 insertions(+), 798 deletions(-) delete mode 100644 mcdstub/mcd_softmmu.c delete mode 100644 mcdstub/mcd_tcp_server.c rename mcdstub/{internals.h => mcdstub.h} (69%) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 2ff50757bb..349d348c7b 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -857,7 +857,7 @@ static int process_string_cmd(const char *data, if (cmd->schema) { if (cmd_parse_params(&data[strlen(cmd->cmd)], - cmd->schema, params)) { + cmd->schema, params)) { return -1; } } diff --git a/include/exec/mcdstub.h b/include/exec/mcdstub.h index 132f32417c..84f7c811cb 100644 --- a/include/exec/mcdstub.h +++ b/include/exec/mcdstub.h @@ -2,9 +2,8 @@ #define MCDSTUB_H #define DEFAULT_MCDSTUB_PORT "1235" -#define TYPE_CHARDEV_MCD "chardev-mcd" -// breakpoint defines +/* breakpoint defines */ #define MCD_BREAKPOINT_SW 0 #define MCD_BREAKPOINT_HW 1 #define MCD_WATCHPOINT_WRITE 2 diff --git a/include/mcdstub/syscalls.h b/include/mcdstub/syscalls.h index 92ae7f4e77..5547d6d29e 100644 --- a/include/mcdstub/syscalls.h +++ b/include/mcdstub/syscalls.h @@ -3,4 +3,4 @@ typedef void (*gdb_syscall_complete_cb)(CPUState *cpu, uint64_t ret, int err); -#endif /* _SYSCALLS_H_ */ \ No newline at end of file +#endif /* _SYSCALLS_H_ */ diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 311d24e12f..891f6477e7 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -1,9 +1,12 @@ -// this file is shared between the mcd dll and the mcd stub. it has to be kept exectly the same! +/* + *this file is shared between the mcd dll and the mcd stub. + *it has to be kept exectly the same! + */ #ifndef MCD_SHARED_DEFINES #define MCD_SHARED_DEFINES -// tcp data characters +/* tcp data characters */ #define TCP_CHAR_OPEN_SERVER 'I' #define TCP_CHAR_OPEN_CORE 'i' #define TCP_CHAR_GO 'C' @@ -19,7 +22,7 @@ #define TCP_CHAR_READ_MEMORY 'm' #define TCP_CHAR_WRITE_MEMORY 'M' -// tcp protocol chars +/* tcp protocol chars */ #define TCP_ACKNOWLEDGED '+' #define TCP_NOT_ACKNOWLEDGED '-' #define TCP_COMMAND_START '$' @@ -30,7 +33,7 @@ #define TCP_EXECUTION_SUCCESS "success" #define TCP_EXECUTION_ERROR "error" -// tcp query arguments +/* tcp query arguments */ #define QUERY_FIRST "f" #define QUERY_CONSEQUTIVE "c" @@ -43,7 +46,7 @@ #define QUERY_ARG_REG "reg" #define QUERY_ARG_STATE "state" -// tcp query packet argument list +/* tcp query packet argument list */ #define TCP_ARGUMENT_NAME "name" #define TCP_ARGUMENT_DATA "data" #define TCP_ARGUMENT_ID "id" @@ -70,10 +73,10 @@ #define TCP_ARGUMENT_OPTION "option" #define TCP_ARGUMENT_ACTION "action" -// for packets sent to qemu +/* for packets sent to qemu */ #define ARGUMENT_SEPARATOR ';' -// core states +/* core states */ #define CORE_STATE_RUNNING "running" #define CORE_STATE_HALTED "halted" #define CORE_STATE_DEBUG "debug" diff --git a/mcdstub/mcd_softmmu.c b/mcdstub/mcd_softmmu.c deleted file mode 100644 index 52dcb182b2..0000000000 --- a/mcdstub/mcd_softmmu.c +++ /dev/null @@ -1,171 +0,0 @@ -/* -#if defined(WIN32) -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 -#endif -#include -#include -//#pragma comment(lib, "Ws2_32.lib") -#define ISVALIDSOCKET(s) ((s) != INVALID_SOCKET) -#define CLOSESOCKET(s) closesocket(s) -#define GETSOCKETERRNO() (WSAGetLastError()) -#else -#include -#include -#include -#include -#include -#include -//#include -#define SOCKET int -#define ISVALIDSOCKET(s) ((s) >= 0) -#define CLOSESOCKET(s) close(s) -#define GETSOCKETERRNO() (errno) -#endif - -#define SA struct sockaddr - - - -#include "exec/mcdstub.h" -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu/error-report.h" -#include "qemu/cutils.h" -#include "gdbstub/syscalls.h" -#include "exec/hwaddr.h" -#include "exec/tb-flush.h" -#include "sysemu/cpus.h" -#include "sysemu/runstate.h" -#include "sysemu/replay.h" -#include "hw/core/cpu.h" -#include "hw/cpu/cluster.h" -#include "hw/boards.h" -#include "chardev/char.h" -#include "chardev/char-fe.h" -#include "monitor/monitor.h" -#include "internals.h" - -//here only deprecated code: - -int old_mcdserver_start(const char *device) -{ - //the device is a char array. if its "default" we use tcp with the default DEFAULT_MCDSTUB_PORT. Otherwise it has to look like "tcp::" - char tcp_port[MX_INPUT_LENGTH]; - int error; - error = mcd_extract_tcp_port_num(device, tcp_port); - if (error != 0) { - return -1; - } - int tcp_port_num = atoi(tcp_port); - - if (!mcdserver_state.init) { - mcd_init_mcdserver_state(); - } - return mcd_open_tcp_socket(tcp_port_num); -} - -int mcd_open_tcp_socket(int tcp_port) -//soon to be deprecated (hopefully) -{ - SOCKET socked_fd, connect_fd; - struct sockaddr_in server_address, client_address; - -#if defined(WIN32) - WSADATA d; - if (WSAStartup(MAKEWORD(2, 2), &d)) { - return -1; - } - int len; -#else - unsigned int len; -#endif - - // socket create and verification - socked_fd = socket(AF_INET, SOCK_STREAM, 0); - if (!ISVALIDSOCKET(socked_fd)) { - return -1; - } - memset(&server_address, 0, sizeof(server_address)); - - // assign IP, PORT - server_address.sin_family = AF_INET; - server_address.sin_port = htons(tcp_port); - server_address.sin_addr.s_addr = htonl(INADDR_ANY); - - // Binding newly created socket to given IP and verification - if ((bind(socked_fd, (SA*)&server_address, sizeof(server_address))) != 0) { - CLOSESOCKET(socked_fd); - return -1; - } - - // Now server is ready to listen and verification - if ((listen(socked_fd, 5)) != 0) { - CLOSESOCKET(socked_fd); - return -1; - } - else { - printf("TCP server listening on port %d\n", tcp_port); - } - - //accepting connection - len = sizeof(client_address); - connect_fd = accept(socked_fd, (SA*)&client_address, &len); - if (!ISVALIDSOCKET(connect_fd)) { - CLOSESOCKET(socked_fd); - return -1; - } - - //lets do the handshake - - char buff[MCD_TCP_DATALEN]; - char expected_buff[MCD_TCP_DATALEN]; - - memset(buff, 0, sizeof(buff)); - memset(expected_buff, 0, sizeof(buff)); - strcpy((char*)expected_buff, "initializing handshake"); - - // read the message from client - recv(connect_fd, buff, MCD_TCP_DATALEN, 0); - - if (strcmp(buff, expected_buff)==0) { - strcpy((char*)buff, "shaking your hand"); - send(connect_fd, buff, MCD_TCP_DATALEN, 0); - printf("handshake complete\n"); - return 0; - } - else { - CLOSESOCKET(socked_fd); - CLOSESOCKET(connect_fd); - return -1; - } -} - -int mcd_extract_tcp_port_num(const char *in_string, char *out_string) -{ - int string_length = strlen(in_string); - if (string_length>MX_INPUT_LENGTH+1) { - return -1; - } - - const char default_str[] = "default"; - - if ((string_length==strlen(default_str)) && (strcmp(default_str, in_string)==0)) { - strcpy((char*)out_string, DEFAULT_MCDSTUB_PORT); - return 0; - } - else if (strcmp("tcp::", in_string)==0) { - for (int index = 5; index < string_length; index++) { - if (!isdigit(in_string[index])) { - return -1; - } - } - } - else { - return -1; - } - strcpy((char*)out_string, in_string+5); - return 0; -} - -*/ \ No newline at end of file diff --git a/mcdstub/mcd_syscalls.c b/mcdstub/mcd_syscalls.c index dec0af51b7..eaa6853335 100644 --- a/mcdstub/mcd_syscalls.c +++ b/mcdstub/mcd_syscalls.c @@ -3,12 +3,11 @@ #include "semihosting/semihost.h" #include "sysemu/runstate.h" #include "mcdstub/syscalls.h" -//#include "trace.h" -#include "internals.h" +#include "mcdstub.h" typedef struct { char syscall_buf[256]; - //TODO: this needs to be get fixed mcd_syscall_complete_cb + /* TODO: this needs to be get fixed mcd_syscall_complete_cb */ int current_syscall_cb; } MCDSyscallState; @@ -28,4 +27,4 @@ void mcd_syscall_reset(void) void mcd_disable_syscalls(void) { mcd_syscall_mode = MCD_SYS_DISABLED; -} \ No newline at end of file +} diff --git a/mcdstub/mcd_tcp_server.c b/mcdstub/mcd_tcp_server.c deleted file mode 100644 index 558ddcb969..0000000000 --- a/mcdstub/mcd_tcp_server.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include // read(), write(), close() -#include "exec/mcdstub.h" -#define MAX 80 -#define SA struct sockaddr - -// Function designed for chat between client and server. -void func(int connfd) -{ - char buff[MAX]; - int n; - // infinite loop for chat - for (;;) { - bzero(buff, MAX); - - // read the message from client and copy it in buffer - read(connfd, buff, sizeof(buff)); - // print buffer which contains the client contents - printf("From client: %s\t To client : ", buff); - bzero(buff, MAX); - n = 0; - // copy server message in the buffer - while ((buff[n++] = getchar()) != '\n') - ; - - // and send that buffer to client - write(connfd, buff, sizeof(buff)); - - // if msg contains "Exit" then server exit and chat ended. - if (strncmp("exit", buff, 4) == 0) { - printf("Server Exit...\n"); - break; - } - } -} - -// Driver function -int main() -{ - int sockfd, connfd, len; - struct sockaddr_in servaddr, cli; - - // socket create and verification - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == -1) { - printf("socket creation failed...\n"); - exit(0); - } - else - printf("Socket successfully created..\n"); - bzero(&servaddr, sizeof(servaddr)); - - // assign IP, PORT - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - servaddr.sin_port = htons(DEFAULT_MCDSTUB_PORT); - - // Binding newly created socket to given IP and verification - if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) { - printf("socket bind failed...\n"); - exit(0); - } - else - printf("Socket successfully binded..\n"); - - // Now server is ready to listen and verification - if ((listen(sockfd, 5)) != 0) { - printf("Listen failed...\n"); - exit(0); - } - else - printf("Server listening..\n"); - len = sizeof(cli); - - // Accept the data packet from client and verification - connfd = accept(sockfd, (SA*)&cli, &len); - if (connfd < 0) { - printf("server accept failed...\n"); - exit(0); - } - else - printf("server accept the client...\n"); - - // Function for chatting between client and server - func(connfd); - - // After chatting close the socket - close(sockfd); -} diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index d65b0a54d2..9f79864af6 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -2,8 +2,6 @@ * This is the main mcdstub. */ -#include "mcd_shared_defines.h" - #include "qemu/osdep.h" #include "qemu/ctype.h" #include "qemu/cutils.h" @@ -17,7 +15,6 @@ #include "sysemu/runstate.h" #include "exec/replay-core.h" #include "exec/hwaddr.h" -#include "internals.h" #include "qapi/error.h" #include "exec/tb-flush.h" @@ -27,11 +24,12 @@ #include "chardev/char-fe.h" #include "monitor/monitor.h" -// architecture specific stubs -#include "target/arm/mcdstub.h" +/* mcdstub header files */ +#include "mcd_shared_defines.h" +#include "mcdstub.h" -// FIXME: delete the following line and check if it worked -#include "hw/core/sysemu-cpu-ops.h" +/* architecture specific stubs */ +#include "target/arm/mcdstub.h" typedef struct { CharBackend chr; @@ -43,7 +41,7 @@ MCDState mcdserver_state; void mcd_init_mcdserver_state(void) { - g_assert(!mcdserver_state.init); + g_assert(!mcdserver_state.init); memset(&mcdserver_state, 0, sizeof(MCDState)); mcdserver_state.init = true; mcdserver_state.str_buf = g_string_new(NULL); @@ -55,14 +53,15 @@ void mcd_init_mcdserver_state(void) * By default try to use no IRQs and no timers while single * stepping so as to make single stepping like a typical ICE HW step. */ - mcdserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); + mcdserver_state.supported_sstep_flags = + accel_supported_gdbstub_sstep_flags(); mcdserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; mcdserver_state.sstep_flags &= mcdserver_state.supported_sstep_flags; - // init query table + /* init query table */ init_query_cmds_table(mcdserver_state.mcd_query_cmds_table); - // at this time the cpu hans't been started! -> set cpu_state + /* at this time the cpu hans't been started! -> set cpu_state */ mcd_cpu_state_st cpu_state = { .state = CORE_STATE_HALTED, .info_str = STATE_STR_INIT_HALTED, @@ -70,8 +69,9 @@ void mcd_init_mcdserver_state(void) mcdserver_state.cpu_state = cpu_state; } -void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table) { - // initalizes a list of all query commands +void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) +{ + /* initalizes a list of all query commands */ int cmd_number = 0; MCDCmdParseEntry query_system = { @@ -270,7 +270,7 @@ int mcdserver_start(const char *device) return -1; } - // if device == default -> set device = tcp::1235 + /* if device == default -> set device = tcp::1235 */ if (strcmp(device, "default") == 0) { device = "tcp::1235"; } @@ -329,10 +329,12 @@ int mcd_chr_can_receive(void *opaque) void mcd_chr_receive(void *opaque, const uint8_t *buf, int size) { int i; - + for (i = 0; i < size; i++) { mcd_read_byte(buf[i]); - if (buf[i]==0) break; + if (buf[i] == 0) { + break; + } } } @@ -342,27 +344,30 @@ void mcd_read_byte(uint8_t ch) if (mcdserver_state.last_packet->len) { if (ch == TCP_NOT_ACKNOWLEDGED) { - // the previous packet was not akcnowledged - mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); - } - else if (ch == TCP_ACKNOWLEDGED) { - // the previous packet was acknowledged + /* the previous packet was not akcnowledged */ + mcd_put_buffer(mcdserver_state.last_packet->data, + mcdserver_state.last_packet->len); + } else if (ch == TCP_ACKNOWLEDGED) { + /* the previous packet was acknowledged */ } if (ch == TCP_ACKNOWLEDGED || ch == TCP_COMMAND_START) { - // either acknowledged or a new communication starts -> discard previous packet + /* + * either acknowledged or a new communication starts + * -> discard previous packet + */ g_byte_array_set_size(mcdserver_state.last_packet, 0); } if (ch != TCP_COMMAND_START) { - // skip to the next char + /* skip to the next char */ return; } } - switch(mcdserver_state.state) { + switch (mcdserver_state.state) { case RS_IDLE: if (ch == TCP_COMMAND_START) { - // start of command packet + /* start of command packet */ mcdserver_state.line_buf_index = 0; mcdserver_state.line_sum = 0; mcdserver_state.state = RS_GETLINE; @@ -370,16 +375,15 @@ void mcd_read_byte(uint8_t ch) break; case RS_GETLINE: if (ch == TCP_COMMAND_END) { - // end of command + /* end of command */ mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = 0; mcdserver_state.state = RS_DATAEND; - } - else if (mcdserver_state.line_buf_index >= sizeof(mcdserver_state.line_buf) - 1) { - // the input string is too long for the linebuffer! + } else if (mcdserver_state.line_buf_index >= + sizeof(mcdserver_state.line_buf) - 1) { + /* the input string is too long for the linebuffer! */ mcdserver_state.state = RS_IDLE; - } - else { - // copy the content to the line_buf + } else { + /* copy the content to the line_buf */ mcdserver_state.line_buf[mcdserver_state.line_buf_index++] = ch; mcdserver_state.line_sum += ch; } @@ -389,17 +393,15 @@ void mcd_read_byte(uint8_t ch) reply = TCP_ACKNOWLEDGED; mcd_put_buffer(&reply, 1); mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); - } - else if (ch == TCP_WAS_LAST) { + } else if (ch == TCP_WAS_LAST) { reply = TCP_ACKNOWLEDGED; mcd_put_buffer(&reply, 1); mcdserver_state.state = mcd_handle_packet(mcdserver_state.line_buf); - } - else { - // not acknowledged! + } else { + /* not acknowledged! */ reply = TCP_NOT_ACKNOWLEDGED; mcd_put_buffer(&reply, 1); - // waiting for package to get resent + /* waiting for package to get resent */ mcdserver_state.state = RS_IDLE; } break; @@ -410,7 +412,10 @@ void mcd_read_byte(uint8_t ch) int mcd_handle_packet(const char *line_buf) { - // decides what function (handler) to call depending on the first character in the line_buf + /* + * decides what function (handler) to call depending on + * the first character in the line_buf + */ const MCDCmdParseEntry *cmd_parser = NULL; switch (line_buf[0]) { @@ -438,7 +443,8 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_vm_step, }; step_cmd_desc.cmd = (char[2]) { TCP_CHAR_STEP, '\0' }; - strcpy(step_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + strcpy(step_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &step_cmd_desc; } break; @@ -452,7 +458,7 @@ int mcd_handle_packet(const char *line_buf) } break; case TCP_CHAR_KILLQEMU: - // kill qemu completely + /* kill qemu completely */ error_report("QEMU: Terminated via MCDstub"); mcd_exit(0); exit(0); @@ -462,7 +468,8 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_gen_query, }; query_cmd_desc.cmd = (char[2]) { TCP_CHAR_QUERY, '\0' }; - strcpy(query_cmd_desc.schema, (char[2]) { ARG_SCHEMA_STRING, '\0' }); + strcpy(query_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_STRING, '\0' }); cmd_parser = &query_cmd_desc; } break; @@ -472,7 +479,8 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_open_core, }; open_core_cmd_desc.cmd = (char[2]) { TCP_CHAR_OPEN_CORE, '\0' }; - strcpy(open_core_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + strcpy(open_core_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &open_core_cmd_desc; } break; @@ -481,7 +489,8 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry close_server_cmd_desc = { .handler = handle_close_server, }; - close_server_cmd_desc.cmd = (char[2]) { TCP_CHAR_CLOSE_SERVER, '\0' }; + close_server_cmd_desc.cmd = + (char[2]) { TCP_CHAR_CLOSE_SERVER, '\0' }; cmd_parser = &close_server_cmd_desc; } break; @@ -491,7 +500,8 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_close_core, }; close_core_cmd_desc.cmd = (char[2]) { TCP_CHAR_CLOSE_CORE, '\0' }; - strcpy(close_core_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + strcpy(close_core_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &close_core_cmd_desc; } break; @@ -511,7 +521,8 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_read_register, }; read_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_READ_REGISTER, '\0' }; - strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, '\0' }); + strcpy(read_reg_cmd_desc.schema, + (char[3]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, '\0' }); cmd_parser = &read_reg_cmd_desc; } break; @@ -520,8 +531,11 @@ int mcd_handle_packet(const char *line_buf) static MCDCmdParseEntry write_reg_cmd_desc = { .handler = handle_write_register, }; - write_reg_cmd_desc.cmd = (char[2]) { TCP_CHAR_WRITE_REGISTER, '\0' }; - strcpy(write_reg_cmd_desc.schema, (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); + write_reg_cmd_desc.cmd = + (char[2]) { TCP_CHAR_WRITE_REGISTER, '\0' }; + strcpy(write_reg_cmd_desc.schema, + (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, + ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); cmd_parser = &write_reg_cmd_desc; } break; @@ -531,7 +545,9 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_read_memory, }; read_mem_cmd_desc.cmd = (char[2]) { TCP_CHAR_READ_MEMORY, '\0' }; - strcpy(read_mem_cmd_desc.schema, (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, '\0' }); + strcpy(read_mem_cmd_desc.schema, + (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, + ARG_SCHEMA_INT, '\0' }); cmd_parser = &read_mem_cmd_desc; } break; @@ -541,48 +557,57 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_write_memory, }; write_mem_cmd_desc.cmd = (char[2]) { TCP_CHAR_WRITE_MEMORY, '\0' }; - strcpy(write_mem_cmd_desc.schema, (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); + strcpy(write_mem_cmd_desc.schema, + (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, + ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); cmd_parser = &write_mem_cmd_desc; } break; default: - // command not supported + /* command not supported */ mcd_put_packet(""); break; } if (cmd_parser) { - // parse commands and run the selected handler function + /* parse commands and run the selected handler function */ run_cmd_parser(line_buf, cmd_parser); } return RS_IDLE; } -void handle_vm_start(GArray *params, void *user_ctx) { - // TODO: add partial restart with arguments and so on +void handle_vm_start(GArray *params, void *user_ctx) +{ + /* TODO: add partial restart with arguments and so on */ mcd_vm_start(); } -void handle_vm_step(GArray *params, void *user_ctx) { - // TODO: add partial restart with arguments and so on +void handle_vm_step(GArray *params, void *user_ctx) +{ + /* TODO: add partial restart with arguments and so on */ uint32_t cpu_id = get_param(params, 0)->cpu_id; CPUState *cpu = mcd_get_cpu(cpu_id); - mcd_vm_sstep(cpu); + int return_value = mcd_vm_sstep(cpu); + if (return_value != 0) { + g_assert_not_reached(); + } } -void handle_vm_stop(GArray *params, void *user_ctx) { - // TODO: add partial stop with arguments and so on +void handle_vm_stop(GArray *params, void *user_ctx) +{ + /* TODO: add partial stop with arguments and so on */ mcd_vm_stop(); } -void handle_gen_query(GArray *params, void *user_ctx) { +void handle_gen_query(GArray *params, void *user_ctx) +{ if (!params->len) { return; } - // iterate over all possible query functions and execute the right one + /* iterate over all possible query functions and execute the right one */ if (process_string_cmd(NULL, get_param(params, 0)->data, mcdserver_state.mcd_query_cmds_table, ARRAY_SIZE(mcdserver_state.mcd_query_cmds_table))) { @@ -590,7 +615,8 @@ void handle_gen_query(GArray *params, void *user_ctx) { } } -void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) { +void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) +{ if (!data) { return; } @@ -603,10 +629,10 @@ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd) { } } -uint64_t atouint64_t(const char* in) { +uint64_t atouint64_t(const char *in) +{ uint64_t res = 0; - for (int i = 0; i < strlen(in); ++i) - { + for (int i = 0; i < strlen(in); ++i) { const char c = in[i]; res *= 10; res += c - '0'; @@ -615,33 +641,33 @@ uint64_t atouint64_t(const char* in) { return res; } -int cmd_parse_params(const char *data, const char *schema, GArray *params) { - +int cmd_parse_params(const char *data, const char *schema, GArray *params) +{ + char data_buffer[64] = {0}; const char *remaining_data = data; - - for (int i = 0; ihandler && cmd->cmd); - // continue if data and command are different + /* continue if data and command are different */ if (strncmp(data, cmd->cmd, strlen(cmd->cmd))) { continue; } if (strlen(cmd->schema)) { - // extract data for parameters - if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, params)) { + /* extract data for parameters */ + if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, params)) + { return -1; } } - // call handler + /* call handler */ cmd->handler(params, user_ctx); return 0; } @@ -703,8 +732,9 @@ int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry return -1; } -void mcd_exit(int code) { - // terminate qemu +void mcd_exit(int code) +{ + /* terminate qemu */ if (!mcdserver_state.init) { return; } @@ -712,13 +742,14 @@ void mcd_exit(int code) { qemu_chr_fe_deinit(&mcdserver_system_state.chr, true); } -void mcd_chr_event(void *opaque, QEMUChrEvent event) { +void mcd_chr_event(void *opaque, QEMUChrEvent event) +{ int i; MCDState *s = (MCDState *) opaque; switch (event) { case CHR_EVENT_OPENED: - // Start with first process attached, others detached + /* Start with first process attached, others detached */ for (i = 0; i < s->process_num; i++) { s->processes[i].attached = !i; } @@ -730,7 +761,8 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event) { } } -bool mcd_supports_guest_debug(void) { +bool mcd_supports_guest_debug(void) +{ const AccelOpsClass *ops = cpus_get_accel(); if (ops->supports_guest_debug) { return ops->supports_guest_debug(); @@ -739,15 +771,17 @@ bool mcd_supports_guest_debug(void) { } #ifndef _WIN32 -void mcd_sigterm_handler(int signal) { +void mcd_sigterm_handler(int signal) +{ if (runstate_is_running()) { vm_stop(RUN_STATE_PAUSED); } } #endif -void mcd_vm_state_change(void *opaque, bool running, RunState state) { - CPUState *cpu = mcdserver_state.c_cpu; +void mcd_vm_state_change(void *opaque, bool running, RunState state) +{ + CPUState *cpu = mcdserver_state.c_cpu; if (mcdserver_state.state == RS_INACTIVE) { return; @@ -755,7 +789,10 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) { if (cpu == NULL) { if (running) { - // this is the case if qemu starts the vm before a mcd client is connected + /* + * this is the case if qemu starts the vm + * before a mcd client is connected + */ const char *mcd_state; mcd_state = CORE_STATE_RUNNING; const char *info_str; @@ -798,13 +835,11 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) { stop_str = STATE_STR_BREAK_UNKNOWN; } cpu->watchpoint_hit = NULL; - } - else if (cpu->singlestep_enabled){ - // we land here when a single step is performed + } else if (cpu->singlestep_enabled) { + /* we land here when a single step is performed */ cpu_single_step(cpu, 0); stop_str = STATE_STEP_PERFORMED; - } - else { + } else { trig_id = MCD_TRIG_TYPE_IP; stop_str = STATE_STR_BREAK_HW; tb_flush(cpu); @@ -816,7 +851,6 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) { stop_str = ""; break; case RUN_STATE_WATCHDOG: - printf("runstate watchdog hit\n"); info_str = STATE_STR_UNKNOWN(cpu->cpu_index); mcd_state = CORE_STATE_UNKNOWN; stop_str = ""; @@ -828,30 +862,38 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) { break; } - // set state for c_cpu + /* set state for c_cpu */ mcdserver_state.cpu_state.state = mcd_state; mcdserver_state.cpu_state.trig_id = trig_id; mcdserver_state.cpu_state.stop_str = stop_str; mcdserver_state.cpu_state.info_str = info_str; } -int mcd_put_packet(const char *buf) { +int mcd_put_packet(const char *buf) +{ return mcd_put_packet_binary(buf, strlen(buf), false); } -void mcd_put_strbuf(void) { +void mcd_put_strbuf(void) +{ mcd_put_packet(mcdserver_state.str_buf->str); } -int mcd_put_packet_binary(const char *buf, int len, bool dump) { - for(;;) { +int mcd_put_packet_binary(const char *buf, int len, bool dump) +{ + for (;;) { g_byte_array_set_size(mcdserver_state.last_packet, 0); - g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_COMMAND_START, '\0' }, 1); - g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) buf, len); - g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_COMMAND_END, '\0' }, 1); - g_byte_array_append(mcdserver_state.last_packet, (const uint8_t *) (char[2]) { TCP_WAS_LAST, '\0' }, 1); - - mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.last_packet->len); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) (char[2]) { TCP_COMMAND_START, '\0' }, 1); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) buf, len); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) (char[2]) { TCP_COMMAND_END, '\0' }, 1); + g_byte_array_append(mcdserver_state.last_packet, + (const uint8_t *) (char[2]) { TCP_WAS_LAST, '\0' }, 1); + + mcd_put_buffer(mcdserver_state.last_packet->data, + mcdserver_state.last_packet->len); if (mcd_got_immediate_ack()) { break; @@ -860,28 +902,33 @@ int mcd_put_packet_binary(const char *buf, int len, bool dump) { return 0; } -bool mcd_got_immediate_ack(void) { +bool mcd_got_immediate_ack(void) +{ return true; } -void mcd_put_buffer(const uint8_t *buf, int len) { +void mcd_put_buffer(const uint8_t *buf, int len) +{ qemu_chr_fe_write_all(&mcdserver_system_state.chr, buf, len); } -MCDProcess *mcd_get_cpu_process(CPUState *cpu) { +MCDProcess *mcd_get_cpu_process(CPUState *cpu) +{ return mcd_get_process(mcd_get_cpu_pid(cpu)); } -uint32_t mcd_get_cpu_pid(CPUState *cpu) { +uint32_t mcd_get_cpu_pid(CPUState *cpu) +{ if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) { - // Return the default process' PID + /* Return the default process' PID */ int index = mcdserver_state.process_num - 1; return mcdserver_state.processes[index].pid; } return cpu->cluster_index + 1; } -MCDProcess *mcd_get_process(uint32_t pid) { +MCDProcess *mcd_get_process(uint32_t pid) +{ int i; if (!pid) { @@ -898,7 +945,8 @@ MCDProcess *mcd_get_process(uint32_t pid) { return NULL; } -CPUState* mcd_get_cpu(uint32_t i_cpu_index) { +CPUState *mcd_get_cpu(uint32_t i_cpu_index) +{ CPUState *cpu = first_cpu; while (cpu) { @@ -911,7 +959,8 @@ CPUState* mcd_get_cpu(uint32_t i_cpu_index) { return cpu; } -CPUState *mcd_first_attached_cpu(void) { +CPUState *mcd_first_attached_cpu(void) +{ CPUState *cpu = first_cpu; MCDProcess *process = mcd_get_cpu_process(cpu); @@ -922,7 +971,8 @@ CPUState *mcd_first_attached_cpu(void) { return cpu; } -CPUState *mcd_next_attached_cpu(CPUState *cpu) { +CPUState *mcd_next_attached_cpu(CPUState *cpu) +{ cpu = CPU_NEXT(cpu); while (cpu) { @@ -936,11 +986,13 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu) { return cpu; } -int mcd_get_cpu_index(CPUState *cpu) { +int mcd_get_cpu_index(CPUState *cpu) +{ return cpu->cpu_index + 1; } -CPUState *get_first_cpu_in_process(MCDProcess *process) { +CPUState *get_first_cpu_in_process(MCDProcess *process) +{ CPUState *cpu; CPU_FOREACH(cpu) { @@ -952,7 +1004,8 @@ CPUState *get_first_cpu_in_process(MCDProcess *process) { return NULL; } -CPUState *find_cpu(uint32_t thread_id) { +CPUState *find_cpu(uint32_t thread_id) +{ CPUState *cpu; CPU_FOREACH(cpu) { @@ -965,8 +1018,9 @@ CPUState *find_cpu(uint32_t thread_id) { } -void parse_reg_xml(const char *xml, int size, GArray* registers) { - // iterates over the complete xml file +void parse_reg_xml(const char *xml, int size, GArray *registers) +{ + /* iterates over the complete xml file */ int i, j; int still_to_skip = 0; char argument[64] = {0}; @@ -987,108 +1041,103 @@ void parse_reg_xml(const char *xml, int size, GArray* registers) { c = xml[i]; c_ptr = &c; - if (still_to_skip>0) { - // skip unwanted chars - still_to_skip --; + if (still_to_skip > 0) { + /* skip unwanted chars */ + still_to_skip--; continue; } - if (strncmp(&xml[i], "", 2)==0) { - // end of register info + } else if (is_reg) { + if (strncmp(&xml[i], "/>", 2) == 0) { + /* end of register info */ still_to_skip = 1; is_reg = false; - // create empty register + /* create empty register */ mcd_reg_st my_register = (const struct mcd_reg_st){ 0 }; - // add found attribtues - for (j = 0; jlen; j++) { + /* add found attribtues */ + for (j = 0; j < reg_data->len; j++) { attribute_j = g_array_index(reg_data, xml_attrib, j); argument_j = attribute_j.argument; value_j = attribute_j.value; - if (strcmp(argument_j, "name")==0) { + if (strcmp(argument_j, "name") == 0) { strcpy(my_register.name, value_j); - } - else if (strcmp(argument_j, "regnum")==0) { + } else if (strcmp(argument_j, "regnum") == 0) { my_register.id = atoi(value_j); - } - else if (strcmp(argument_j, "bitsize")==0) { + } else if (strcmp(argument_j, "bitsize") == 0) { my_register.bitsize = atoi(value_j); - } - else if (strcmp(argument_j, "type")==0) { + } else if (strcmp(argument_j, "type") == 0) { strcpy(my_register.type, value_j); - } - else if (strcmp(argument_j, "group")==0) { + } else if (strcmp(argument_j, "group") == 0) { strcpy(my_register.group, value_j); } } - // store register + /* store register */ g_array_append_vals(registers, (gconstpointer)&my_register, 1); - // free memory + /* free memory */ g_array_free(reg_data, false); - } - else { - // store info for register + } else { + /* store info for register */ switch (c) { - case ' ': - break; - case '=': - is_argument = false; - break; - case '"': - if (is_value) { - // end of value reached - is_value = false; - // store arg-val combo - xml_attrib current_attribute; - strcpy(current_attribute.argument, argument); - strcpy(current_attribute.value, value); - g_array_append_vals(reg_data, (gconstpointer)¤t_attribute, 1); - memset(argument, 0, sizeof(argument)); - memset(value, 0, sizeof(value)); - } - else { - //start of value - is_value = true; - } - break; - default: - if (is_argument) { - strncat(argument, c_ptr, 1); - } - else if (is_value) { - strncat(value, c_ptr, 1); - } - else { - is_argument = true; - strncat(argument, c_ptr, 1); - } - break; + case ' ': + break; + case '=': + is_argument = false; + break; + case '"': + if (is_value) { + /* end of value reached */ + is_value = false; + /* store arg-val combo */ + xml_attrib current_attribute; + strcpy(current_attribute.argument, argument); + strcpy(current_attribute.value, value); + g_array_append_vals(reg_data, + (gconstpointer)¤t_attribute, 1); + memset(argument, 0, sizeof(argument)); + memset(value, 0, sizeof(value)); + } else { + /*start of value */ + is_value = true; + } + break; + default: + if (is_argument) { + strncat(argument, c_ptr, 1); + } else if (is_value) { + strncat(value, c_ptr, 1); + } else { + is_argument = true; + strncat(argument, c_ptr, 1); + } + break; } } } } } -int int_cmp(gconstpointer a, gconstpointer b) { - if (*(int*)a == *(int*)b) { +int int_cmp(gconstpointer a, gconstpointer b) +{ + int int_a = *(int *)a; + int int_b = *(int *)b; + if (int_a == int_b) { return 0; - } - else { + } else { return 1; } } -int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces) { +int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) +{ int nr_address_spaces = cpu->num_ases; mcd_mem_space_st space1 = { @@ -1117,7 +1166,7 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces) { }; g_array_append_vals(memspaces, (gconstpointer)&space2, 1); - if (nr_address_spaces==2) { + if (nr_address_spaces == 2) { mcd_mem_space_st space3 = { .name = "Secure", .id = 3, @@ -1143,7 +1192,7 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces) { }; g_array_append_vals(memspaces, (gconstpointer)&space4, 1); } - // TODO: get dynamically how the per (CP15) space is called + /* TODO: get dynamically how the per (CP15) space is called */ mcd_mem_space_st space5 = { .name = "GPR Registers", .id = 5, @@ -1172,7 +1221,8 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces) { return 0; } -int init_resets(GArray* resets) { +int init_resets(GArray *resets) +{ mcd_reset_st system_reset = { .id = 0, .name = RESET_SYSTEM}; mcd_reset_st gpr_reset = { .id = 1, .name = RESET_GPR}; mcd_reset_st memory_reset = { .id = 2, .name = RESET_MEMORY}; @@ -1182,32 +1232,41 @@ int init_resets(GArray* resets) { return 0; } -int init_trigger(mcd_trigger_st* trigger) { - trigger->type = (MCD_TRIG_TYPE_IP | MCD_TRIG_TYPE_READ | MCD_TRIG_TYPE_WRITE | MCD_TRIG_TYPE_RW); +int init_trigger(mcd_trigger_st *trigger) +{ + trigger->type = (MCD_TRIG_TYPE_IP | MCD_TRIG_TYPE_READ | + MCD_TRIG_TYPE_WRITE | MCD_TRIG_TYPE_RW); trigger->option = (MCD_TRIG_OPT_DATA_IS_CONDITION); trigger->action = (MCD_TRIG_ACTION_DBG_DEBUG); trigger->nr_trigger = 4; return 0; } -void handle_open_server(GArray *params, void *user_ctx) { - // initialize core-independent data +void handle_open_server(GArray *params, void *user_ctx) +{ + /* initialize core-independent data */ int return_value = 0; mcdserver_state.resets = g_array_new(false, true, sizeof(mcd_reset_st)); return_value = init_resets(mcdserver_state.resets); - if (return_value!=0) assert(0); + if (return_value != 0) { + g_assert_not_reached(); + } return_value = init_trigger(&mcdserver_state.trigger); - if (return_value!=0) assert(0); + if (return_value != 0) { + g_assert_not_reached(); + } - mcd_put_packet(TCP_HANDSHAKE_SUCCESS); + mcd_put_packet(TCP_HANDSHAKE_SUCCESS); } -void handle_query_system(GArray *params, void *user_ctx) { +void handle_query_system(GArray *params, void *user_ctx) +{ mcd_put_packet(MCD_SYSTEM_NAME); } -void handle_query_cores(GArray *params, void *user_ctx) { - // get first cpu +void handle_query_cores(GArray *params, void *user_ctx) +{ + /* get first cpu */ CPUState *cpu = mcd_first_attached_cpu(); if (!cpu) { return; @@ -1218,123 +1277,136 @@ void handle_query_cores(GArray *params, void *user_ctx) { CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - + int nr_cores = cpu->nr_cores; char device_name[] = DEVICE_NAME_TEMPLATE(arch); g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%s.%s=%d.", - TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_ARGUMENT_AMOUNT_CORE, nr_cores); + TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, + TCP_ARGUMENT_AMOUNT_CORE, nr_cores); mcd_put_strbuf(); g_free(arch); } -int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray* reggroups, GArray* registers, int* current_group_id) { +int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray *reggroups, + GArray *registers, int *current_group_id) +{ const char *xml_filename = NULL; const char *current_xml_filename = NULL; const char *xml_content = NULL; int i = 0; - // 1. get correct file + /* 1. get correct file */ xml_filename = cc->gdb_core_xml_file; for (i = 0; ; i++) { current_xml_filename = xml_builtin[i][0]; - if (!current_xml_filename || (strncmp(current_xml_filename, xml_filename, strlen(xml_filename)) == 0 + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) == 0 && strlen(current_xml_filename) == strlen(xml_filename))) - break; + break; } - // without gpr registers we can do nothing + /* without gpr registers we can do nothing */ if (!current_xml_filename) { return -1; } - // 2. add group for gpr registers - mcd_reg_group_st gprregs = { .name = "GPR Registers", .id = *current_group_id }; + /* 2. add group for gpr registers */ + mcd_reg_group_st gprregs = { + .name = "GPR Registers", + .id = *current_group_id + }; g_array_append_vals(reggroups, (gconstpointer)&gprregs, 1); *current_group_id = *current_group_id + 1; - // 3. parse xml + /* 3. parse xml */ xml_content = xml_builtin[i][1]; parse_reg_xml(xml_content, strlen(xml_content), registers); return 0; } -int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray* registers, int* current_group_id) { +int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray *reggroups, + GArray *registers, int *current_group_id) { const char *xml_filename = NULL; const char *current_xml_filename = NULL; const char *xml_content = NULL; int i = 0; - // iterate over all gdb xml files + /* iterate over all gdb xml files*/ GDBRegisterState *r; for (r = cpu->gdb_regs; r; r = r->next) { xml_filename = r->xml; xml_content = NULL; - // 1. get xml content + /* 1. get xml content */ xml_content = arm_mcd_get_dynamic_xml(cpu, xml_filename); if (xml_content) { - if (strcmp(xml_filename, "system-registers.xml")==0) { - // these are the coprocessor register - mcd_reg_group_st corprocessorregs = { .name = "CP15 Registers", .id = *current_group_id }; - g_array_append_vals(reggroups, (gconstpointer)&corprocessorregs, 1); + if (strcmp(xml_filename, "system-registers.xml") == 0) { + /* these are the coprocessor register */ + mcd_reg_group_st corprocessorregs = { + .name = "CP15 Registers", + .id = *current_group_id + }; + g_array_append_vals(reggroups, + (gconstpointer)&corprocessorregs, 1); *current_group_id = *current_group_id + 1; - } - } - else { - // its not a coprocessor xml -> it is a static xml file + } + } else { + /* its not a coprocessor xml -> it is a static xml file */ for (i = 0; ; i++) { current_xml_filename = xml_builtin[i][0]; - if (!current_xml_filename || (strncmp(current_xml_filename, xml_filename, strlen(xml_filename)) == 0 + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) == 0 && strlen(current_xml_filename) == strlen(xml_filename))) - break; + break; } if (current_xml_filename) { xml_content = xml_builtin[i][1]; - } - else { - printf("no data found for %s\n", xml_filename); + } else { continue; } } - // 2. parse xml + /* 2. parse xml */ parse_reg_xml(xml_content, strlen(xml_content), registers); } return 0; } -int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers) { +int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers) +{ GList *register_numbers = NULL; mcd_reg_st *current_register; int i = 0; int id_neg_offset = 0; int effective_id = 0; - // iterate over all registers + /* iterate over all registers */ for (i = 0; i < registers->len; i++) { current_register = &(g_array_index(registers, mcd_reg_st, i)); - // 1. ad the id + /* 1. ad the id */ if (current_register->id) { - // id is already in place - // NOTE: qemu doesn't emulate the FPA regs (so we are missing the indices 16 to 24) + /* + *id is already in place + *NOTE: qemu doesn't emulate the FPA regs + *(so we are missing the indices 16 to 24) + */ int used_id = current_register->id; register_numbers = g_list_append(register_numbers, &used_id); - id_neg_offset ++; - } - else { + id_neg_offset++; + } else { effective_id = i - id_neg_offset; - if (g_list_find_custom(register_numbers, &effective_id, (GCompareFunc)int_cmp)!=NULL) { - id_neg_offset --; + if (g_list_find_custom(register_numbers, &effective_id, + (GCompareFunc)int_cmp) != NULL) { + id_neg_offset--; } current_register->id = i - id_neg_offset; } - // 2. add mcd_reg_group_id and mcd_mem_space_id - if (strcmp(current_register->group, "cp_regs")==0) { - // coprocessor registers + /* 2. add mcd_reg_group_id and mcd_mem_space_id */ + if (strcmp(current_register->group, "cp_regs") == 0) { + /* coprocessor registers */ current_register->mcd_reg_group_id = 2; current_register->mcd_mem_space_id = 6; - // TODO: get info for opcode - } - else { - // gpr register + /* TODO: get info for opcode */ + } else { + /* gpr register */ current_register->mcd_reg_group_id = 1; current_register->mcd_mem_space_id = 5; } @@ -1343,7 +1415,8 @@ int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers) { return 0; } -void handle_open_core(GArray *params, void *user_ctx) { +void handle_open_core(GArray *params, void *user_ctx) +{ uint32_t cpu_id = get_param(params, 0)->cpu_id; CPUState *cpu = mcd_get_cpu(cpu_id); mcdserver_state.c_cpu = cpu; @@ -1351,315 +1424,373 @@ void handle_open_core(GArray *params, void *user_ctx) { gchar *arch = cc->gdb_arch_name(cpu); int return_value = 0; - // prepare data strucutures - GArray* memspaces = g_array_new(false, true, sizeof(mcd_mem_space_st)); - GArray* reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); - GArray* registers = g_array_new(false, true, sizeof(mcd_reg_st)); - - if (strcmp(arch, "arm")==0) { - // TODO: make group and memspace ids dynamic + /* prepare data strucutures */ + GArray *memspaces = g_array_new(false, true, sizeof(mcd_mem_space_st)); + GArray *reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); + GArray *registers = g_array_new(false, true, sizeof(mcd_reg_st)); + + if (strcmp(arch, "arm") == 0) { + /* TODO: make group and memspace ids dynamic */ int current_group_id = 1; - // 1. store mem spaces + /* 1. store mem spaces */ return_value = mcd_arm_store_mem_spaces(cpu, memspaces); - if (return_value!=0) assert(0); - // 2. parse core xml - return_value = mcd_arm_parse_core_xml_file(cc, reggroups, registers, ¤t_group_id); - if (return_value!=0) assert(0); - // 3. parse other xmls - return_value = mcd_arm_parse_general_xml_files(cpu, reggroups, registers, ¤t_group_id); - if (return_value!=0) assert(0); - // 4. add additional data the the regs from the xmls - return_value = mcd_arm_get_additional_register_info(reggroups, registers); - if (return_value!=0) assert(0); - // 5. store all found data + if (return_value != 0) { + g_assert_not_reached(); + } + /* 2. parse core xml */ + return_value = mcd_arm_parse_core_xml_file(cc, reggroups, + registers, ¤t_group_id); + if (return_value != 0) { + g_assert_not_reached(); + } + /* 3. parse other xmls */ + return_value = mcd_arm_parse_general_xml_files(cpu, reggroups, + registers, ¤t_group_id); + if (return_value != 0) { + g_assert_not_reached(); + } + /* 4. add additional data the the regs from the xmls */ + return_value = mcd_arm_get_additional_register_info(reggroups, + registers); + if (return_value != 0) { + g_assert_not_reached(); + } + /* 5. store all found data */ if (g_list_nth(mcdserver_state.all_memspaces, cpu_id)) { - GList* memspaces_ptr = g_list_nth(mcdserver_state.all_memspaces, cpu_id); + GList *memspaces_ptr = + g_list_nth(mcdserver_state.all_memspaces, cpu_id); memspaces_ptr->data = memspaces; - } - else { - mcdserver_state.all_memspaces = g_list_insert(mcdserver_state.all_memspaces, memspaces, cpu_id); + } else { + mcdserver_state.all_memspaces = + g_list_insert(mcdserver_state.all_memspaces, memspaces, cpu_id); } if (g_list_nth(mcdserver_state.all_reggroups, cpu_id)) { - GList* reggroups_ptr = g_list_nth(mcdserver_state.all_reggroups, cpu_id); + GList *reggroups_ptr = + g_list_nth(mcdserver_state.all_reggroups, cpu_id); reggroups_ptr->data = reggroups; - } - else { - mcdserver_state.all_reggroups = g_list_insert(mcdserver_state.all_reggroups, reggroups, cpu_id); + } else { + mcdserver_state.all_reggroups = + g_list_insert(mcdserver_state.all_reggroups, reggroups, cpu_id); } if (g_list_nth(mcdserver_state.all_registers, cpu_id)) { - GList* registers_ptr = g_list_nth(mcdserver_state.all_registers, cpu_id); + GList *registers_ptr = + g_list_nth(mcdserver_state.all_registers, cpu_id); registers_ptr->data = registers; + } else { + mcdserver_state.all_registers = + g_list_insert(mcdserver_state.all_registers, registers, cpu_id); } - else { - mcdserver_state.all_registers = g_list_insert(mcdserver_state.all_registers, registers, cpu_id); - } - } - else { - // we don't support other architectures - assert(0); + } else { + /* we don't support other architectures */ + g_assert_not_reached(); } g_free(arch); } -void handle_query_reset_f(GArray *params, void *user_ctx) { - // TODO: vull reset over the qemu monitor - - // 1. check length +void handle_query_reset_f(GArray *params, void *user_ctx) +{ + /* TODO: vull reset over the qemu monitor */ + + /* 1. check length */ int nb_resets = mcdserver_state.resets->len; if (nb_resets == 1) { - // indicates this is the last packet + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { + } else { g_string_printf(mcdserver_state.str_buf, "1!"); } - // 2. send data + /* 2. send data */ mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", + TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); } -void handle_query_reset_c(GArray *params, void *user_ctx) { - // reset options are the same for every cpu! +void handle_query_reset_c(GArray *params, void *user_ctx) +{ + /* reset options are the same for every cpu! */ int query_index = get_param(params, 0)->query_handle; - - // 1. check weather this was the last mem space + + /* 1. check weather this was the last mem space */ int nb_groups = mcdserver_state.resets->len; - if (query_index+1 == nb_groups) { - // indicates this is the last packet + if (query_index + 1 == nb_groups) { + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); + } else { + g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); } - // 2. send data - mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); + /* 2. send data */ + mcd_reset_st reset = g_array_index(mcdserver_state.resets, + mcd_reset_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", + TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); } -void handle_close_core(GArray *params, void *user_ctx) { - // free memory for correct core +void handle_close_core(GArray *params, void *user_ctx) +{ + /* free memory for correct core */ uint32_t cpu_id = get_param(params, 0)->cpu_id; - GArray* memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); - mcdserver_state.all_memspaces = g_list_remove(mcdserver_state.all_memspaces, memspaces); + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcdserver_state.all_memspaces = + g_list_remove(mcdserver_state.all_memspaces, memspaces); g_array_free(memspaces, TRUE); - GArray* reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); - mcdserver_state.all_reggroups = g_list_remove(mcdserver_state.all_reggroups, reggroups); + GArray *reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + mcdserver_state.all_reggroups = + g_list_remove(mcdserver_state.all_reggroups, reggroups); g_array_free(reggroups, TRUE); - GArray* registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); - mcdserver_state.all_registers = g_list_remove(mcdserver_state.all_registers, registers); + GArray *registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + mcdserver_state.all_registers = + g_list_remove(mcdserver_state.all_registers, registers); g_array_free(registers, TRUE); } -void handle_close_server(GArray *params, void *user_ctx) { +void handle_close_server(GArray *params, void *user_ctx) +{ uint32_t pid = 1; MCDProcess *process = mcd_get_process(pid); - // 1. free memory - // TODO: do this only if there are no processes attached anymore! + /* + * 1. free memory + * TODO: do this only if there are no processes attached anymore! + */ g_list_free(mcdserver_state.all_memspaces); g_list_free(mcdserver_state.all_reggroups); g_list_free(mcdserver_state.all_registers); g_array_free(mcdserver_state.resets, TRUE); - // 2. detach + /* 2. detach */ process->attached = false; - // 3. reset process + /* 3. reset process */ if (pid == mcd_get_cpu_pid(mcdserver_state.c_cpu)) { mcdserver_state.c_cpu = mcd_first_attached_cpu(); } if (!mcdserver_state.c_cpu) { - // no more processes attached + /* no more processes attached */ mcd_disable_syscalls(); mcd_vm_start(); } } -void handle_query_trigger(GArray *params, void *user_ctx) { +void handle_query_trigger(GArray *params, void *user_ctx) +{ mcd_trigger_st trigger = mcdserver_state.trigger; g_string_printf(mcdserver_state.str_buf, "%s=%d.%s=%d.%s=%d.%s=%d.", - TCP_ARGUMENT_AMOUNT_TRIGGER, trigger.nr_trigger, TCP_ARGUMENT_TYPE, trigger.type, - TCP_ARGUMENT_OPTION, trigger.option, TCP_ARGUMENT_ACTION, trigger.action); + TCP_ARGUMENT_AMOUNT_TRIGGER, trigger.nr_trigger, + TCP_ARGUMENT_TYPE, trigger.type, TCP_ARGUMENT_OPTION, trigger.option, + TCP_ARGUMENT_ACTION, trigger.action); mcd_put_strbuf(); } -void mcd_vm_start(void) { +void mcd_vm_start(void) +{ if (!runstate_needs_reset() && !runstate_is_running()) { vm_start(); } } -int mcd_vm_sstep(CPUState *cpu) { +int mcd_vm_sstep(CPUState *cpu) +{ cpu_single_step(mcdserver_state.c_cpu, mcdserver_state.sstep_flags); mcd_vm_start(); return 0; } -void mcd_vm_stop(void) { +void mcd_vm_stop(void) +{ if (runstate_is_running()) { vm_stop(RUN_STATE_DEBUG); } } -void handle_query_mem_spaces_f(GArray *params, void *user_ctx) { - // 1. get correct memspaces and set the query_cpu +void handle_query_mem_spaces_f(GArray *params, void *user_ctx) +{ + /* 1. get correct memspaces and set the query_cpu */ uint32_t cpu_id = get_param(params, 0)->cpu_id; mcdserver_state.query_cpu_id = cpu_id; - GArray* memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); - // 2. check length + /* 2. check length */ int nb_groups = memspaces->len; if (nb_groups == 1) { - // indicates this is the last packet + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { + } else { g_string_printf(mcdserver_state.str_buf, "1!"); } - // 3. send data + /* 3. send data */ mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", - TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, space.id, TCP_ARGUMENT_TYPE, space.type, - TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, TCP_ARGUMENT_ENDIAN, space.endian, - TCP_ARGUMENT_MIN, space.min_addr, TCP_ARGUMENT_MAX, space.max_addr, - TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_options); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", + TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, space.id, + TCP_ARGUMENT_TYPE, space.type, TCP_ARGUMENT_BITS_PER_MAU, + space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, + TCP_ARGUMENT_ENDIAN, space.endian, TCP_ARGUMENT_MIN, space.min_addr, + TCP_ARGUMENT_MAX, space.max_addr, TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, + space.supported_access_options); mcd_put_strbuf(); } -void handle_query_mem_spaces_c(GArray *params, void *user_ctx) { - // this funcitons send all mem spaces except for the first - // 1. get parameter and memspace +void handle_query_mem_spaces_c(GArray *params, void *user_ctx) +{ + /* + * this funcitons send all mem spaces except for the first + * 1. get parameter and memspace + */ int query_index = get_param(params, 0)->query_handle; uint32_t cpu_id = mcdserver_state.query_cpu_id; - GArray* memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); - // 2. check weather this was the last mem space + /* 2. check weather this was the last mem space */ int nb_groups = memspaces->len; - if (query_index+1 == nb_groups) { - // indicates this is the last packet + if (query_index + 1 == nb_groups) { + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); - } - - // 3. send the correct memspace - mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", - TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, space.id, TCP_ARGUMENT_TYPE, space.type, - TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, TCP_ARGUMENT_ENDIAN, space.endian, - TCP_ARGUMENT_MIN, space.min_addr, TCP_ARGUMENT_MAX, space.max_addr, - TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_options); + } else { + g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); + } + + /* 3. send the correct memspace */ + mcd_mem_space_st space = g_array_index(memspaces, + mcd_mem_space_st, query_index); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", + TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, + space.id, TCP_ARGUMENT_TYPE, space.type, TCP_ARGUMENT_BITS_PER_MAU, + space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, + TCP_ARGUMENT_ENDIAN, space.endian, TCP_ARGUMENT_MIN, space.min_addr, + TCP_ARGUMENT_MAX, space.max_addr, TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, + space.supported_access_options); mcd_put_strbuf(); } -void handle_query_reg_groups_f(GArray *params, void *user_ctx) { - // 1. get correct reggroups and set the query_cpu +void handle_query_reg_groups_f(GArray *params, void *user_ctx) +{ + /* 1. get correct reggroups and set the query_cpu */ uint32_t cpu_id = get_param(params, 0)->cpu_id; mcdserver_state.query_cpu_id = cpu_id; - GArray* reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + GArray *reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); - // 2. check length + /* 2. check length */ int nb_groups = reggroups->len; if (nb_groups == 1) { - // indicates this is the last packet + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { + } else { g_string_printf(mcdserver_state.str_buf, "1!"); } - // 3. send data + /* 3. send data */ mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); + g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", + TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); mcd_put_strbuf(); } -void handle_query_reg_groups_c(GArray *params, void *user_ctx) { - // this funcitons send all reg groups except for the first - // 1. get parameter and memspace +void handle_query_reg_groups_c(GArray *params, void *user_ctx) +{ + /* + * this funcitons send all reg groups except for the first + * 1. get parameter and memspace + */ int query_index = get_param(params, 0)->query_handle; uint32_t cpu_id = mcdserver_state.query_cpu_id; - GArray* reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); + GArray *reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); - // 2. check weather this was the last reg group + /* 2. check weather this was the last reg group */ int nb_groups = reggroups->len; - if (query_index+1 == nb_groups) { - // indicates this is the last packet + if (query_index + 1 == nb_groups) { + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); + } else { + g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); } - // 3. send the correct reggroup - mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); + /* 3. send the correct reggroup */ + mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, + query_index); + g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", + TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); mcd_put_strbuf(); } -void handle_query_regs_f(GArray *params, void *user_ctx) { - // 1. get correct registers and set the query_cpu +void handle_query_regs_f(GArray *params, void *user_ctx) +{ + /* 1. get correct registers and set the query_cpu */ uint32_t cpu_id = get_param(params, 0)->cpu_id; mcdserver_state.query_cpu_id = cpu_id; - GArray* registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + GArray *registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); - // 2. check length + /* 2. check length */ int nb_regs = registers->len; if (nb_regs == 1) { - // indicates this is the last packet + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { + } else { g_string_printf(mcdserver_state.str_buf, "1!"); } - // 3. send data + /* 3. send data */ mcd_reg_st my_register = g_array_index(registers, mcd_reg_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", - TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, - TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, - TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", + TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, + my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, + TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, + TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, + TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, + TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); mcd_put_strbuf(); } -void handle_query_regs_c(GArray *params, void *user_ctx) { - // this funcitons send all regs except for the first - // 1. get parameter and registers +void handle_query_regs_c(GArray *params, void *user_ctx) +{ + /* + * this funcitons send all regs except for the first + * 1. get parameter and registers + */ int query_index = get_param(params, 0)->query_handle; uint32_t cpu_id = mcdserver_state.query_cpu_id; - GArray* registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); + GArray *registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); - // 2. check weather this was the last register + /* 2. check weather this was the last register */ int nb_regs = registers->len; - if (query_index+1 == nb_regs) { - // indicates this is the last packet + if (query_index + 1 == nb_regs) { + /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); - } - else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index+1); + } else { + g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); } - // 3. send the correct register + /* 3. send the correct register */ mcd_reg_st my_register = g_array_index(registers, mcd_reg_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", - TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, - TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, - TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); + g_string_append_printf(mcdserver_state.str_buf, + "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", + TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, + my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, + TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, + TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, + TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, + TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); mcd_put_strbuf(); } -void handle_reset(GArray *params, void *user_ctx) { - //int reset_id = get_param(params, 0)->data_int; - // TODO: implement resets +void handle_reset(GArray *params, void *user_ctx) +{ + /* + * int reset_id = get_param(params, 0)->data_int; + * TODO: implement resets + */ } -void handle_query_state(GArray *params, void *user_ctx) { - // TODO: multicore support - // get state info +void handle_query_state(GArray *params, void *user_ctx) +{ + /* + * TODO: multicore support + * get state info + */ mcd_cpu_state_st state_info = mcdserver_state.cpu_state; mcd_core_event_et event = MCD_CORE_EVENT_NONE; if (state_info.memory_changed) { @@ -1674,42 +1805,47 @@ void handle_query_state(GArray *params, void *user_ctx) { event = event | MCD_CORE_EVENT_STOPPED; state_info.target_was_stopped = false; } - // send data - g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.%s=%d.%s=%d.%s=%s.%s=%s.", TCP_ARGUMENT_STATE, state_info.state, - TCP_ARGUMENT_EVENT, event, TCP_ARGUMENT_THREAD, 0, TCP_ARGUMENT_TRIGGER_ID, state_info.trig_id, - TCP_ARGUMENT_STOP_STRING, state_info.stop_str, TCP_ARGUMENT_INFO_STRING, state_info.info_str); + /* send data */ + g_string_printf(mcdserver_state.str_buf, + "%s=%s.%s=%d.%s=%d.%s=%d.%s=%s.%s=%s.", + TCP_ARGUMENT_STATE, state_info.state, + TCP_ARGUMENT_EVENT, event, TCP_ARGUMENT_THREAD, 0, + TCP_ARGUMENT_TRIGGER_ID, state_info.trig_id, + TCP_ARGUMENT_STOP_STRING, state_info.stop_str, + TCP_ARGUMENT_INFO_STRING, state_info.info_str); mcd_put_strbuf(); } -int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) { +int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) +{ CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - if (strcmp(arch, "arm")==0) { + if (strcmp(arch, "arm") == 0) { g_free(arch); return arm_mcd_read_register(cpu, buf, reg); - } - else { + } else { g_free(arch); return 0; } } -int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg) { +int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg) +{ CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - if (strcmp(arch, "arm")==0) { + if (strcmp(arch, "arm") == 0) { g_free(arch); return arm_mcd_write_register(cpu, buf, reg); - } - else { + } else { g_free(arch); return 0; } } -void mcd_memtohex(GString *buf, const uint8_t *mem, int len) { +void mcd_memtohex(GString *buf, const uint8_t *mem, int len) +{ int i, c; - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { c = mem[i]; g_string_append_c(buf, tohex(c >> 4)); g_string_append_c(buf, tohex(c & 0xf)); @@ -1717,45 +1853,50 @@ void mcd_memtohex(GString *buf, const uint8_t *mem, int len) { g_string_append_c(buf, '\0'); } -void mcd_hextomem(GByteArray *mem, const char *buf, int len) { +void mcd_hextomem(GByteArray *mem, const char *buf, int len) +{ int i; - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { guint8 byte = fromhex(buf[0]) << 4 | fromhex(buf[1]); g_byte_array_append(mem, &byte, 1); buf += 2; } } -void handle_read_register(GArray *params, void *user_ctx) { +void handle_read_register(GArray *params, void *user_ctx) +{ uint32_t cpu_id = get_param(params, 0)->cpu_id; uint64_t reg_num = get_param(params, 1)->data_int; int reg_size; CPUState *cpu = mcd_get_cpu(cpu_id); reg_size = mcd_read_register(cpu, mcdserver_state.mem_buf, reg_num); - mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, reg_size); + mcd_memtohex(mcdserver_state.str_buf, + mcdserver_state.mem_buf->data, reg_size); mcd_put_strbuf(); } -void handle_write_register(GArray *params, void *user_ctx) { +void handle_write_register(GArray *params, void *user_ctx) +{ uint32_t cpu_id = get_param(params, 0)->cpu_id; uint64_t reg_num = get_param(params, 1)->data_int; uint32_t reg_size = get_param(params, 2)->data_int; CPUState *cpu = mcd_get_cpu(cpu_id); - mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, reg_size); - if (mcd_write_register(cpu, mcdserver_state.mem_buf, reg_num)==0) { + mcd_hextomem(mcdserver_state.mem_buf, + mcdserver_state.str_buf->str, reg_size); + if (mcd_write_register(cpu, mcdserver_state.mem_buf, reg_num) == 0) { mcd_put_packet(TCP_EXECUTION_ERROR); - } - else { + } else { mcd_put_packet(TCP_EXECUTION_SUCCESS); } } -int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { +int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) +{ CPUClass *cc; - //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); + /*TODO: add physical mem cpu_physical_memory_read(addr, buf, len); */ cc = CPU_GET_CLASS(cpu); if (cc->memory_rw_debug) { return cc->memory_rw_debug(cpu, addr, buf, len, false); @@ -1764,9 +1905,10 @@ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { return cpu_memory_rw_debug(cpu, addr, buf, len, false); } -int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { +int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) +{ CPUClass *cc; - //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); + /*TODO: add physical mem cpu_physical_memory_read(addr, buf, len); */ cc = CPU_GET_CLASS(cpu); if (cc->memory_rw_debug) { return cc->memory_rw_debug(cpu, addr, buf, len, true); @@ -1775,33 +1917,36 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) { return cpu_memory_rw_debug(cpu, addr, buf, len, true); } -void handle_read_memory(GArray *params, void *user_ctx) { +void handle_read_memory(GArray *params, void *user_ctx) +{ uint32_t cpu_id = get_param(params, 0)->cpu_id; uint64_t mem_address = get_param(params, 1)->data_uint64_t; int len = get_param(params, 2)->data_int; CPUState *cpu = mcd_get_cpu(cpu_id); g_byte_array_set_size(mcdserver_state.mem_buf, len); - if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len)!=0) { + if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf->data, + mcdserver_state.mem_buf->len) != 0) { mcd_put_packet(TCP_EXECUTION_ERROR); - } - else { - mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len); + } else { + mcd_memtohex(mcdserver_state.str_buf, mcdserver_state.mem_buf->data, + mcdserver_state.mem_buf->len); mcd_put_strbuf(); } } -void handle_write_memory(GArray *params, void *user_ctx) { +void handle_write_memory(GArray *params, void *user_ctx) +{ uint32_t cpu_id = get_param(params, 0)->cpu_id; uint64_t mem_address = get_param(params, 1)->data_uint64_t; int len = get_param(params, 2)->data_int; CPUState *cpu = mcd_get_cpu(cpu_id); mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, len); - if (mcd_write_memory(cpu, mem_address, mcdserver_state.mem_buf->data, len)!=0) { + if (mcd_write_memory(cpu, mem_address, + mcdserver_state.mem_buf->data, len) != 0) { mcd_put_packet(TCP_EXECUTION_ERROR); - } - else { + } else { mcd_put_packet(TCP_EXECUTION_SUCCESS); } } diff --git a/mcdstub/internals.h b/mcdstub/mcdstub.h similarity index 69% rename from mcdstub/internals.h rename to mcdstub/mcdstub.h index 0afab434ce..83156dceb8 100644 --- a/mcdstub/internals.h +++ b/mcdstub/mcdstub.h @@ -4,49 +4,46 @@ #include "exec/cpu-common.h" #include "chardev/char.h" #include "hw/core/cpu.h" -// just used for the register xml files +/* just used for the register xml files */ #include "exec/gdbstub.h" #define MAX_PACKET_LENGTH 1024 -// trigger defines +/* trigger defines */ #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 typedef uint32_t mcd_trig_type_et; -// TODO: replace mcd defines with custom layer +/* TODO: replace mcd defines with custom layer */ enum { - MCD_TRIG_TYPE_UNDEFINED = 0x00000000, /**< Undefined trigger type. */ - MCD_TRIG_TYPE_IP = 0x00000001, /**< Trigger on a changing instruction pointer. */ - MCD_TRIG_TYPE_READ = 0x00000002, /**< Trigger on a read data access to a specific address or address range. */ - MCD_TRIG_TYPE_WRITE = 0x00000004, /**< Trigger on a write data access to a specific address or address range. */ - MCD_TRIG_TYPE_RW = 0x00000008, /**< Trigger on a read or a write data access to a specific address or - address range. */ - MCD_TRIG_TYPE_NOCYCLE = 0x00000010, /**< Trigger on core information other than an IP or data compare trigger. */ - MCD_TRIG_TYPE_TRIG_BUS = 0x00000020, /**< Trigger on a trigger bus combination. */ - MCD_TRIG_TYPE_COUNTER = 0x00000040, /**< Trigger on an elapsed trigger counter. */ - MCD_TRIG_TYPE_CUSTOM = 0x00000080, /**< Custom trigger using standard format as defined by \ref mcd_trig_custom_st. */ - MCD_TRIG_TYPE_CUSTOM_LO = 0x00010000, /**< Begin Range: User defined trigger types. */ - MCD_TRIG_TYPE_CUSTOM_HI = 0x40000000, /**< End Range: User defined trigger types. */ + MCD_TRIG_TYPE_UNDEFINED = 0x00000000, + MCD_TRIG_TYPE_IP = 0x00000001, + MCD_TRIG_TYPE_READ = 0x00000002, + MCD_TRIG_TYPE_WRITE = 0x00000004, + MCD_TRIG_TYPE_RW = 0x00000008, + MCD_TRIG_TYPE_NOCYCLE = 0x00000010, + MCD_TRIG_TYPE_TRIG_BUS = 0x00000020, + MCD_TRIG_TYPE_COUNTER = 0x00000040, + MCD_TRIG_TYPE_CUSTOM = 0x00000080, + MCD_TRIG_TYPE_CUSTOM_LO = 0x00010000, + MCD_TRIG_TYPE_CUSTOM_HI = 0x40000000, }; typedef uint32_t mcd_core_event_et; -// TODO: replace mcd defines with custom layer +/* TODO: replace mcd defines with custom layer */ enum { - MCD_CORE_EVENT_NONE = 0x00000000, /**< No since the last poll. */ - MCD_CORE_EVENT_MEMORY_CHANGE = 0x00000001, /**< Memory content has changed. */ - MCD_CORE_EVENT_REGISTER_CHANGE = 0x00000002, /**< Register contents have changed. */ - MCD_CORE_EVENT_TRACE_CHANGE = 0x00000004, /**< Trace contents or states have changed. */ - MCD_CORE_EVENT_TRIGGER_CHANGE = 0x00000008, /**< Triggers or trigger states have changed. */ - MCD_CORE_EVENT_STOPPED = 0x00000010, /**< Target was stopped at least once since the last poll, - it may already be running again. */ - MCD_CORE_EVENT_CHL_PENDING = 0x00000020, /**< A target communication channel request from the target - is pending. */ - MCD_CORE_EVENT_CUSTOM_LO = 0x00010000, /**< Begin Range: User defined core events. */ - MCD_CORE_EVENT_CUSTOM_HI = 0x40000000, /**< End Range: User defined core events. */ + MCD_CORE_EVENT_NONE = 0x00000000, + MCD_CORE_EVENT_MEMORY_CHANGE = 0x00000001, + MCD_CORE_EVENT_REGISTER_CHANGE = 0x00000002, + MCD_CORE_EVENT_TRACE_CHANGE = 0x00000004, + MCD_CORE_EVENT_TRIGGER_CHANGE = 0x00000008, + MCD_CORE_EVENT_STOPPED = 0x00000010, + MCD_CORE_EVENT_CHL_PENDING = 0x00000020, + MCD_CORE_EVENT_CUSTOM_LO = 0x00010000, + MCD_CORE_EVENT_CUSTOM_HI = 0x40000000, }; -// schema defines +/* schema defines */ #define ARG_SCHEMA_QRYHANDLE 'q' #define ARG_SCHEMA_STRING 's' #define ARG_SCHEMA_INT 'd' @@ -54,20 +51,20 @@ enum { #define ARG_SCHEMA_CORENUM 'c' #define ARG_SCHEMA_HEXDATA 'h' -// resets +/* resets */ #define RESET_SYSTEM "full_system_reset" #define RESET_GPR "gpr_reset" #define RESET_MEMORY "memory_reset" -// misc -#define QUERY_TOTAL_NUMBER 12 +/* misc */ +#define QUERY_TOTAL_NUMBER 12 #define CMD_SCHEMA_LENGTH 5 #define MCD_SYSTEM_NAME "qemu-system" -// tcp query packet values templates +/* tcp query packet values templates */ #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" -// state strings +/* state strings */ #define STATE_STR_UNKNOWN(d) "cpu " #d " in unknown state" #define STATE_STR_DEBUG(d) "cpu " #d " in debug state" #define STATE_STR_RUNNING(d) "cpu " #d " running" @@ -82,7 +79,7 @@ enum { #define STATE_STR_BREAK_UNKNOWN "stopped for unknown reason" typedef struct GDBRegisterState { - // needed for the used gdb functions + /* needed for the used gdb functions */ int base_reg; int num_regs; gdb_get_reg_cb get_reg; @@ -193,22 +190,22 @@ typedef struct xml_attrib { } xml_attrib; typedef struct mcd_reg_st { - // xml info + /* xml info */ char name[64]; char group[64]; char type[64]; uint32_t bitsize; uint32_t id; - // mcd metadata + /* mcd metadata */ uint32_t mcd_reg_group_id; uint32_t mcd_mem_space_id; uint32_t mcd_reg_type; uint32_t mcd_hw_thread_id; - // data for op-code + /* data for op-code */ uint8_t cp; uint8_t crn; uint8_t crm; - uint8_t opc0; // <- might not be needed! + uint8_t opc0; /* <- might not be needed! */ uint8_t opc1; uint8_t opc2; } mcd_reg_st; @@ -245,9 +242,9 @@ void mcd_sigterm_handler(int signal); #endif void mcd_init_mcdserver_state(void); -void init_query_cmds_table(MCDCmdParseEntry* mcd_query_cmds_table); -int init_resets(GArray* resets); -int init_trigger(mcd_trigger_st* trigger); +void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table); +int init_resets(GArray *resets); +int init_trigger(mcd_trigger_st *trigger); void reset_mcdserver_state(void); void create_processes(MCDState *s); void mcd_create_default_process(MCDState *s); @@ -272,14 +269,15 @@ int mcd_handle_packet(const char *line_buf); void mcd_put_strbuf(void); void mcd_exit(int code); void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd); -int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds); +int process_string_cmd(void *user_ctx, const char *data, + const MCDCmdParseEntry *cmds, int num_cmds); int cmd_parse_params(const char *data, const char *schema, GArray *params); void handle_vm_start(GArray *params, void *user_ctx); void handle_vm_step(GArray *params, void *user_ctx); void handle_vm_stop(GArray *params, void *user_ctx); void handle_gen_query(GArray *params, void *user_ctx); int mcd_get_cpu_index(CPUState *cpu); -CPUState* mcd_get_cpu(uint32_t i_cpu_index); +CPUState *mcd_get_cpu(uint32_t i_cpu_index); void handle_query_cores(GArray *params, void *user_ctx); void handle_query_system(GArray *params, void *user_ctx); CPUState *get_first_cpu_in_process(MCDProcess *process); @@ -312,20 +310,22 @@ int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg); int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); -// arm specific functions -int mcd_arm_store_mem_spaces(CPUState *cpu, GArray* memspaces); -int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray* reggroups, GArray* registers, int* current_group_id); -int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray* registers, int* current_group_id); -int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* registers); +/* arm specific functions */ +int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces); +int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray *reggroups, + GArray *registers, int *current_group_id); +int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, + GArray *registers, int *current_group_id); +int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers); -// sycall handling +/* sycall handling */ void mcd_syscall_reset(void); void mcd_disable_syscalls(void); -// helpers +/* helpers */ int int_cmp(gconstpointer a, gconstpointer b); void mcd_memtohex(GString *buf, const uint8_t *mem, int len); void mcd_hextomem(GByteArray *mem, const char *buf, int len); -uint64_t atouint64_t(const char* in); +uint64_t atouint64_t(const char *in); #endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/meson.build b/mcdstub/meson.build index f17e2f3e89..ebd47b0725 100644 --- a/mcdstub/meson.build +++ b/mcdstub/meson.build @@ -7,19 +7,21 @@ # We need to build the core mcd code via a library to be able to tweak # cflags so: -mcd_softmmu_ss = ss.source_set() +mcd_system_ss = ss.source_set() -# We build one version of the mcdstub, because it only needs to work for system emulation -mcd_softmmu_ss.add(files('mcdstub.c')) +# We build one version of the mcdstub, +#because it only needs to work for system emulation +mcd_system_ss.add(files('mcdstub.c')) -mcd_softmmu_ss = mcd_softmmu_ss.apply(config_host, strict: false) +mcd_system_ss = mcd_system_ss.apply(config_host, strict: false) libmcd_softmmu = static_library('mcd_softmmu', - mcd_softmmu_ss.sources() + genh, - name_suffix: 'fa') + mcd_system_ss.sources() + genh, + name_suffix: 'fa', + build_by_default: have_system) mcd_softmmu = declare_dependency(link_whole: libmcd_softmmu) -softmmu_ss.add(mcd_softmmu) +system_ss.add(mcd_softmmu) # this might cause problems because we don't support user mode common_ss.add(files('mcd_syscalls.c')) diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 6a1c969f3b..0848e0dbdb 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -306,7 +306,7 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - //gdb_set_stop_cpu(cpu); + gdb_set_stop_cpu(cpu); qemu_system_debug_request(); cpu->stopped = true; } diff --git a/softmmu/vl.c b/softmmu/vl.c index 2d66f612a7..085a312f9d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2663,9 +2663,9 @@ static void qemu_machine_creation_done(void) if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { exit(1); } - + if (foreach_device_config(DEV_MCD, mcdserver_start) < 0) { - /* + /* * starts the mcdserver if the mcd option was set */ exit(1); diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index 27e1a13b69..e4e632d3f3 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -8,8 +8,10 @@ static inline int mcd_get_reg32(GByteArray *buf, uint32_t val) { - //TODO: move this to a separate file - // convert endianess if necessary + /* + *TODO: move this to a separate file + *convert endianess if necessary + */ uint32_t to_long = tswap32(val); g_byte_array_append(buf, (uint8_t *) &to_long, 4); return 4; @@ -17,7 +19,7 @@ static inline int mcd_get_reg32(GByteArray *buf, uint32_t val) static inline int mcd_get_zeroes(GByteArray *array, size_t len) { - //TODO: move this to a separate file + /*TODO: move this to a separate file */ guint oldlen = array->len; g_byte_array_set_size(array, oldlen + len); memset(array->data + oldlen, 0, len); @@ -43,7 +45,8 @@ const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname) return NULL; } -int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) { +int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) +{ ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; @@ -52,12 +55,12 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) { return mcd_get_reg32(mem_buf, env->regs[n]); } if (n < 24) { - // TODO: these numbers don't match mine + /* TODO: these numbers don't match mine */ return mcd_get_zeroes(mem_buf, 12); } switch (n) { case 24: - // TODO: these numbers don't match mine + /* TODO: these numbers don't match mine */ return mcd_get_reg32(mem_buf, 0); case 25: /* CPSR, or XPSR for M-profile */ @@ -67,17 +70,18 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) { return mcd_get_reg32(mem_buf, cpsr_read(env)); } } - //TODO: add funcitons for the remaining regs (including cp_regs) + /* TODO: add funcitons for the remaining regs (including cp_regs) */ return 0; } -int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) { +int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) +{ ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; uint32_t tmp; tmp = ldl_p(mem_buf); - tmp = *((uint32_t*)mem_buf->data); + tmp = *((uint32_t *)mem_buf->data); /* * Mask out low bits of PC to workaround gdb bugs. @@ -122,6 +126,6 @@ int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) { } return 4; } - //TODO: add funcitons for the remaining regs (including cp_regs) + /* TODO: add funcitons for the remaining regs (including cp_regs) */ return 0; } From patchwork Fri Oct 6 09:05:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844305 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22gV334Sz20Vp for ; Fri, 6 Oct 2023 20:09:42 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognY-0008Gp-Jd; Fri, 06 Oct 2023 05:07:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognL-0008AB-9W for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:52 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognJ-0000z9-FM for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:50 -0400 Received: (qmail 19743 invoked by uid 484); 6 Oct 2023 09:06:37 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.143277 secs); 06 Oct 2023 09:06:37 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:35 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 16/29] deleting the mcdd startup option Date: Fri, 6 Oct 2023 11:05:57 +0200 Message-Id: <20231006090610.26171-17-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder Signed-off-by: neder --- mcdstub/meson.build | 10 +--------- qemu-options.hx | 13 +++---------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/mcdstub/meson.build b/mcdstub/meson.build index ebd47b0725..6b2f970eae 100644 --- a/mcdstub/meson.build +++ b/mcdstub/meson.build @@ -1,16 +1,9 @@ -# -# The main gdbstub still relies on per-build definitions of various -# types. The bits pushed to softmmu/user.c try to use guest agnostic -# types such as hwaddr. -# - # We need to build the core mcd code via a library to be able to tweak # cflags so: mcd_system_ss = ss.source_set() -# We build one version of the mcdstub, -#because it only needs to work for system emulation +# only system emulation is supported over mcd mcd_system_ss.add(files('mcdstub.c')) mcd_system_ss = mcd_system_ss.apply(config_host, strict: false) @@ -23,5 +16,4 @@ libmcd_softmmu = static_library('mcd_softmmu', mcd_softmmu = declare_dependency(link_whole: libmcd_softmmu) system_ss.add(mcd_softmmu) -# this might cause problems because we don't support user mode common_ss.add(files('mcd_syscalls.c')) diff --git a/qemu-options.hx b/qemu-options.hx index 0c15125b92..0b72c2de07 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4417,7 +4417,8 @@ ERST DEF("mcd", HAS_ARG, QEMU_OPTION_mcd, \ "-mcd dev accept mcd connection on 'dev'. (QEMU defaults to starting\n" " the guest without waiting for a mcd client to connect; use -S too\n" - " if you want it to not start execution.)\n", + " if you want it to not start execution.)\n" + " To use the default Port write '-mcd default'\n", QEMU_ARCH_ALL) SRST ``-mcd dev`` @@ -4428,15 +4429,7 @@ SRST The most usual configuration is to listen on a local TCP socket:: - -mcd tcp::1234 -ERST - -DEF("mcdd", 0, QEMU_OPTION_mcdd, \ - "-mcdd shorthand for -mcd tcp::" DEFAULT_MCDSTUB_PORT "\n", - QEMU_ARCH_ALL) -SRST -``-mcdd`` - Shorthand for -mcd tcp::1234, i.e. open a mcdserver on TCP port 1234 + -mcd tcp::1235 ERST DEF("d", HAS_ARG, QEMU_OPTION_d, \ From patchwork Fri Oct 6 09:05:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844294 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dq5zGyz1yqF for ; Fri, 6 Oct 2023 20:08:15 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogna-0008H0-Rl; Fri, 06 Oct 2023 05:07:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognO-0008DN-SK for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:54 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognL-0000za-T6 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:54 -0400 Received: (qmail 19776 invoked by uid 484); 6 Oct 2023 09:06:40 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.184611 secs); 06 Oct 2023 09:06:40 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:38 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 17/29] handler for breakpoints and watchpoints added Date: Fri, 6 Oct 2023 11:05:58 +0200 Message-Id: <20231006090610.26171-18-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcd_shared_defines.h | 8 +++ mcdstub/mcdstub.c | 124 ++++++++++++++++++++++++++++++++++- mcdstub/mcdstub.h | 4 ++ softmmu/cpus.c | 2 +- 4 files changed, 135 insertions(+), 3 deletions(-) diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 891f6477e7..2e0831594a 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -21,6 +21,8 @@ #define TCP_CHAR_WRITE_REGISTER 'P' #define TCP_CHAR_READ_MEMORY 'm' #define TCP_CHAR_WRITE_MEMORY 'M' +#define TCP_CHAR_BREAKPOINT_INSERT 't' +#define TCP_CHAR_BREAKPOINT_REMOVE 'T' /* tcp protocol chars */ #define TCP_ACKNOWLEDGED '+' @@ -82,4 +84,10 @@ #define CORE_STATE_DEBUG "debug" #define CORE_STATE_UNKNOWN "unknown" +/* breakpoint types */ +#define MCD_BREAKPOINT_HW 1 +#define MCD_BREAKPOINT_READ 2 +#define MCD_BREAKPOINT_WRITE 3 +#define MCD_BREAKPOINT_RW 4 + #endif diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 9f79864af6..4327703bca 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -563,6 +563,32 @@ int mcd_handle_packet(const char *line_buf) cmd_parser = &write_mem_cmd_desc; } break; + case TCP_CHAR_BREAKPOINT_INSERT: + { + static MCDCmdParseEntry handle_breakpoint_insert_cmd_desc = { + .handler = handle_breakpoint_insert, + }; + handle_breakpoint_insert_cmd_desc.cmd = + (char[2]) { TCP_CHAR_BREAKPOINT_INSERT, '\0' }; + strcpy(handle_breakpoint_insert_cmd_desc.schema, + (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, ARG_SCHEMA_UINT64_T, '\0' }); + cmd_parser = &handle_breakpoint_insert_cmd_desc; + } + break; + case TCP_CHAR_BREAKPOINT_REMOVE: + { + static MCDCmdParseEntry handle_breakpoint_remove_cmd_desc = { + .handler = handle_breakpoint_remove, + }; + handle_breakpoint_remove_cmd_desc.cmd = + (char[2]) { TCP_CHAR_BREAKPOINT_REMOVE, '\0' }; + strcpy(handle_breakpoint_remove_cmd_desc.schema, + (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, ARG_SCHEMA_UINT64_T, '\0' }); + cmd_parser = &handle_breakpoint_remove_cmd_desc; + } + break; default: /* command not supported */ mcd_put_packet(""); @@ -837,13 +863,14 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) cpu->watchpoint_hit = NULL; } else if (cpu->singlestep_enabled) { /* we land here when a single step is performed */ - cpu_single_step(cpu, 0); stop_str = STATE_STEP_PERFORMED; } else { trig_id = MCD_TRIG_TYPE_IP; stop_str = STATE_STR_BREAK_HW; tb_flush(cpu); } + /* deactivate single step */ + cpu_single_step(cpu, 0); break; case RUN_STATE_PAUSED: info_str = STATE_STR_HALTED(cpu->cpu_index); @@ -1594,7 +1621,8 @@ void mcd_vm_start(void) int mcd_vm_sstep(CPUState *cpu) { - cpu_single_step(mcdserver_state.c_cpu, mcdserver_state.sstep_flags); + mcdserver_state.c_cpu = cpu; + cpu_single_step(cpu, mcdserver_state.sstep_flags); mcd_vm_start(); return 0; } @@ -1950,3 +1978,95 @@ void handle_write_memory(GArray *params, void *user_ctx) mcd_put_packet(TCP_EXECUTION_SUCCESS); } } + +int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr, vaddr len) +{ + /* translate the type to known gdb types and function call*/ + int bp_type = 0; + CPUClass *cc = CPU_GET_CLASS(cpu); + if (cc->gdb_stop_before_watchpoint) { + //bp_type |= BP_STOP_BEFORE_ACCESS; + } + int return_value = 0; + switch (type) { + case MCD_BREAKPOINT_HW: + return_value = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); + return return_value; + case MCD_BREAKPOINT_READ: + bp_type |= BP_GDB | BP_MEM_READ; + return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL); + return return_value; + case MCD_BREAKPOINT_WRITE: + bp_type |= BP_GDB | BP_MEM_WRITE; + return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL); + return return_value; + case MCD_BREAKPOINT_RW: + bp_type |= BP_GDB | BP_MEM_ACCESS; + return_value = cpu_watchpoint_insert(cpu, addr, 4, bp_type, NULL); + return return_value; + default: + return -ENOSYS; + } +} + +int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr, vaddr len) +{ + /* translate the type to known gdb types and function call*/ + int bp_type = 0; + CPUClass *cc = CPU_GET_CLASS(cpu); + if (cc->gdb_stop_before_watchpoint) { + //bp_type |= BP_STOP_BEFORE_ACCESS; + } + int return_value = 0; + switch (type) { + case MCD_BREAKPOINT_HW: + return_value = cpu_breakpoint_remove(cpu, addr, BP_GDB); + return return_value; + case MCD_BREAKPOINT_READ: + bp_type |= BP_GDB | BP_MEM_READ; + return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + case MCD_BREAKPOINT_WRITE: + bp_type |= BP_GDB | BP_MEM_WRITE; + return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + case MCD_BREAKPOINT_RW: + bp_type |= BP_GDB | BP_MEM_ACCESS; + return_value = cpu_watchpoint_remove(cpu, addr, 4, bp_type); + return return_value; + default: + return -ENOSYS; + } +} + +void handle_breakpoint_insert(GArray *params, void *user_ctx) +{ + /* 1. get parameter data */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint32_t type = get_param(params, 1)->data_int; + uint64_t address = get_param(params, 2)->data_uint64_t; + uint64_t len = get_param(params, 3)->data_uint64_t; + /* 2. insert breakpoint and send reply*/ + CPUState *cpu = mcd_get_cpu(cpu_id); + if (mcd_breakpoint_insert(cpu, type, address, len) != 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} + +void handle_breakpoint_remove(GArray *params, void *user_ctx) +{ + /* 1. get parameter data */ + uint32_t cpu_id = get_param(params, 0)->cpu_id; + uint32_t type = get_param(params, 1)->data_int; + uint64_t address = get_param(params, 2)->data_uint64_t; + uint64_t len = get_param(params, 3)->data_uint64_t; + /* 2. remove breakpoint and send reply*/ + CPUState *cpu = mcd_get_cpu(cpu_id); + if (mcd_breakpoint_remove(cpu, type, address, len) != 0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } +} diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index 83156dceb8..c2bdaee410 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -309,6 +309,10 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg); int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); +void handle_breakpoint_insert(GArray *params, void *user_ctx); +void handle_breakpoint_remove(GArray *params, void *user_ctx); +int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr, vaddr len); +int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr, vaddr len); /* arm specific functions */ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces); diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 0848e0dbdb..b1807e6d7b 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -306,7 +306,7 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - gdb_set_stop_cpu(cpu); + /*gdb_set_stop_cpu(cpu);*/ qemu_system_debug_request(); cpu->stopped = true; } From patchwork Fri Oct 6 09:05:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844299 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22fd6xZSz1yqF for ; Fri, 6 Oct 2023 20:08:57 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognq-0000LJ-7D; Fri, 06 Oct 2023 05:07:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognR-0008EL-3e for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:58 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognO-00010O-16 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:55 -0400 Received: (qmail 19808 invoked by uid 484); 6 Oct 2023 09:06:41 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.088364 secs); 06 Oct 2023 09:06:41 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:40 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 18/29] making step and go handlers core-specific Date: Fri, 6 Oct 2023 11:05:59 +0200 Message-Id: <20231006090610.26171-19-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcdstub.c | 26 ++++++++++++++++++++++---- mcdstub/mcdstub.h | 3 ++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 4327703bca..8fc95d96a4 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -434,6 +434,8 @@ int mcd_handle_packet(const char *line_buf) .handler = handle_vm_start, }; go_cmd_desc.cmd = (char[2]) { TCP_CHAR_GO, '\0' }; + strcpy(go_cmd_desc.schema, + (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &go_cmd_desc; } break; @@ -606,7 +608,9 @@ int mcd_handle_packet(const char *line_buf) void handle_vm_start(GArray *params, void *user_ctx) { /* TODO: add partial restart with arguments and so on */ - mcd_vm_start(); + uint32_t cpu_id = get_param(params, 0)->cpu_id; + CPUState *cpu = mcd_get_cpu(cpu_id); + mcd_cpu_start(cpu); } void handle_vm_step(GArray *params, void *user_ctx) @@ -615,7 +619,7 @@ void handle_vm_step(GArray *params, void *user_ctx) uint32_t cpu_id = get_param(params, 0)->cpu_id; CPUState *cpu = mcd_get_cpu(cpu_id); - int return_value = mcd_vm_sstep(cpu); + int return_value = mcd_cpu_sstep(cpu); if (return_value != 0) { g_assert_not_reached(); } @@ -1619,11 +1623,25 @@ void mcd_vm_start(void) } } -int mcd_vm_sstep(CPUState *cpu) +void mcd_cpu_start(CPUState *cpu) +{ + if (!runstate_needs_reset() && !runstate_is_running() && + !vm_prepare_start(false)) { + mcdserver_state.c_cpu = cpu; + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); + cpu_resume(cpu); + } +} + +int mcd_cpu_sstep(CPUState *cpu) { mcdserver_state.c_cpu = cpu; cpu_single_step(cpu, mcdserver_state.sstep_flags); - mcd_vm_start(); + if (!runstate_needs_reset() && !runstate_is_running() && + !vm_prepare_start(true)) { + qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); + cpu_resume(cpu); + } return 0; } diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index c2bdaee410..ab44252ba0 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -289,7 +289,8 @@ void handle_close_server(GArray *params, void *user_ctx); void handle_close_core(GArray *params, void *user_ctx); void handle_query_trigger(GArray *params, void *user_ctx); void mcd_vm_start(void); -int mcd_vm_sstep(CPUState *cpu); +void mcd_cpu_start(CPUState *cpu); +int mcd_cpu_sstep(CPUState *cpu); void mcd_vm_stop(void); void handle_query_reg_groups_f(GArray *params, void *user_ctx); void handle_query_reg_groups_c(GArray *params, void *user_ctx); From patchwork Fri Oct 6 09:06:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844291 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dS1Qmcz1yqF for ; Fri, 6 Oct 2023 20:07:56 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognw-0000y7-0r; Fri, 06 Oct 2023 05:07:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognV-0008FJ-6t for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:02 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognR-00011h-98 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:06:59 -0400 Received: (qmail 19843 invoked by uid 484); 6 Oct 2023 09:06:45 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.245072 secs); 06 Oct 2023 09:06:45 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:42 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 19/29] adding trigger ID handling for TRACE32 Date: Fri, 6 Oct 2023 11:06:00 +0200 Message-Id: <20231006090610.26171-20-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcd_shared_defines.h | 2 +- mcdstub/mcdstub.c | 101 +++++++++++++++++++++-------------- mcdstub/mcdstub.h | 29 ++++++---- 3 files changed, 82 insertions(+), 50 deletions(-) diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 2e0831594a..88d556cab1 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -63,7 +63,7 @@ #define TCP_ARGUMENT_MEMSPACEID "memspaceid" #define TCP_ARGUMENT_SIZE "size" #define TCP_ARGUMENT_THREAD "thread" -#define TCP_ARGUMENT_TRIGGER_ID "trig_id" +#define TCP_ARGUMENT_ADDRESS "address" #define TCP_ARGUMENT_STOP_STRING "stop_str" #define TCP_ARGUMENT_INFO_STRING "info_str" #define TCP_ARGUMENT_STATE "state" diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 8fc95d96a4..bd532b0f4c 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -573,8 +573,8 @@ int mcd_handle_packet(const char *line_buf) handle_breakpoint_insert_cmd_desc.cmd = (char[2]) { TCP_CHAR_BREAKPOINT_INSERT, '\0' }; strcpy(handle_breakpoint_insert_cmd_desc.schema, - (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, - ARG_SCHEMA_UINT64_T, ARG_SCHEMA_UINT64_T, '\0' }); + (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, '\0' }); cmd_parser = &handle_breakpoint_insert_cmd_desc; } break; @@ -586,8 +586,8 @@ int mcd_handle_packet(const char *line_buf) handle_breakpoint_remove_cmd_desc.cmd = (char[2]) { TCP_CHAR_BREAKPOINT_REMOVE, '\0' }; strcpy(handle_breakpoint_remove_cmd_desc.schema, - (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, - ARG_SCHEMA_UINT64_T, ARG_SCHEMA_UINT64_T, '\0' }); + (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, '\0' }); cmd_parser = &handle_breakpoint_remove_cmd_desc; } break; @@ -671,6 +671,18 @@ uint64_t atouint64_t(const char *in) return res; } +uint32_t atouint32_t(const char *in) +{ + uint32_t res = 0; + for (int i = 0; i < strlen(in); ++i) { + const char c = in[i]; + res *= 10; + res += c - '0'; + } + + return res; +} + int cmd_parse_params(const char *data, const char *schema, GArray *params) { @@ -705,7 +717,7 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) g_string_printf(mcdserver_state.str_buf, "%s", data_buffer); break; case ARG_SCHEMA_INT: - this_param.data_int = atoi(data_buffer); + this_param.data_uint32_t = atouint32_t(data_buffer); g_array_append_val(params, this_param); break; case ARG_SCHEMA_UINT64_T: @@ -713,11 +725,11 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params) g_array_append_val(params, this_param); break; case ARG_SCHEMA_QRYHANDLE: - this_param.query_handle = atoi(data_buffer); + this_param.query_handle = atouint32_t(data_buffer); g_array_append_val(params, this_param); break; case ARG_SCHEMA_CORENUM: - this_param.cpu_id = atoi(data_buffer); + this_param.cpu_id = atouint32_t(data_buffer); g_array_append_val(params, this_param); break; default: @@ -828,7 +840,7 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) const char *info_str; info_str = STATE_STR_INIT_RUNNING; mcdserver_state.cpu_state.state = mcd_state; - mcdserver_state.cpu_state.state = info_str; + mcdserver_state.cpu_state.info_str = info_str; } return; } @@ -836,7 +848,8 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) const char *mcd_state; const char *stop_str; const char *info_str; - uint32_t trig_id = 0; + uint32_t bp_type = 0; + uint64_t bp_address = 0; switch (state) { case RUN_STATE_RUNNING: mcd_state = CORE_STATE_RUNNING; @@ -849,27 +862,28 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) if (cpu->watchpoint_hit) { switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { case BP_MEM_READ: - trig_id = MCD_TRIG_TYPE_READ; + bp_type = MCD_BREAKPOINT_READ; stop_str = STATE_STR_BREAK_READ(cpu->watchpoint_hit->hitaddr); break; case BP_MEM_WRITE: - trig_id = MCD_TRIG_TYPE_WRITE; + bp_type = MCD_BREAKPOINT_WRITE; stop_str = STATE_STR_BREAK_WRITE(cpu->watchpoint_hit->hitaddr); break; case BP_MEM_ACCESS: - trig_id = MCD_TRIG_TYPE_RW; + bp_type = MCD_BREAKPOINT_RW; stop_str = STATE_STR_BREAK_RW(cpu->watchpoint_hit->hitaddr); break; default: - break; stop_str = STATE_STR_BREAK_UNKNOWN; + break; } + bp_address = cpu->watchpoint_hit->hitaddr; cpu->watchpoint_hit = NULL; } else if (cpu->singlestep_enabled) { /* we land here when a single step is performed */ stop_str = STATE_STEP_PERFORMED; } else { - trig_id = MCD_TRIG_TYPE_IP; + bp_type = MCD_BREAKPOINT_HW; stop_str = STATE_STR_BREAK_HW; tb_flush(cpu); } @@ -895,7 +909,8 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) /* set state for c_cpu */ mcdserver_state.cpu_state.state = mcd_state; - mcdserver_state.cpu_state.trig_id = trig_id; + mcdserver_state.cpu_state.bp_type = bp_type; + mcdserver_state.cpu_state.bp_address = bp_address; mcdserver_state.cpu_state.stop_str = stop_str; mcdserver_state.cpu_state.info_str = info_str; } @@ -1263,13 +1278,14 @@ int init_resets(GArray *resets) return 0; } -int init_trigger(mcd_trigger_st *trigger) +int init_trigger(mcd_trigger_into_st *trigger) { trigger->type = (MCD_TRIG_TYPE_IP | MCD_TRIG_TYPE_READ | MCD_TRIG_TYPE_WRITE | MCD_TRIG_TYPE_RW); trigger->option = (MCD_TRIG_OPT_DATA_IS_CONDITION); trigger->action = (MCD_TRIG_ACTION_DBG_DEBUG); - trigger->nr_trigger = 4; + /* there is no specific upper limit for trigger */ + trigger->nr_trigger = 0; return 0; } @@ -1541,7 +1557,7 @@ void handle_query_reset_f(GArray *params, void *user_ctx) void handle_query_reset_c(GArray *params, void *user_ctx) { /* reset options are the same for every cpu! */ - int query_index = get_param(params, 0)->query_handle; + uint32_t query_index = get_param(params, 0)->query_handle; /* 1. check weather this was the last mem space */ int nb_groups = mcdserver_state.resets->len; @@ -1608,7 +1624,7 @@ void handle_close_server(GArray *params, void *user_ctx) void handle_query_trigger(GArray *params, void *user_ctx) { - mcd_trigger_st trigger = mcdserver_state.trigger; + mcd_trigger_into_st trigger = mcdserver_state.trigger; g_string_printf(mcdserver_state.str_buf, "%s=%d.%s=%d.%s=%d.%s=%d.", TCP_ARGUMENT_AMOUNT_TRIGGER, trigger.nr_trigger, TCP_ARGUMENT_TYPE, trigger.type, TCP_ARGUMENT_OPTION, trigger.option, @@ -1687,7 +1703,7 @@ void handle_query_mem_spaces_c(GArray *params, void *user_ctx) * this funcitons send all mem spaces except for the first * 1. get parameter and memspace */ - int query_index = get_param(params, 0)->query_handle; + uint32_t query_index = get_param(params, 0)->query_handle; uint32_t cpu_id = mcdserver_state.query_cpu_id; GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); @@ -1742,7 +1758,7 @@ void handle_query_reg_groups_c(GArray *params, void *user_ctx) * this funcitons send all reg groups except for the first * 1. get parameter and memspace */ - int query_index = get_param(params, 0)->query_handle; + uint32_t query_index = get_param(params, 0)->query_handle; uint32_t cpu_id = mcdserver_state.query_cpu_id; GArray *reggroups = g_list_nth_data(mcdserver_state.all_reggroups, cpu_id); @@ -1797,7 +1813,7 @@ void handle_query_regs_c(GArray *params, void *user_ctx) * this funcitons send all regs except for the first * 1. get parameter and registers */ - int query_index = get_param(params, 0)->query_handle; + uint32_t query_index = get_param(params, 0)->query_handle; uint32_t cpu_id = mcdserver_state.query_cpu_id; GArray *registers = g_list_nth_data(mcdserver_state.all_registers, cpu_id); @@ -1853,13 +1869,22 @@ void handle_query_state(GArray *params, void *user_ctx) } /* send data */ g_string_printf(mcdserver_state.str_buf, - "%s=%s.%s=%d.%s=%d.%s=%d.%s=%s.%s=%s.", + "%s=%s.%s=%u.%s=%u.%s=%u.%s=%lu.%s=%s.%s=%s.", TCP_ARGUMENT_STATE, state_info.state, TCP_ARGUMENT_EVENT, event, TCP_ARGUMENT_THREAD, 0, - TCP_ARGUMENT_TRIGGER_ID, state_info.trig_id, + TCP_ARGUMENT_TYPE, state_info.bp_type, + TCP_ARGUMENT_ADDRESS, state_info.bp_address, TCP_ARGUMENT_STOP_STRING, state_info.stop_str, TCP_ARGUMENT_INFO_STRING, state_info.info_str); mcd_put_strbuf(); + + /* reset debug info after first query */ + if (strcmp(state_info.state, CORE_STATE_DEBUG) == 0) { + mcdserver_state.cpu_state.stop_str = ""; + mcdserver_state.cpu_state.info_str = ""; + mcdserver_state.cpu_state.bp_type = 0; + mcdserver_state.cpu_state.bp_address = 0; + } } int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) @@ -1913,7 +1938,7 @@ void mcd_hextomem(GByteArray *mem, const char *buf, int len) void handle_read_register(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint64_t reg_num = get_param(params, 1)->data_int; + uint64_t reg_num = get_param(params, 1)->data_uint64_t; int reg_size; CPUState *cpu = mcd_get_cpu(cpu_id); @@ -1926,8 +1951,8 @@ void handle_read_register(GArray *params, void *user_ctx) void handle_write_register(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint64_t reg_num = get_param(params, 1)->data_int; - uint32_t reg_size = get_param(params, 2)->data_int; + uint64_t reg_num = get_param(params, 1)->data_uint64_t; + uint32_t reg_size = get_param(params, 2)->data_uint32_t; CPUState *cpu = mcd_get_cpu(cpu_id); mcd_hextomem(mcdserver_state.mem_buf, @@ -1967,7 +1992,7 @@ void handle_read_memory(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; uint64_t mem_address = get_param(params, 1)->data_uint64_t; - int len = get_param(params, 2)->data_int; + uint32_t len = get_param(params, 2)->data_uint32_t; CPUState *cpu = mcd_get_cpu(cpu_id); g_byte_array_set_size(mcdserver_state.mem_buf, len); @@ -1985,7 +2010,7 @@ void handle_write_memory(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; uint64_t mem_address = get_param(params, 1)->data_uint64_t; - int len = get_param(params, 2)->data_int; + uint32_t len = get_param(params, 2)->data_uint32_t; CPUState *cpu = mcd_get_cpu(cpu_id); mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, len); @@ -1997,7 +2022,7 @@ void handle_write_memory(GArray *params, void *user_ctx) } } -int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr, vaddr len) +int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr) { /* translate the type to known gdb types and function call*/ int bp_type = 0; @@ -2027,7 +2052,7 @@ int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr, vaddr len) } } -int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr, vaddr len) +int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr) { /* translate the type to known gdb types and function call*/ int bp_type = 0; @@ -2061,12 +2086,11 @@ void handle_breakpoint_insert(GArray *params, void *user_ctx) { /* 1. get parameter data */ uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint32_t type = get_param(params, 1)->data_int; + uint32_t type = get_param(params, 1)->data_uint32_t; uint64_t address = get_param(params, 2)->data_uint64_t; - uint64_t len = get_param(params, 3)->data_uint64_t; - /* 2. insert breakpoint and send reply*/ + /* 2. insert breakpoint and send reply */ CPUState *cpu = mcd_get_cpu(cpu_id); - if (mcd_breakpoint_insert(cpu, type, address, len) != 0) { + if (mcd_breakpoint_insert(cpu, type, address) != 0) { mcd_put_packet(TCP_EXECUTION_ERROR); } else { mcd_put_packet(TCP_EXECUTION_SUCCESS); @@ -2077,12 +2101,11 @@ void handle_breakpoint_remove(GArray *params, void *user_ctx) { /* 1. get parameter data */ uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint32_t type = get_param(params, 1)->data_int; + uint32_t type = get_param(params, 1)->data_uint32_t; uint64_t address = get_param(params, 2)->data_uint64_t; - uint64_t len = get_param(params, 3)->data_uint64_t; - /* 2. remove breakpoint and send reply*/ + /* 2. remove breakpoint and send reply */ CPUState *cpu = mcd_get_cpu(cpu_id); - if (mcd_breakpoint_remove(cpu, type, address, len) != 0) { + if (mcd_breakpoint_remove(cpu, type, address) != 0) { mcd_put_packet(TCP_EXECUTION_ERROR); } else { mcd_put_packet(TCP_EXECUTION_SUCCESS); diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index ab44252ba0..7a63a01a39 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -104,10 +104,10 @@ typedef struct MCDCmdParseEntry { typedef union MCDCmdVariant { const char *data; - int data_int; + uint32_t data_uint32_t; uint64_t data_uint64_t; - int query_handle; - int cpu_id; + uint32_t query_handle; + uint32_t cpu_id; } MCDCmdVariant; #define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) @@ -119,19 +119,26 @@ enum RSState { RS_DATAEND, }; -typedef struct mcd_trigger_st { +typedef struct breakpoint_st { + uint32_t type; + uint64_t address; + uint32_t id; +} breakpoint_st; + +typedef struct mcd_trigger_into_st { uint32_t type; uint32_t option; uint32_t action; uint32_t nr_trigger; -} mcd_trigger_st; +} mcd_trigger_into_st; typedef struct mcd_cpu_state_st { const char *state; bool memory_changed; bool registers_changed; bool target_was_stopped; - uint32_t trig_id; + uint32_t bp_type; + uint64_t bp_address; const char *stop_str; const char *info_str; } mcd_cpu_state_st; @@ -158,8 +165,9 @@ typedef struct MCDState { GList *all_memspaces; GList *all_reggroups; GList *all_registers; + GList *all_breakpoints; GArray *resets; - mcd_trigger_st trigger; + mcd_trigger_into_st trigger; mcd_cpu_state_st cpu_state; MCDCmdParseEntry mcd_query_cmds_table[QUERY_TOTAL_NUMBER]; } MCDState; @@ -244,7 +252,7 @@ void mcd_sigterm_handler(int signal); void mcd_init_mcdserver_state(void); void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table); int init_resets(GArray *resets); -int init_trigger(mcd_trigger_st *trigger); +int init_trigger(mcd_trigger_into_st *trigger); void reset_mcdserver_state(void); void create_processes(MCDState *s); void mcd_create_default_process(MCDState *s); @@ -312,8 +320,8 @@ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); void handle_breakpoint_insert(GArray *params, void *user_ctx); void handle_breakpoint_remove(GArray *params, void *user_ctx); -int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr, vaddr len); -int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr, vaddr len); +int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr); +int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr); /* arm specific functions */ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces); @@ -332,5 +340,6 @@ int int_cmp(gconstpointer a, gconstpointer b); void mcd_memtohex(GString *buf, const uint8_t *mem, int len); void mcd_hextomem(GByteArray *mem, const char *buf, int len); uint64_t atouint64_t(const char *in); +uint32_t atouint32_t(const char *in); #endif /* MCDSTUB_INTERNALS_H */ From patchwork Fri Oct 6 09:06:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844310 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22hm2Lp0z1yq9 for ; Fri, 6 Oct 2023 20:10:48 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognx-0001DR-Ur; Fri, 06 Oct 2023 05:07:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogna-0008HG-SZ for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:06 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognT-00012I-AD for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:06 -0400 Received: (qmail 19868 invoked by uid 484); 6 Oct 2023 09:06:47 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.094354 secs); 06 Oct 2023 09:06:47 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:45 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 20/29] cp register read/write added Date: Fri, 6 Oct 2023 11:06:01 +0200 Message-Id: <20231006090610.26171-21-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcd_shared_defines.h | 1 + mcdstub/mcdstub.c | 117 ++++++++++------ mcdstub/mcdstub.h | 18 ++- target/arm/mcdstub.c | 265 ++++++++++++++++++++++++++++++----- target/arm/mcdstub.h | 16 ++- 5 files changed, 330 insertions(+), 87 deletions(-) diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 88d556cab1..91d476a555 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -74,6 +74,7 @@ #define TCP_ARGUMENT_AMOUNT_TRIGGER "nr_trigger" #define TCP_ARGUMENT_OPTION "option" #define TCP_ARGUMENT_ACTION "action" +#define TCP_ARGUMENT_OPCODE "opcode" /* for packets sent to qemu */ #define ARGUMENT_SEPARATOR ';' diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index bd532b0f4c..3772bda0a1 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -1064,10 +1064,12 @@ CPUState *find_cpu(uint32_t thread_id) } -void parse_reg_xml(const char *xml, int size, GArray *registers) +void parse_reg_xml(const char *xml, int size, GArray *registers, + uint8_t reg_type) { /* iterates over the complete xml file */ int i, j; + uint32_t internal_id = 0; int still_to_skip = 0; char argument[64] = {0}; char value[64] = {0}; @@ -1116,8 +1118,11 @@ void parse_reg_xml(const char *xml, int size, GArray *registers) if (strcmp(argument_j, "name") == 0) { strcpy(my_register.name, value_j); - } else if (strcmp(argument_j, "regnum") == 0) { - my_register.id = atoi(value_j); + /* + * we might want to read out the regnum + * } else if (strcmp(argument_j, "regnum") == 0) { + * my_register.internal_id = atoi(value_j); + */ } else if (strcmp(argument_j, "bitsize") == 0) { my_register.bitsize = atoi(value_j); } else if (strcmp(argument_j, "type") == 0) { @@ -1126,6 +1131,10 @@ void parse_reg_xml(const char *xml, int size, GArray *registers) strcpy(my_register.group, value_j); } } + /* add reg_type and internal id */ + my_register.reg_type = reg_type; + my_register.internal_id = internal_id; + internal_id++; /* store register */ g_array_append_vals(registers, (gconstpointer)&my_register, 1); /* free memory */ @@ -1238,6 +1247,7 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) }; g_array_append_vals(memspaces, (gconstpointer)&space4, 1); } + /* TODO: get dynamically how the per (CP15) space is called */ mcd_mem_space_st space5 = { .name = "GPR Registers", @@ -1263,7 +1273,6 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) .supported_access_options = 0, }; g_array_append_vals(memspaces, (gconstpointer)&space6, 1); - return 0; } @@ -1366,7 +1375,8 @@ int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray *reggroups, /* 3. parse xml */ xml_content = xml_builtin[i][1]; - parse_reg_xml(xml_content, strlen(xml_content), registers); + parse_reg_xml(xml_content, strlen(xml_content), registers, + MCD_ARM_REG_TYPE_GPR); return 0; } @@ -1376,6 +1386,7 @@ int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray *reggroups, const char *current_xml_filename = NULL; const char *xml_content = NULL; int i = 0; + uint8_t reg_type; /* iterate over all gdb xml files*/ GDBRegisterState *r; @@ -1395,6 +1406,7 @@ int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray *reggroups, g_array_append_vals(reggroups, (gconstpointer)&corprocessorregs, 1); *current_group_id = *current_group_id + 1; + reg_type = MCD_ARM_REG_TYPE_CPR; } } else { /* its not a coprocessor xml -> it is a static xml file */ @@ -1407,58 +1419,59 @@ int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray *reggroups, } if (current_xml_filename) { xml_content = xml_builtin[i][1]; + /* select correct reg_type */ + if (strcmp(current_xml_filename, "arm-vfp.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, "arm-vfp3.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-vfp-sysregs.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP_SYS; + } else if (strcmp(current_xml_filename, + "arm-neon.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-m-profile-mve.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_MVE; + } } else { continue; } } /* 2. parse xml */ - parse_reg_xml(xml_content, strlen(xml_content), registers); + parse_reg_xml(xml_content, strlen(xml_content), registers, reg_type); } return 0; } -int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers) +int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers, + CPUState *cpu) { - GList *register_numbers = NULL; mcd_reg_st *current_register; - int i = 0; - int id_neg_offset = 0; - int effective_id = 0; + uint32_t i = 0; /* iterate over all registers */ for (i = 0; i < registers->len; i++) { current_register = &(g_array_index(registers, mcd_reg_st, i)); - /* 1. ad the id */ - if (current_register->id) { - /* - *id is already in place - *NOTE: qemu doesn't emulate the FPA regs - *(so we are missing the indices 16 to 24) - */ - int used_id = current_register->id; - register_numbers = g_list_append(register_numbers, &used_id); - id_neg_offset++; - } else { - effective_id = i - id_neg_offset; - if (g_list_find_custom(register_numbers, &effective_id, - (GCompareFunc)int_cmp) != NULL) { - id_neg_offset--; - } - current_register->id = i - id_neg_offset; - } - /* 2. add mcd_reg_group_id and mcd_mem_space_id */ + current_register->id = i; + /* add mcd_reg_group_id and mcd_mem_space_id */ if (strcmp(current_register->group, "cp_regs") == 0) { /* coprocessor registers */ current_register->mcd_reg_group_id = 2; current_register->mcd_mem_space_id = 6; - /* TODO: get info for opcode */ + /* + * get info for opcode + * for 32bit the opcode is only 16 bit long + * for 64bit it is 32 bit long + */ + current_register->opcode |= + arm_mcd_get_opcode(cpu, current_register->internal_id); } else { /* gpr register */ current_register->mcd_reg_group_id = 1; current_register->mcd_mem_space_id = 5; } } - g_list_free(register_numbers); return 0; } @@ -1498,7 +1511,7 @@ void handle_open_core(GArray *params, void *user_ctx) } /* 4. add additional data the the regs from the xmls */ return_value = mcd_arm_get_additional_register_info(reggroups, - registers); + registers, cpu); if (return_value != 0) { g_assert_not_reached(); } @@ -1797,13 +1810,15 @@ void handle_query_regs_f(GArray *params, void *user_ctx) /* 3. send data */ mcd_reg_st my_register = g_array_index(registers, mcd_reg_st, 0); g_string_append_printf(mcdserver_state.str_buf, - "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", - TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, - my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, + "%s=%u.%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.", + TCP_ARGUMENT_ID, my_register.id, + TCP_ARGUMENT_NAME, my_register.name, + TCP_ARGUMENT_SIZE, my_register.bitsize, TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, - TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); + TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id, + TCP_ARGUMENT_OPCODE, my_register.opcode); mcd_put_strbuf(); } @@ -1829,13 +1844,15 @@ void handle_query_regs_c(GArray *params, void *user_ctx) /* 3. send the correct register */ mcd_reg_st my_register = g_array_index(registers, mcd_reg_st, query_index); g_string_append_printf(mcdserver_state.str_buf, - "%s=%d.%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.", - TCP_ARGUMENT_ID, my_register.id, TCP_ARGUMENT_NAME, - my_register.name, TCP_ARGUMENT_SIZE, my_register.bitsize, + "%s=%u.%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.", + TCP_ARGUMENT_ID, my_register.id, + TCP_ARGUMENT_NAME, my_register.name, + TCP_ARGUMENT_SIZE, my_register.bitsize, TCP_ARGUMENT_REGGROUPID, my_register.mcd_reg_group_id, TCP_ARGUMENT_MEMSPACEID, my_register.mcd_mem_space_id, TCP_ARGUMENT_TYPE, my_register.mcd_reg_type, - TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id); + TCP_ARGUMENT_THREAD, my_register.mcd_hw_thread_id, + TCP_ARGUMENT_OPCODE, my_register.opcode); mcd_put_strbuf(); } @@ -1889,11 +1906,18 @@ void handle_query_state(GArray *params, void *user_ctx) int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) { + /* 1. get reg type and internal id */ + GArray *registers = + g_list_nth_data(mcdserver_state.all_registers, cpu->cpu_index); + mcd_reg_st desired_register = g_array_index(registers, mcd_reg_st, reg); + uint8_t reg_type = desired_register.reg_type; + uint32_t internal_id = desired_register.internal_id; + /* 2. read register */ CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); if (strcmp(arch, "arm") == 0) { g_free(arch); - return arm_mcd_read_register(cpu, buf, reg); + return arm_mcd_read_register(cpu, buf, reg_type, internal_id); } else { g_free(arch); return 0; @@ -1902,11 +1926,18 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg) { + /* 1. get reg type and internal id */ + GArray *registers = + g_list_nth_data(mcdserver_state.all_registers, cpu->cpu_index); + mcd_reg_st desired_register = g_array_index(registers, mcd_reg_st, reg); + uint8_t reg_type = desired_register.reg_type; + uint32_t internal_id = desired_register.internal_id; + /* 2. write register */ CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); if (strcmp(arch, "arm") == 0) { g_free(arch); - return arm_mcd_write_register(cpu, buf, reg); + return arm_mcd_write_register(cpu, buf, reg_type, internal_id); } else { g_free(arch); return 0; diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index 7a63a01a39..25475acaf7 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -203,19 +203,16 @@ typedef struct mcd_reg_st { char group[64]; char type[64]; uint32_t bitsize; - uint32_t id; + uint32_t id; /* id used by the mcd interface */ + uint32_t internal_id; /* id inside reg type */ + uint8_t reg_type; /* mcd metadata */ uint32_t mcd_reg_group_id; uint32_t mcd_mem_space_id; uint32_t mcd_reg_type; uint32_t mcd_hw_thread_id; /* data for op-code */ - uint8_t cp; - uint8_t crn; - uint8_t crm; - uint8_t opc0; /* <- might not be needed! */ - uint8_t opc1; - uint8_t opc2; + uint32_t opcode; } mcd_reg_st; typedef struct mcd_reset_st { @@ -307,7 +304,8 @@ void handle_query_mem_spaces_c(GArray *params, void *user_ctx); void handle_query_regs_f(GArray *params, void *user_ctx); void handle_query_regs_c(GArray *params, void *user_ctx); void handle_open_server(GArray *params, void *user_ctx); -void parse_reg_xml(const char *xml, int size, GArray* registers); +void parse_reg_xml(const char *xml, int size, GArray* registers, + uint8_t reg_type); void handle_reset(GArray *params, void *user_ctx); void handle_query_state(GArray *params, void *user_ctx); void handle_read_register(GArray *params, void *user_ctx); @@ -329,8 +327,8 @@ int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray *reggroups, GArray *registers, int *current_group_id); int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray *registers, int *current_group_id); -int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers); - +int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers, + CPUState *cpu); /* sycall handling */ void mcd_syscall_reset(void); void mcd_disable_syscalls(void); diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index e4e632d3f3..c0bd5bb545 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -17,6 +17,31 @@ static inline int mcd_get_reg32(GByteArray *buf, uint32_t val) return 4; } +static inline int mcd_get_reg64(GByteArray *buf, uint64_t val) +{ + uint64_t to_quad = tswap64(val); + g_byte_array_append(buf, (uint8_t *) &to_quad, 8); + return 8; +} + +static inline int mcd_get_reg128(GByteArray *buf, uint64_t val_hi, + uint64_t val_lo) +{ + uint64_t to_quad; +#if TARGET_BIG_ENDIAN + to_quad = tswap64(val_hi); + g_byte_array_append(buf, (uint8_t *) &to_quad, 8); + to_quad = tswap64(val_lo); + g_byte_array_append(buf, (uint8_t *) &to_quad, 8); +#else + to_quad = tswap64(val_lo); + g_byte_array_append(buf, (uint8_t *) &to_quad, 8); + to_quad = tswap64(val_hi); + g_byte_array_append(buf, (uint8_t *) &to_quad, 8); +#endif + return 16; +} + static inline int mcd_get_zeroes(GByteArray *array, size_t len) { /*TODO: move this to a separate file */ @@ -45,24 +70,13 @@ const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname) return NULL; } -int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) +static int arm_mcd_read_gpr_register(CPUARMState *env, GByteArray *mem_buf, + uint32_t n) { - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - if (n < 16) { /* Core integer register. */ return mcd_get_reg32(mem_buf, env->regs[n]); - } - if (n < 24) { - /* TODO: these numbers don't match mine */ - return mcd_get_zeroes(mem_buf, 12); - } - switch (n) { - case 24: - /* TODO: these numbers don't match mine */ - return mcd_get_reg32(mem_buf, 0); - case 25: + } else if (n == 16) { /* CPSR, or XPSR for M-profile */ if (arm_feature(env, ARM_FEATURE_M)) { return mcd_get_reg32(mem_buf, xpsr_read(env)); @@ -70,21 +84,17 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) return mcd_get_reg32(mem_buf, cpsr_read(env)); } } - /* TODO: add funcitons for the remaining regs (including cp_regs) */ return 0; } -int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) +static int arm_mcd_write_gpr_register(CPUARMState *env, uint8_t *mem_buf, + uint32_t n) { - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; uint32_t tmp; tmp = ldl_p(mem_buf); - tmp = *((uint32_t *)mem_buf->data); - /* - * Mask out low bits of PC to workaround gdb bugs. + * Mask out low bits of PC * This avoids an assert in thumb_tr_translate_insn, because it is * architecturally impossible to misalign the pc. * This will probably cause problems if we ever implement the @@ -102,16 +112,7 @@ int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) } env->regs[n] = tmp; return 4; - } - if (n < 24) { /* 16-23 */ - /* FPA registers (ignored). */ - return 4; - } - switch (n) { - case 24: - /* FPA status register (ignored). */ - return 4; - case 25: + } else if (n == 16) { /* CPSR, or XPSR for M-profile */ if (arm_feature(env, ARM_FEATURE_M)) { /* @@ -126,6 +127,206 @@ int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n) } return 4; } - /* TODO: add funcitons for the remaining regs (including cp_regs) */ + return 0; +} + +static int arm_mcd_read_vfp_register(CPUARMState *env, GByteArray *buf, + uint32_t reg) +{ + ARMCPU *cpu = env_archcpu(env); + int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; + + /* VFP data registers are always little-endian. */ + if (reg < nregs) { + return mcd_get_reg64(buf, *aa32_vfp_dreg(env, reg)); + } + if (arm_feature(env, ARM_FEATURE_NEON)) { + /* Aliases for Q regs. */ + nregs += 16; + if (reg < nregs) { + uint64_t *q = aa32_vfp_qreg(env, reg - 32); + return mcd_get_reg128(buf, q[0], q[1]); + } + } + switch (reg - nregs) { + case 0: + return mcd_get_reg32(buf, vfp_get_fpscr(env)); + } + return 0; +} + +static int arm_mcd_write_vfp_register(CPUARMState *env, uint8_t *buf, + uint32_t reg) +{ + ARMCPU *cpu = env_archcpu(env); + int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; + + if (reg < nregs) { + *aa32_vfp_dreg(env, reg) = ldq_le_p(buf); + return 8; + } + if (arm_feature(env, ARM_FEATURE_NEON)) { + nregs += 16; + if (reg < nregs) { + uint64_t *q = aa32_vfp_qreg(env, reg - 32); + q[0] = ldq_le_p(buf); + q[1] = ldq_le_p(buf + 8); + return 16; + } + } + switch (reg - nregs) { + case 0: + vfp_set_fpscr(env, ldl_p(buf)); + return 4; + } + return 0; +} + +static int arm_mcd_read_vfp_sys_register(CPUARMState *env, GByteArray *buf, + uint32_t reg) +{ + switch (reg) { + case 0: + return mcd_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); + case 1: + return mcd_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); + } + return 0; +} + +static int arm_mcd_write_vfp_sys_register(CPUARMState *env, uint8_t *buf, + uint32_t reg) +{ + switch (reg) { + case 0: + env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); + return 4; + case 1: + env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); + return 4; + } + return 0; +} + +static int arm_mcd_read_mve_register(CPUARMState *env, GByteArray *buf, + uint32_t reg) +{ + switch (reg) { + case 0: + return mcd_get_reg32(buf, env->v7m.vpr); + default: + return 0; + } +} + +static int arm_mcd_write_mve_register(CPUARMState *env, uint8_t *buf, + uint32_t reg) +{ + switch (reg) { + case 0: + env->v7m.vpr = ldl_p(buf); + return 4; + default: + return 0; + } +} + +static int arm_mcd_read_cpr_register(CPUARMState *env, GByteArray *buf, + uint32_t reg) +{ + ARMCPU *cpu = env_archcpu(env); + const ARMCPRegInfo *ri; + uint32_t key; + + key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg]; + ri = get_arm_cp_reginfo(cpu->cp_regs, key); + if (ri) { + if (cpreg_field_is_64bit(ri)) { + return mcd_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri)); + } else { + return mcd_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri)); + } + } + return 0; +} + +static int arm_mcd_write_cpr_register(CPUARMState *env, uint8_t *buf, + uint32_t reg) +{ + /* try write_raw_cp_reg here*/ + return 0; +} + +int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, + uint32_t n) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + switch (reg_type) { + case MCD_ARM_REG_TYPE_GPR: + return arm_mcd_read_gpr_register(env, mem_buf, n); + break; + case MCD_ARM_REG_TYPE_VFP: + return arm_mcd_read_vfp_register(env, mem_buf, n); + break; + case MCD_ARM_REG_TYPE_VFP_SYS: + return arm_mcd_read_vfp_sys_register(env, mem_buf, n); + break; + case MCD_ARM_REG_TYPE_MVE: + return arm_mcd_read_mve_register(env, mem_buf, n); + break; + case MCD_ARM_REG_TYPE_CPR: + return arm_mcd_read_cpr_register(env, mem_buf, n); + break; + default: + /* unknown register type*/ + return 0; + } +} + +int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, + uint32_t n) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + switch (reg_type) { + case MCD_ARM_REG_TYPE_GPR: + return arm_mcd_write_gpr_register(env, mem_buf->data, n); + break; + case MCD_ARM_REG_TYPE_VFP: + return arm_mcd_write_vfp_register(env, mem_buf->data, n); + break; + case MCD_ARM_REG_TYPE_VFP_SYS: + return arm_mcd_write_vfp_sys_register(env, mem_buf->data, n); + break; + case MCD_ARM_REG_TYPE_MVE: + return arm_mcd_write_mve_register(env, mem_buf->data, n); + break; + case MCD_ARM_REG_TYPE_CPR: + return arm_mcd_write_cpr_register(env, mem_buf->data, n); + break; + default: + /* unknown register type*/ + return 0; + } +} + +uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n) +{ + /*gets the opcode for a cp register*/ + ARMCPU *cpu = ARM_CPU(cs); + const ARMCPRegInfo *ri; + uint32_t key; + + key = cpu->dyn_sysreg_xml.data.cpregs.keys[n]; + ri = get_arm_cp_reginfo(cpu->cp_regs, key); + if (ri) { + uint16_t opcode = 0; + opcode |= ri->opc1 << 14; + opcode |= ri->opc2 << 10; + opcode |= ri->crm << 7; + opcode |= ri->crn << 3; + return opcode; + } return 0; } diff --git a/target/arm/mcdstub.h b/target/arm/mcdstub.h index 28c7f2baec..81d67246d8 100644 --- a/target/arm/mcdstub.h +++ b/target/arm/mcdstub.h @@ -1,8 +1,20 @@ #ifndef ARM_MCDSTUB_H #define ARM_MCDSTUB_H +/* ids for each different type of register */ +enum { + MCD_ARM_REG_TYPE_GPR, + MCD_ARM_REG_TYPE_VFP, + MCD_ARM_REG_TYPE_VFP_SYS, + MCD_ARM_REG_TYPE_MVE, + MCD_ARM_REG_TYPE_CPR, +}; + const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname); -int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n); -int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, int n); +int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, + uint32_t n); +int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, + uint32_t n); +uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); #endif /* ARM_MCDSTUB_H */ From patchwork Fri Oct 6 09:06:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844292 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dV1XHLz1yqF for ; Fri, 6 Oct 2023 20:07:58 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogno-0000Hq-8C; Fri, 06 Oct 2023 05:07:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognZ-0008HA-NN for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:06 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognV-00012p-MI for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:05 -0400 Received: (qmail 19894 invoked by uid 484); 6 Oct 2023 09:06:49 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.333814 secs); 06 Oct 2023 09:06:49 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:47 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 21/29] switching between secure and non-secure memory added Date: Fri, 6 Oct 2023 11:06:02 +0200 Message-Id: <20231006090610.26171-22-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcdstub.c | 131 +++++++++++++++++++++++++++---------------- mcdstub/mcdstub.h | 4 +- target/arm/mcdstub.c | 14 +++++ target/arm/mcdstub.h | 1 + 4 files changed, 100 insertions(+), 50 deletions(-) diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 3772bda0a1..7d8ce634c8 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -548,8 +548,8 @@ int mcd_handle_packet(const char *line_buf) }; read_mem_cmd_desc.cmd = (char[2]) { TCP_CHAR_READ_MEMORY, '\0' }; strcpy(read_mem_cmd_desc.schema, - (char[4]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, - ARG_SCHEMA_INT, '\0' }); + (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, '\0' }); cmd_parser = &read_mem_cmd_desc; } break; @@ -560,8 +560,9 @@ int mcd_handle_packet(const char *line_buf) }; write_mem_cmd_desc.cmd = (char[2]) { TCP_CHAR_WRITE_MEMORY, '\0' }; strcpy(write_mem_cmd_desc.schema, - (char[5]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_UINT64_T, - ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); + (char[6]) { ARG_SCHEMA_CORENUM, ARG_SCHEMA_INT, + ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, + ARG_SCHEMA_HEXDATA, '\0' }); cmd_parser = &write_mem_cmd_desc; } break; @@ -1194,10 +1195,17 @@ int int_cmp(gconstpointer a, gconstpointer b) int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) { int nr_address_spaces = cpu->num_ases; + uint32_t mem_space_id = 0; + + /* + * TODO: atm we can only access physical memory addresses, + * but trace32 needs fake locical spaces to work with + */ - mcd_mem_space_st space1 = { + mem_space_id++; + mcd_mem_space_st non_secure = { .name = "Non Secure", - .id = 1, + .id = mem_space_id, .type = 34, .bits_per_mau = 8, .invariance = 1, @@ -1205,38 +1213,13 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) .min_addr = 0, .max_addr = -1, .supported_access_options = 0, + .is_secure = false, }; - g_array_append_vals(memspaces, (gconstpointer)&space1, 1); - - mcd_mem_space_st space2 = { + g_array_append_vals(memspaces, (gconstpointer)&non_secure, 1); + mem_space_id++; + mcd_mem_space_st phys_non_secure = { .name = "Physical (Non Secure)", - .id = 2, - .type = 18, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - }; - g_array_append_vals(memspaces, (gconstpointer)&space2, 1); - - if (nr_address_spaces == 2) { - mcd_mem_space_st space3 = { - .name = "Secure", - .id = 3, - .type = 34, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - }; - g_array_append_vals(memspaces, (gconstpointer)&space3, 1); - mcd_mem_space_st space4 = { - .name = "Physical (Secure)", - .id = 4, + .id = mem_space_id, .type = 18, .bits_per_mau = 8, .invariance = 1, @@ -1244,14 +1227,44 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) .min_addr = 0, .max_addr = -1, .supported_access_options = 0, + .is_secure = false, }; - g_array_append_vals(memspaces, (gconstpointer)&space4, 1); + g_array_append_vals(memspaces, (gconstpointer)&phys_non_secure, 1); + if(nr_address_spaces > 1) { + mem_space_id++; + mcd_mem_space_st secure = { + .name = "Secure", + .id = mem_space_id, + .type = 34, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = true, + }; + g_array_append_vals(memspaces, (gconstpointer)&secure, 1); + mem_space_id++; + mcd_mem_space_st phys_secure = { + .name = "Physical (Secure)", + .id = mem_space_id, + .type = 18, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = true, + }; + g_array_append_vals(memspaces, (gconstpointer)&phys_secure, 1); } - /* TODO: get dynamically how the per (CP15) space is called */ - mcd_mem_space_st space5 = { + mem_space_id++; + mcd_mem_space_st gpr = { .name = "GPR Registers", - .id = 5, + .id = mem_space_id, .type = 1, .bits_per_mau = 8, .invariance = 1, @@ -1260,10 +1273,11 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(memspaces, (gconstpointer)&space5, 1); - mcd_mem_space_st space6 = { + g_array_append_vals(memspaces, (gconstpointer)&gpr, 1); + mem_space_id++; + mcd_mem_space_st cpr = { .name = "CP15 Registers", - .id = 6, + .id = mem_space_id, .type = 1, .bits_per_mau = 8, .invariance = 1, @@ -1272,7 +1286,7 @@ int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) .max_addr = -1, .supported_access_options = 0, }; - g_array_append_vals(memspaces, (gconstpointer)&space6, 1); + g_array_append_vals(memspaces, (gconstpointer)&cpr, 1); return 0; } @@ -2022,10 +2036,20 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) void handle_read_memory(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint64_t mem_address = get_param(params, 1)->data_uint64_t; - uint32_t len = get_param(params, 2)->data_uint32_t; + uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; + uint64_t mem_address = get_param(params, 2)->data_uint64_t; + uint32_t len = get_param(params, 3)->data_uint32_t; CPUState *cpu = mcd_get_cpu(cpu_id); + /* check if the mem space is secure */ + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, + mem_space_id - 1); + if (arm_mcd_set_scr(cpu, space.is_secure)) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + /* read memory */ g_byte_array_set_size(mcdserver_state.mem_buf, len); if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf->data, mcdserver_state.mem_buf->len) != 0) { @@ -2040,10 +2064,19 @@ void handle_read_memory(GArray *params, void *user_ctx) void handle_write_memory(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint64_t mem_address = get_param(params, 1)->data_uint64_t; - uint32_t len = get_param(params, 2)->data_uint32_t; - + uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; + uint64_t mem_address = get_param(params, 2)->data_uint64_t; + uint32_t len = get_param(params, 3)->data_uint32_t; CPUState *cpu = mcd_get_cpu(cpu_id); + /* check if the mem space is secure */ + GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, + mem_space_id - 1); + if (arm_mcd_set_scr(cpu, space.is_secure)) { + mcd_put_packet(TCP_EXECUTION_ERROR); + return; + } + /* read memory */ mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, len); if (mcd_write_memory(cpu, mem_address, mcdserver_state.mem_buf->data, len) != 0) { diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index 25475acaf7..f8171cba71 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -58,7 +58,7 @@ enum { /* misc */ #define QUERY_TOTAL_NUMBER 12 -#define CMD_SCHEMA_LENGTH 5 +#define CMD_SCHEMA_LENGTH 6 #define MCD_SYSTEM_NAME "qemu-system" /* tcp query packet values templates */ @@ -185,6 +185,8 @@ typedef struct mcd_mem_space_st { uint64_t min_addr; uint64_t max_addr; uint32_t supported_access_options; + /* internal */ + bool is_secure; } mcd_mem_space_st; typedef struct mcd_reg_group_st { diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index c0bd5bb545..8456352370 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -330,3 +330,17 @@ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n) } return 0; } + +int arm_mcd_set_scr(CPUState *cs, bool secure) +{ + /* swtiches between secure and non secure mode */ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + /* set bit 0 to 1 if non secure, to 0 if secure*/ + if (secure) { + env->cp15.scr_el3 &= 0xFFFFFFFE; + } else { + env->cp15.scr_el3 |= 1; + } + return 0; +} diff --git a/target/arm/mcdstub.h b/target/arm/mcdstub.h index 81d67246d8..c3b5c1ae8d 100644 --- a/target/arm/mcdstub.h +++ b/target/arm/mcdstub.h @@ -16,5 +16,6 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, uint32_t n); uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); +int arm_mcd_set_scr(CPUState *cs, bool secure); #endif /* ARM_MCDSTUB_H */ From patchwork Fri Oct 6 09:06:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844306 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22gn1SnFz1yqH for ; Fri, 6 Oct 2023 20:09:57 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognu-0000fP-53; Fri, 06 Oct 2023 05:07:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognZ-0008HB-Um for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:06 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognX-00013M-QF for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:05 -0400 Received: (qmail 19924 invoked by uid 484); 6 Oct 2023 09:06:52 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.072039 secs); 06 Oct 2023 09:06:52 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:50 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 22/29] transitioning to unsinged integers in TCP packets and removing MCD-API-specific terms Date: Fri, 6 Oct 2023 11:06:03 +0200 Message-Id: <20231006090610.26171-23-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcd_shared_defines.h | 8 ++++ mcdstub/mcdstub.c | 74 ++++++++++++++++++++---------------- mcdstub/mcdstub.h | 33 +++++----------- target/arm/mcdstub.c | 2 +- 4 files changed, 60 insertions(+), 57 deletions(-) diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 91d476a555..5cfda4121d 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -91,4 +91,12 @@ #define MCD_BREAKPOINT_WRITE 3 #define MCD_BREAKPOINT_RW 4 +/* trigger data */ +#define MCD_TRIG_ACT_BREAK "check_data_value" +#define MCD_TRIG_OPT_VALUE "break_on_trigger" + +/* register mem space key words */ +#define MCD_GRP_KEYWORD "GPR" +#define MCD_CP_KEYWORD "CP" + #endif diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 7d8ce634c8..8e711a0a40 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -1303,12 +1303,15 @@ int init_resets(GArray *resets) int init_trigger(mcd_trigger_into_st *trigger) { - trigger->type = (MCD_TRIG_TYPE_IP | MCD_TRIG_TYPE_READ | - MCD_TRIG_TYPE_WRITE | MCD_TRIG_TYPE_RW); - trigger->option = (MCD_TRIG_OPT_DATA_IS_CONDITION); - trigger->action = (MCD_TRIG_ACTION_DBG_DEBUG); - /* there is no specific upper limit for trigger */ - trigger->nr_trigger = 0; + snprintf(trigger->type, sizeof(trigger->type), + "%d,%d,%d,%d", MCD_BREAKPOINT_HW, MCD_BREAKPOINT_READ, + MCD_BREAKPOINT_WRITE, MCD_BREAKPOINT_RW); + snprintf(trigger->option, sizeof(trigger->option), + "%s", MCD_TRIG_OPT_VALUE); + snprintf(trigger->action, sizeof(trigger->action), + "%s", MCD_TRIG_ACT_BREAK); + /* there can be 16 breakpoints and 16 watchpoints each */ + trigger->nr_trigger = 16; return 0; } @@ -1348,9 +1351,9 @@ void handle_query_cores(GArray *params, void *user_ctx) CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - int nr_cores = cpu->nr_cores; + uint32_t nr_cores = cpu->nr_cores; char device_name[] = DEVICE_NAME_TEMPLATE(arch); - g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%s.%s=%d.", + g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%s.%s=%u.", TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_ARGUMENT_AMOUNT_CORE, nr_cores); mcd_put_strbuf(); @@ -1576,7 +1579,7 @@ void handle_query_reset_f(GArray *params, void *user_ctx) } /* 2. send data */ mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%u.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); } @@ -1592,13 +1595,13 @@ void handle_query_reset_c(GArray *params, void *user_ctx) /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); } else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } /* 2. send data */ mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%d.", + g_string_append_printf(mcdserver_state.str_buf, "%s=%s.%s=%u.", TCP_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); } @@ -1652,9 +1655,10 @@ void handle_close_server(GArray *params, void *user_ctx) void handle_query_trigger(GArray *params, void *user_ctx) { mcd_trigger_into_st trigger = mcdserver_state.trigger; - g_string_printf(mcdserver_state.str_buf, "%s=%d.%s=%d.%s=%d.%s=%d.", + g_string_printf(mcdserver_state.str_buf, "%s=%u.%s=%s.%s=%s.%s=%s.", TCP_ARGUMENT_AMOUNT_TRIGGER, trigger.nr_trigger, - TCP_ARGUMENT_TYPE, trigger.type, TCP_ARGUMENT_OPTION, trigger.option, + TCP_ARGUMENT_TYPE, trigger.type, + TCP_ARGUMENT_OPTION, trigger.option, TCP_ARGUMENT_ACTION, trigger.action); mcd_put_strbuf(); } @@ -1714,13 +1718,16 @@ void handle_query_mem_spaces_f(GArray *params, void *user_ctx) /* 3. send data */ mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, 0); g_string_append_printf(mcdserver_state.str_buf, - "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", - TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, space.id, - TCP_ARGUMENT_TYPE, space.type, TCP_ARGUMENT_BITS_PER_MAU, - space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, - TCP_ARGUMENT_ENDIAN, space.endian, TCP_ARGUMENT_MIN, space.min_addr, - TCP_ARGUMENT_MAX, space.max_addr, TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, - space.supported_access_options); + "%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%ld.%s=%ld.%s=%u.", + TCP_ARGUMENT_NAME, space.name, + TCP_ARGUMENT_ID, space.id, + TCP_ARGUMENT_TYPE, space.type, + TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, + TCP_ARGUMENT_INVARIANCE, space.invariance, + TCP_ARGUMENT_ENDIAN, space.endian, + TCP_ARGUMENT_MIN, space.min_addr, + TCP_ARGUMENT_MAX, space.max_addr, + TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_options); mcd_put_strbuf(); } @@ -1740,20 +1747,23 @@ void handle_query_mem_spaces_c(GArray *params, void *user_ctx) /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); } else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } /* 3. send the correct memspace */ mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, query_index); g_string_append_printf(mcdserver_state.str_buf, - "%s=%s.%s=%d.%s=%d.%s=%d.%s=%d.%s=%d.%s=%ld.%s=%ld.%s=%d.", - TCP_ARGUMENT_NAME, space.name, TCP_ARGUMENT_ID, - space.id, TCP_ARGUMENT_TYPE, space.type, TCP_ARGUMENT_BITS_PER_MAU, - space.bits_per_mau, TCP_ARGUMENT_INVARIANCE, space.invariance, - TCP_ARGUMENT_ENDIAN, space.endian, TCP_ARGUMENT_MIN, space.min_addr, - TCP_ARGUMENT_MAX, space.max_addr, TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, - space.supported_access_options); + "%s=%s.%s=%u.%s=%u.%s=%u.%s=%u.%s=%u.%s=%ld.%s=%ld.%s=%u.", + TCP_ARGUMENT_NAME, space.name, + TCP_ARGUMENT_ID, space.id, + TCP_ARGUMENT_TYPE, space.type, + TCP_ARGUMENT_BITS_PER_MAU, space.bits_per_mau, + TCP_ARGUMENT_INVARIANCE, space.invariance, + TCP_ARGUMENT_ENDIAN, space.endian, + TCP_ARGUMENT_MIN, space.min_addr, + TCP_ARGUMENT_MAX, space.max_addr, + TCP_ARGUMENT_SUPPORTED_ACCESS_OPTIONS, space.supported_access_options); mcd_put_strbuf(); } @@ -1774,7 +1784,7 @@ void handle_query_reg_groups_f(GArray *params, void *user_ctx) } /* 3. send data */ mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, 0); - g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", + g_string_append_printf(mcdserver_state.str_buf, "%s=%u.%s=%s.", TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); mcd_put_strbuf(); } @@ -1795,13 +1805,13 @@ void handle_query_reg_groups_c(GArray *params, void *user_ctx) /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); } else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } /* 3. send the correct reggroup */ mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, query_index); - g_string_append_printf(mcdserver_state.str_buf, "%s=%d.%s=%s.", + g_string_append_printf(mcdserver_state.str_buf, "%s=%u.%s=%s.", TCP_ARGUMENT_ID, group.id, TCP_ARGUMENT_NAME, group.name); mcd_put_strbuf(); } @@ -1852,7 +1862,7 @@ void handle_query_regs_c(GArray *params, void *user_ctx) /* indicates this is the last packet */ g_string_printf(mcdserver_state.str_buf, "0!"); } else { - g_string_printf(mcdserver_state.str_buf, "%d!", query_index + 1); + g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } /* 3. send the correct register */ diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index f8171cba71..a436551bb1 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -13,22 +13,6 @@ #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 -typedef uint32_t mcd_trig_type_et; -/* TODO: replace mcd defines with custom layer */ -enum { - MCD_TRIG_TYPE_UNDEFINED = 0x00000000, - MCD_TRIG_TYPE_IP = 0x00000001, - MCD_TRIG_TYPE_READ = 0x00000002, - MCD_TRIG_TYPE_WRITE = 0x00000004, - MCD_TRIG_TYPE_RW = 0x00000008, - MCD_TRIG_TYPE_NOCYCLE = 0x00000010, - MCD_TRIG_TYPE_TRIG_BUS = 0x00000020, - MCD_TRIG_TYPE_COUNTER = 0x00000040, - MCD_TRIG_TYPE_CUSTOM = 0x00000080, - MCD_TRIG_TYPE_CUSTOM_LO = 0x00010000, - MCD_TRIG_TYPE_CUSTOM_HI = 0x40000000, -}; - typedef uint32_t mcd_core_event_et; /* TODO: replace mcd defines with custom layer */ enum { @@ -60,6 +44,7 @@ enum { #define QUERY_TOTAL_NUMBER 12 #define CMD_SCHEMA_LENGTH 6 #define MCD_SYSTEM_NAME "qemu-system" +#define ARGUMENT_STRING_LENGTH 64 /* tcp query packet values templates */ #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" @@ -126,9 +111,9 @@ typedef struct breakpoint_st { } breakpoint_st; typedef struct mcd_trigger_into_st { - uint32_t type; - uint32_t option; - uint32_t action; + char type[ARGUMENT_STRING_LENGTH]; + char option[ARGUMENT_STRING_LENGTH]; + char action[ARGUMENT_STRING_LENGTH]; uint32_t nr_trigger; } mcd_trigger_into_st; @@ -195,15 +180,15 @@ typedef struct mcd_reg_group_st { } mcd_reg_group_st; typedef struct xml_attrib { - char argument[64]; - char value[64]; + char argument[ARGUMENT_STRING_LENGTH]; + char value[ARGUMENT_STRING_LENGTH]; } xml_attrib; typedef struct mcd_reg_st { /* xml info */ - char name[64]; - char group[64]; - char type[64]; + char name[ARGUMENT_STRING_LENGTH]; + char group[ARGUMENT_STRING_LENGTH]; + char type[ARGUMENT_STRING_LENGTH]; uint32_t bitsize; uint32_t id; /* id used by the mcd interface */ uint32_t internal_id; /* id inside reg type */ diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index 8456352370..3a35d1062d 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -333,7 +333,7 @@ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n) int arm_mcd_set_scr(CPUState *cs, bool secure) { - /* swtiches between secure and non secure mode */ + /* switches between secure and non secure mode */ ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; /* set bit 0 to 1 if non secure, to 0 if secure*/ From patchwork Fri Oct 6 09:06:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844304 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22gT4bJSz1yqH for ; Fri, 6 Oct 2023 20:09:41 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognv-0000ph-78; Fri, 06 Oct 2023 05:07:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognc-0008Ma-EZ for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:09 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognZ-00013g-6n for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:08 -0400 Received: (qmail 19947 invoked by uid 484); 6 Oct 2023 09:06:53 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.03596 secs); 06 Oct 2023 09:06:53 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:52 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 23/29] moved all ARM code to the ARM mcdstub and added now commom header file Date: Fri, 6 Oct 2023 11:06:04 +0200 Message-Id: <20231006090610.26171-24-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcdstub.c | 244 ++------------------------------------- mcdstub/mcdstub.h | 64 +--------- mcdstub/mcdstub_common.h | 46 ++++++++ target/arm/mcdstub.c | 231 ++++++++++++++++++++++++++++++++++++ target/arm/mcdstub.h | 22 ++++ 5 files changed, 310 insertions(+), 297 deletions(-) create mode 100644 mcdstub/mcdstub_common.h diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 8e711a0a40..b19ca471ea 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -1192,104 +1192,6 @@ int int_cmp(gconstpointer a, gconstpointer b) } } -int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces) -{ - int nr_address_spaces = cpu->num_ases; - uint32_t mem_space_id = 0; - - /* - * TODO: atm we can only access physical memory addresses, - * but trace32 needs fake locical spaces to work with - */ - - mem_space_id++; - mcd_mem_space_st non_secure = { - .name = "Non Secure", - .id = mem_space_id, - .type = 34, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - .is_secure = false, - }; - g_array_append_vals(memspaces, (gconstpointer)&non_secure, 1); - mem_space_id++; - mcd_mem_space_st phys_non_secure = { - .name = "Physical (Non Secure)", - .id = mem_space_id, - .type = 18, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - .is_secure = false, - }; - g_array_append_vals(memspaces, (gconstpointer)&phys_non_secure, 1); - if(nr_address_spaces > 1) { - mem_space_id++; - mcd_mem_space_st secure = { - .name = "Secure", - .id = mem_space_id, - .type = 34, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - .is_secure = true, - }; - g_array_append_vals(memspaces, (gconstpointer)&secure, 1); - mem_space_id++; - mcd_mem_space_st phys_secure = { - .name = "Physical (Secure)", - .id = mem_space_id, - .type = 18, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - .is_secure = true, - }; - g_array_append_vals(memspaces, (gconstpointer)&phys_secure, 1); - } - /* TODO: get dynamically how the per (CP15) space is called */ - mem_space_id++; - mcd_mem_space_st gpr = { - .name = "GPR Registers", - .id = mem_space_id, - .type = 1, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - }; - g_array_append_vals(memspaces, (gconstpointer)&gpr, 1); - mem_space_id++; - mcd_mem_space_st cpr = { - .name = "CP15 Registers", - .id = mem_space_id, - .type = 1, - .bits_per_mau = 8, - .invariance = 1, - .endian = 1, - .min_addr = 0, - .max_addr = -1, - .supported_access_options = 0, - }; - g_array_append_vals(memspaces, (gconstpointer)&cpr, 1); - return 0; -} - int init_resets(GArray *resets) { mcd_reset_st system_reset = { .id = 0, .name = RESET_SYSTEM}; @@ -1360,138 +1262,6 @@ void handle_query_cores(GArray *params, void *user_ctx) g_free(arch); } -int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray *reggroups, - GArray *registers, int *current_group_id) -{ - const char *xml_filename = NULL; - const char *current_xml_filename = NULL; - const char *xml_content = NULL; - int i = 0; - - /* 1. get correct file */ - xml_filename = cc->gdb_core_xml_file; - for (i = 0; ; i++) { - current_xml_filename = xml_builtin[i][0]; - if (!current_xml_filename || (strncmp(current_xml_filename, - xml_filename, strlen(xml_filename)) == 0 - && strlen(current_xml_filename) == strlen(xml_filename))) - break; - } - /* without gpr registers we can do nothing */ - if (!current_xml_filename) { - return -1; - } - - /* 2. add group for gpr registers */ - mcd_reg_group_st gprregs = { - .name = "GPR Registers", - .id = *current_group_id - }; - g_array_append_vals(reggroups, (gconstpointer)&gprregs, 1); - *current_group_id = *current_group_id + 1; - - /* 3. parse xml */ - xml_content = xml_builtin[i][1]; - parse_reg_xml(xml_content, strlen(xml_content), registers, - MCD_ARM_REG_TYPE_GPR); - return 0; -} - -int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray *reggroups, - GArray *registers, int *current_group_id) { - const char *xml_filename = NULL; - const char *current_xml_filename = NULL; - const char *xml_content = NULL; - int i = 0; - uint8_t reg_type; - - /* iterate over all gdb xml files*/ - GDBRegisterState *r; - for (r = cpu->gdb_regs; r; r = r->next) { - xml_filename = r->xml; - xml_content = NULL; - - /* 1. get xml content */ - xml_content = arm_mcd_get_dynamic_xml(cpu, xml_filename); - if (xml_content) { - if (strcmp(xml_filename, "system-registers.xml") == 0) { - /* these are the coprocessor register */ - mcd_reg_group_st corprocessorregs = { - .name = "CP15 Registers", - .id = *current_group_id - }; - g_array_append_vals(reggroups, - (gconstpointer)&corprocessorregs, 1); - *current_group_id = *current_group_id + 1; - reg_type = MCD_ARM_REG_TYPE_CPR; - } - } else { - /* its not a coprocessor xml -> it is a static xml file */ - for (i = 0; ; i++) { - current_xml_filename = xml_builtin[i][0]; - if (!current_xml_filename || (strncmp(current_xml_filename, - xml_filename, strlen(xml_filename)) == 0 - && strlen(current_xml_filename) == strlen(xml_filename))) - break; - } - if (current_xml_filename) { - xml_content = xml_builtin[i][1]; - /* select correct reg_type */ - if (strcmp(current_xml_filename, "arm-vfp.xml") == 0) { - reg_type = MCD_ARM_REG_TYPE_VFP; - } else if (strcmp(current_xml_filename, "arm-vfp3.xml") == 0) { - reg_type = MCD_ARM_REG_TYPE_VFP; - } else if (strcmp(current_xml_filename, - "arm-vfp-sysregs.xml") == 0) { - reg_type = MCD_ARM_REG_TYPE_VFP_SYS; - } else if (strcmp(current_xml_filename, - "arm-neon.xml") == 0) { - reg_type = MCD_ARM_REG_TYPE_VFP; - } else if (strcmp(current_xml_filename, - "arm-m-profile-mve.xml") == 0) { - reg_type = MCD_ARM_REG_TYPE_MVE; - } - } else { - continue; - } - } - /* 2. parse xml */ - parse_reg_xml(xml_content, strlen(xml_content), registers, reg_type); - } - return 0; -} - -int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers, - CPUState *cpu) -{ - mcd_reg_st *current_register; - uint32_t i = 0; - - /* iterate over all registers */ - for (i = 0; i < registers->len; i++) { - current_register = &(g_array_index(registers, mcd_reg_st, i)); - current_register->id = i; - /* add mcd_reg_group_id and mcd_mem_space_id */ - if (strcmp(current_register->group, "cp_regs") == 0) { - /* coprocessor registers */ - current_register->mcd_reg_group_id = 2; - current_register->mcd_mem_space_id = 6; - /* - * get info for opcode - * for 32bit the opcode is only 16 bit long - * for 64bit it is 32 bit long - */ - current_register->opcode |= - arm_mcd_get_opcode(cpu, current_register->internal_id); - } else { - /* gpr register */ - current_register->mcd_reg_group_id = 1; - current_register->mcd_mem_space_id = 5; - } - } - return 0; -} - void handle_open_core(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; @@ -1506,28 +1276,28 @@ void handle_open_core(GArray *params, void *user_ctx) GArray *reggroups = g_array_new(false, true, sizeof(mcd_reg_group_st)); GArray *registers = g_array_new(false, true, sizeof(mcd_reg_st)); - if (strcmp(arch, "arm") == 0) { + if (strcmp(arch, MCDSTUB_ARCH_ARM) == 0) { /* TODO: make group and memspace ids dynamic */ int current_group_id = 1; /* 1. store mem spaces */ - return_value = mcd_arm_store_mem_spaces(cpu, memspaces); + return_value = arm_mcd_store_mem_spaces(cpu, memspaces); if (return_value != 0) { g_assert_not_reached(); } /* 2. parse core xml */ - return_value = mcd_arm_parse_core_xml_file(cc, reggroups, + return_value = arm_mcd_parse_core_xml_file(cc, reggroups, registers, ¤t_group_id); if (return_value != 0) { g_assert_not_reached(); } /* 3. parse other xmls */ - return_value = mcd_arm_parse_general_xml_files(cpu, reggroups, + return_value = arm_mcd_parse_general_xml_files(cpu, reggroups, registers, ¤t_group_id); if (return_value != 0) { g_assert_not_reached(); } /* 4. add additional data the the regs from the xmls */ - return_value = mcd_arm_get_additional_register_info(reggroups, + return_value = arm_mcd_get_additional_register_info(reggroups, registers, cpu); if (return_value != 0) { g_assert_not_reached(); @@ -1939,7 +1709,7 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg) /* 2. read register */ CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - if (strcmp(arch, "arm") == 0) { + if (strcmp(arch, MCDSTUB_ARCH_ARM) == 0) { g_free(arch); return arm_mcd_read_register(cpu, buf, reg_type, internal_id); } else { @@ -1959,7 +1729,7 @@ int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg) /* 2. write register */ CPUClass *cc = CPU_GET_CLASS(cpu); gchar *arch = cc->gdb_arch_name(cpu); - if (strcmp(arch, "arm") == 0) { + if (strcmp(arch, MCDSTUB_ARCH_ARM) == 0) { g_free(arch); return arm_mcd_write_register(cpu, buf, reg_type, internal_id); } else { diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index a436551bb1..d3f15da180 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -4,8 +4,7 @@ #include "exec/cpu-common.h" #include "chardev/char.h" #include "hw/core/cpu.h" -/* just used for the register xml files */ -#include "exec/gdbstub.h" +#include "mcdstub_common.h" #define MAX_PACKET_LENGTH 1024 @@ -44,7 +43,9 @@ enum { #define QUERY_TOTAL_NUMBER 12 #define CMD_SCHEMA_LENGTH 6 #define MCD_SYSTEM_NAME "qemu-system" -#define ARGUMENT_STRING_LENGTH 64 + +/* supported architectures */ +#define MCDSTUB_ARCH_ARM "arm" /* tcp query packet values templates */ #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" @@ -63,16 +64,6 @@ enum { #define STATE_STR_BREAK_RW(d) "stopped beacuse of read or write access at " #d #define STATE_STR_BREAK_UNKNOWN "stopped for unknown reason" -typedef struct GDBRegisterState { - /* needed for the used gdb functions */ - int base_reg; - int num_regs; - gdb_get_reg_cb get_reg; - gdb_set_reg_cb set_reg; - const char *xml; - struct GDBRegisterState *next; -} GDBRegisterState; - typedef struct MCDProcess { uint32_t pid; bool attached; @@ -160,48 +151,11 @@ typedef struct MCDState { /* lives in main mcdstub.c */ extern MCDState mcdserver_state; -typedef struct mcd_mem_space_st { - const char *name; - uint32_t id; - uint32_t type; - uint32_t bits_per_mau; - uint8_t invariance; - uint32_t endian; - uint64_t min_addr; - uint64_t max_addr; - uint32_t supported_access_options; - /* internal */ - bool is_secure; -} mcd_mem_space_st; - -typedef struct mcd_reg_group_st { - const char *name; - uint32_t id; -} mcd_reg_group_st; - typedef struct xml_attrib { char argument[ARGUMENT_STRING_LENGTH]; char value[ARGUMENT_STRING_LENGTH]; } xml_attrib; -typedef struct mcd_reg_st { - /* xml info */ - char name[ARGUMENT_STRING_LENGTH]; - char group[ARGUMENT_STRING_LENGTH]; - char type[ARGUMENT_STRING_LENGTH]; - uint32_t bitsize; - uint32_t id; /* id used by the mcd interface */ - uint32_t internal_id; /* id inside reg type */ - uint8_t reg_type; - /* mcd metadata */ - uint32_t mcd_reg_group_id; - uint32_t mcd_mem_space_id; - uint32_t mcd_reg_type; - uint32_t mcd_hw_thread_id; - /* data for op-code */ - uint32_t opcode; -} mcd_reg_st; - typedef struct mcd_reset_st { const char *name; uint8_t id; @@ -291,8 +245,6 @@ void handle_query_mem_spaces_c(GArray *params, void *user_ctx); void handle_query_regs_f(GArray *params, void *user_ctx); void handle_query_regs_c(GArray *params, void *user_ctx); void handle_open_server(GArray *params, void *user_ctx); -void parse_reg_xml(const char *xml, int size, GArray* registers, - uint8_t reg_type); void handle_reset(GArray *params, void *user_ctx); void handle_query_state(GArray *params, void *user_ctx); void handle_read_register(GArray *params, void *user_ctx); @@ -308,14 +260,6 @@ void handle_breakpoint_remove(GArray *params, void *user_ctx); int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr); int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr); -/* arm specific functions */ -int mcd_arm_store_mem_spaces(CPUState *cpu, GArray *memspaces); -int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray *reggroups, - GArray *registers, int *current_group_id); -int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, - GArray *registers, int *current_group_id); -int mcd_arm_get_additional_register_info(GArray *reggroups, GArray *registers, - CPUState *cpu); /* sycall handling */ void mcd_syscall_reset(void); void mcd_disable_syscalls(void); diff --git a/mcdstub/mcdstub_common.h b/mcdstub/mcdstub_common.h new file mode 100644 index 0000000000..f5175e3979 --- /dev/null +++ b/mcdstub/mcdstub_common.h @@ -0,0 +1,46 @@ +#ifndef MCDSTUB_COMMON_H +#define MCDSTUB_COMMON_H + +#define ARGUMENT_STRING_LENGTH 64 + +typedef struct mcd_mem_space_st { + const char *name; + uint32_t id; + uint32_t type; + uint32_t bits_per_mau; + uint8_t invariance; + uint32_t endian; + uint64_t min_addr; + uint64_t max_addr; + uint32_t supported_access_options; + /* internal */ + bool is_secure; +} mcd_mem_space_st; + +typedef struct mcd_reg_st { + /* xml info */ + char name[ARGUMENT_STRING_LENGTH]; + char group[ARGUMENT_STRING_LENGTH]; + char type[ARGUMENT_STRING_LENGTH]; + uint32_t bitsize; + uint32_t id; /* id used by the mcd interface */ + uint32_t internal_id; /* id inside reg type */ + uint8_t reg_type; + /* mcd metadata */ + uint32_t mcd_reg_group_id; + uint32_t mcd_mem_space_id; + uint32_t mcd_reg_type; + uint32_t mcd_hw_thread_id; + /* data for op-code */ + uint32_t opcode; +} mcd_reg_st; + +typedef struct mcd_reg_group_st { + const char *name; + uint32_t id; +} mcd_reg_group_st; + +void parse_reg_xml(const char *xml, int size, GArray* registers, + uint8_t reg_type); + +#endif /* MCDSTUB_COMMON_H */ diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index 3a35d1062d..d2a83a3cd9 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -344,3 +344,234 @@ int arm_mcd_set_scr(CPUState *cs, bool secure) } return 0; } + +int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) +{ + int nr_address_spaces = cpu->num_ases; + uint32_t mem_space_id = 0; + + /* + * TODO: atm we can only access physical memory addresses, + * but trace32 needs fake locical spaces to work with + */ + + mem_space_id++; + mcd_mem_space_st non_secure = { + .name = "Non Secure", + .id = mem_space_id, + .type = 34, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = false, + }; + g_array_append_vals(memspaces, (gconstpointer)&non_secure, 1); + mem_space_id++; + mcd_mem_space_st phys_non_secure = { + .name = "Physical (Non Secure)", + .id = mem_space_id, + .type = 18, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = false, + }; + g_array_append_vals(memspaces, (gconstpointer)&phys_non_secure, 1); + if(nr_address_spaces > 1) { + mem_space_id++; + mcd_mem_space_st secure = { + .name = "Secure", + .id = mem_space_id, + .type = 34, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = true, + }; + g_array_append_vals(memspaces, (gconstpointer)&secure, 1); + mem_space_id++; + mcd_mem_space_st phys_secure = { + .name = "Physical (Secure)", + .id = mem_space_id, + .type = 18, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + .is_secure = true, + }; + g_array_append_vals(memspaces, (gconstpointer)&phys_secure, 1); + } + /* TODO: get dynamically how the per (CP15) space is called */ + mem_space_id++; + mcd_mem_space_st gpr = { + .name = "GPR Registers", + .id = mem_space_id, + .type = 1, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(memspaces, (gconstpointer)&gpr, 1); + mem_space_id++; + mcd_mem_space_st cpr = { + .name = "CP15 Registers", + .id = mem_space_id, + .type = 1, + .bits_per_mau = 8, + .invariance = 1, + .endian = 1, + .min_addr = 0, + .max_addr = -1, + .supported_access_options = 0, + }; + g_array_append_vals(memspaces, (gconstpointer)&cpr, 1); + return 0; +} + +int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups, + GArray *registers, int *current_group_id) +{ + const char *xml_filename = NULL; + const char *current_xml_filename = NULL; + const char *xml_content = NULL; + int i = 0; + + /* 1. get correct file */ + xml_filename = cc->gdb_core_xml_file; + for (i = 0; ; i++) { + current_xml_filename = xml_builtin[i][0]; + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) == 0 + && strlen(current_xml_filename) == strlen(xml_filename))) + break; + } + /* without gpr registers we can do nothing */ + if (!current_xml_filename) { + return -1; + } + + /* 2. add group for gpr registers */ + mcd_reg_group_st gprregs = { + .name = "GPR Registers", + .id = *current_group_id + }; + g_array_append_vals(reggroups, (gconstpointer)&gprregs, 1); + *current_group_id = *current_group_id + 1; + + /* 3. parse xml */ + xml_content = xml_builtin[i][1]; + parse_reg_xml(xml_content, strlen(xml_content), registers, + MCD_ARM_REG_TYPE_GPR); + return 0; +} + +int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray *reggroups, + GArray *registers, int *current_group_id) { + const char *xml_filename = NULL; + const char *current_xml_filename = NULL; + const char *xml_content = NULL; + int i = 0; + uint8_t reg_type; + + /* iterate over all gdb xml files*/ + GDBRegisterState *r; + for (r = cpu->gdb_regs; r; r = r->next) { + xml_filename = r->xml; + xml_content = NULL; + + /* 1. get xml content */ + xml_content = arm_mcd_get_dynamic_xml(cpu, xml_filename); + if (xml_content) { + if (strcmp(xml_filename, "system-registers.xml") == 0) { + /* these are the coprocessor register */ + mcd_reg_group_st corprocessorregs = { + .name = "CP15 Registers", + .id = *current_group_id + }; + g_array_append_vals(reggroups, + (gconstpointer)&corprocessorregs, 1); + *current_group_id = *current_group_id + 1; + reg_type = MCD_ARM_REG_TYPE_CPR; + } + } else { + /* its not a coprocessor xml -> it is a static xml file */ + for (i = 0; ; i++) { + current_xml_filename = xml_builtin[i][0]; + if (!current_xml_filename || (strncmp(current_xml_filename, + xml_filename, strlen(xml_filename)) == 0 + && strlen(current_xml_filename) == strlen(xml_filename))) + break; + } + if (current_xml_filename) { + xml_content = xml_builtin[i][1]; + /* select correct reg_type */ + if (strcmp(current_xml_filename, "arm-vfp.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, "arm-vfp3.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-vfp-sysregs.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP_SYS; + } else if (strcmp(current_xml_filename, + "arm-neon.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_VFP; + } else if (strcmp(current_xml_filename, + "arm-m-profile-mve.xml") == 0) { + reg_type = MCD_ARM_REG_TYPE_MVE; + } + } else { + continue; + } + } + /* 2. parse xml */ + parse_reg_xml(xml_content, strlen(xml_content), registers, reg_type); + } + return 0; +} + +int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *registers, + CPUState *cpu) +{ + mcd_reg_st *current_register; + uint32_t i = 0; + + /* iterate over all registers */ + for (i = 0; i < registers->len; i++) { + current_register = &(g_array_index(registers, mcd_reg_st, i)); + current_register->id = i; + /* add mcd_reg_group_id and mcd_mem_space_id */ + if (strcmp(current_register->group, "cp_regs") == 0) { + /* coprocessor registers */ + current_register->mcd_reg_group_id = 2; + current_register->mcd_mem_space_id = 6; + /* + * get info for opcode + * for 32bit the opcode is only 16 bit long + * for 64bit it is 32 bit long + */ + current_register->opcode |= + arm_mcd_get_opcode(cpu, current_register->internal_id); + } else { + /* gpr register */ + current_register->mcd_reg_group_id = 1; + current_register->mcd_mem_space_id = 5; + } + } + return 0; +} + diff --git a/target/arm/mcdstub.h b/target/arm/mcdstub.h index c3b5c1ae8d..1321d5dc07 100644 --- a/target/arm/mcdstub.h +++ b/target/arm/mcdstub.h @@ -1,6 +1,21 @@ #ifndef ARM_MCDSTUB_H #define ARM_MCDSTUB_H +#include "hw/core/cpu.h" +#include "mcdstub/mcdstub_common.h" +/* just used for the register xml files */ +#include "exec/gdbstub.h" + +typedef struct GDBRegisterState { + /* needed for the used gdb functions */ + int base_reg; + int num_regs; + gdb_get_reg_cb get_reg; + gdb_set_reg_cb set_reg; + const char *xml; + struct GDBRegisterState *next; +} GDBRegisterState; + /* ids for each different type of register */ enum { MCD_ARM_REG_TYPE_GPR, @@ -17,5 +32,12 @@ int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, uint32_t n); uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); int arm_mcd_set_scr(CPUState *cs, bool secure); +int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces); +int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups, + GArray *registers, int *current_group_id); +int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray* reggroups, + GArray *registers, int *current_group_id); +int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *registers, + CPUState *cpu); #endif /* ARM_MCDSTUB_H */ From patchwork Fri Oct 6 09:06:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844311 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22ht0mLlz1yq9 for ; Fri, 6 Oct 2023 20:10:54 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognv-0000xX-Vk; Fri, 06 Oct 2023 05:07:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognc-0008Kg-5n for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:08 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogna-000142-G8 for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:07 -0400 Received: (qmail 19968 invoked by uid 484); 6 Oct 2023 09:06:54 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.074474 secs); 06 Oct 2023 09:06:54 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:53 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 24/29] step and go handlers now propperly perform global operations Date: Fri, 6 Oct 2023 11:06:05 +0200 Message-Id: <20231006090610.26171-25-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- mcdstub/mcd_shared_defines.h | 2 ++ mcdstub/mcdstub.c | 35 +++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 5cfda4121d..5fbd732252 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -78,6 +78,8 @@ /* for packets sent to qemu */ #define ARGUMENT_SEPARATOR ';' +#define NEGATIVE_FLAG 0 +#define POSITIVE_FLAG 1 /* core states */ #define CORE_STATE_RUNNING "running" diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index b19ca471ea..7613ed2c4a 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -435,7 +435,7 @@ int mcd_handle_packet(const char *line_buf) }; go_cmd_desc.cmd = (char[2]) { TCP_CHAR_GO, '\0' }; strcpy(go_cmd_desc.schema, - (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + (char[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &go_cmd_desc; } break; @@ -446,7 +446,7 @@ int mcd_handle_packet(const char *line_buf) }; step_cmd_desc.cmd = (char[2]) { TCP_CHAR_STEP, '\0' }; strcpy(step_cmd_desc.schema, - (char[2]) { ARG_SCHEMA_CORENUM, '\0' }); + (char[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' }); cmd_parser = &step_cmd_desc; } break; @@ -608,28 +608,35 @@ int mcd_handle_packet(const char *line_buf) void handle_vm_start(GArray *params, void *user_ctx) { - /* TODO: add partial restart with arguments and so on */ - uint32_t cpu_id = get_param(params, 0)->cpu_id; - CPUState *cpu = mcd_get_cpu(cpu_id); - mcd_cpu_start(cpu); + uint32_t global = get_param(params, 0)->data_uint32_t; + if (global == 1) { + mcd_vm_start(); + } else{ + uint32_t cpu_id = get_param(params, 1)->cpu_id; + CPUState *cpu = mcd_get_cpu(cpu_id); + mcd_cpu_start(cpu); + } } void handle_vm_step(GArray *params, void *user_ctx) { - /* TODO: add partial restart with arguments and so on */ - uint32_t cpu_id = get_param(params, 0)->cpu_id; - - CPUState *cpu = mcd_get_cpu(cpu_id); - int return_value = mcd_cpu_sstep(cpu); - if (return_value != 0) { - g_assert_not_reached(); + uint32_t global = get_param(params, 0)->data_uint32_t; + if (global == 1) { + /* TODO: add multicore support */ + } else{ + uint32_t cpu_id = get_param(params, 1)->cpu_id; + CPUState *cpu = mcd_get_cpu(cpu_id); + int return_value = mcd_cpu_sstep(cpu); + if (return_value != 0) { + g_assert_not_reached(); + } } } void handle_vm_stop(GArray *params, void *user_ctx) { - /* TODO: add partial stop with arguments and so on */ + /* TODO: add core dependant break option */ mcd_vm_stop(); } From patchwork Fri Oct 6 09:06:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844300 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22fk0nf6z1yqF for ; Fri, 6 Oct 2023 20:09:00 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognu-0000eT-2Y; Fri, 06 Oct 2023 05:07:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogng-0008Qs-3L for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:17 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognb-00014G-Qs for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:11 -0400 Received: (qmail 19990 invoked by uid 484); 6 Oct 2023 09:06:55 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.07256 secs); 06 Oct 2023 09:06:55 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:54 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 25/29] Doxygen documentation added Date: Fri, 6 Oct 2023 11:06:06 +0200 Message-Id: <20231006090610.26171-26-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- include/exec/mcdstub.h | 7 - include/mcdstub/syscalls.h | 2 +- mcdstub/mcd_shared_defines.h | 1 + mcdstub/mcdstub.c | 61 ++-- mcdstub/mcdstub.h | 579 ++++++++++++++++++++++++++++++++++- mcdstub/mcdstub_common.h | 18 ++ target/arm/mcdstub.c | 6 - target/arm/mcdstub.h | 105 +++++++ 8 files changed, 709 insertions(+), 70 deletions(-) diff --git a/include/exec/mcdstub.h b/include/exec/mcdstub.h index 84f7c811cb..9b7c31a951 100644 --- a/include/exec/mcdstub.h +++ b/include/exec/mcdstub.h @@ -3,13 +3,6 @@ #define DEFAULT_MCDSTUB_PORT "1235" -/* breakpoint defines */ -#define MCD_BREAKPOINT_SW 0 -#define MCD_BREAKPOINT_HW 1 -#define MCD_WATCHPOINT_WRITE 2 -#define MCD_WATCHPOINT_READ 3 -#define MCD_WATCHPOINT_ACCESS 4 - /** * mcd_tcp_server_start: start the tcp server to connect via mcd * @device: connection spec for mcd diff --git a/include/mcdstub/syscalls.h b/include/mcdstub/syscalls.h index 5547d6d29e..52a26be3a9 100644 --- a/include/mcdstub/syscalls.h +++ b/include/mcdstub/syscalls.h @@ -3,4 +3,4 @@ typedef void (*gdb_syscall_complete_cb)(CPUState *cpu, uint64_t ret, int err); -#endif /* _SYSCALLS_H_ */ +#endif /* _MCD_SYSCALLS_H_ */ diff --git a/mcdstub/mcd_shared_defines.h b/mcdstub/mcd_shared_defines.h index 5fbd732252..110d36d975 100644 --- a/mcdstub/mcd_shared_defines.h +++ b/mcdstub/mcd_shared_defines.h @@ -38,6 +38,7 @@ /* tcp query arguments */ #define QUERY_FIRST "f" #define QUERY_CONSEQUTIVE "c" +#define QUERY_END_INDEX "!" #define QUERY_ARG_SYSTEM "system" #define QUERY_ARG_CORES "cores" diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 7613ed2c4a..a468a7d7b8 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -218,12 +218,6 @@ int find_cpu_clusters(Object *child, void *opaque) s->processes = g_renew(MCDProcess, s->processes, ++s->process_num); process = &s->processes[s->process_num - 1]; - - /* - * GDB process IDs -1 and 0 are reserved. To avoid subtle errors at - * runtime, we enforce here that the machine does not use a cluster ID - * that would lead to PID 0. - */ assert(cluster->cluster_id != UINT32_MAX); process->pid = cluster->cluster_id + 1; process->attached = false; @@ -925,7 +919,7 @@ void mcd_vm_state_change(void *opaque, bool running, RunState state) int mcd_put_packet(const char *buf) { - return mcd_put_packet_binary(buf, strlen(buf), false); + return mcd_put_packet_binary(buf, strlen(buf)); } void mcd_put_strbuf(void) @@ -933,7 +927,7 @@ void mcd_put_strbuf(void) mcd_put_packet(mcdserver_state.str_buf->str); } -int mcd_put_packet_binary(const char *buf, int len, bool dump) +int mcd_put_packet_binary(const char *buf, int len) { for (;;) { g_byte_array_set_size(mcdserver_state.last_packet, 0); @@ -999,12 +993,12 @@ MCDProcess *mcd_get_process(uint32_t pid) return NULL; } -CPUState *mcd_get_cpu(uint32_t i_cpu_index) +CPUState *mcd_get_cpu(uint32_t cpu_index) { CPUState *cpu = first_cpu; while (cpu) { - if (cpu->cpu_index == i_cpu_index) { + if (cpu->cpu_index == cpu_index) { return cpu; } cpu = mcd_next_attached_cpu(cpu); @@ -1344,15 +1338,13 @@ void handle_open_core(GArray *params, void *user_ctx) void handle_query_reset_f(GArray *params, void *user_ctx) { - /* TODO: vull reset over the qemu monitor */ - /* 1. check length */ int nb_resets = mcdserver_state.resets->len; if (nb_resets == 1) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { - g_string_printf(mcdserver_state.str_buf, "1!"); + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); } /* 2. send data */ mcd_reset_st reset = g_array_index(mcdserver_state.resets, mcd_reset_st, 0); @@ -1370,7 +1362,7 @@ void handle_query_reset_c(GArray *params, void *user_ctx) int nb_groups = mcdserver_state.resets->len; if (query_index + 1 == nb_groups) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } @@ -1487,9 +1479,9 @@ void handle_query_mem_spaces_f(GArray *params, void *user_ctx) int nb_groups = memspaces->len; if (nb_groups == 1) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { - g_string_printf(mcdserver_state.str_buf, "1!"); + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); } /* 3. send data */ @@ -1522,7 +1514,7 @@ void handle_query_mem_spaces_c(GArray *params, void *user_ctx) int nb_groups = memspaces->len; if (query_index + 1 == nb_groups) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } @@ -1555,9 +1547,9 @@ void handle_query_reg_groups_f(GArray *params, void *user_ctx) int nb_groups = reggroups->len; if (nb_groups == 1) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { - g_string_printf(mcdserver_state.str_buf, "1!"); + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); } /* 3. send data */ mcd_reg_group_st group = g_array_index(reggroups, mcd_reg_group_st, 0); @@ -1580,7 +1572,7 @@ void handle_query_reg_groups_c(GArray *params, void *user_ctx) int nb_groups = reggroups->len; if (query_index + 1 == nb_groups) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } @@ -1604,9 +1596,9 @@ void handle_query_regs_f(GArray *params, void *user_ctx) int nb_regs = registers->len; if (nb_regs == 1) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { - g_string_printf(mcdserver_state.str_buf, "1!"); + g_string_printf(mcdserver_state.str_buf, "1%s", QUERY_END_INDEX); } /* 3. send data */ mcd_reg_st my_register = g_array_index(registers, mcd_reg_st, 0); @@ -1637,7 +1629,7 @@ void handle_query_regs_c(GArray *params, void *user_ctx) int nb_regs = registers->len; if (query_index + 1 == nb_regs) { /* indicates this is the last packet */ - g_string_printf(mcdserver_state.str_buf, "0!"); + g_string_printf(mcdserver_state.str_buf, "0%s", QUERY_END_INDEX); } else { g_string_printf(mcdserver_state.str_buf, "%u!", query_index + 1); } @@ -1672,19 +1664,8 @@ void handle_query_state(GArray *params, void *user_ctx) * get state info */ mcd_cpu_state_st state_info = mcdserver_state.cpu_state; - mcd_core_event_et event = MCD_CORE_EVENT_NONE; - if (state_info.memory_changed) { - event = event | MCD_CORE_EVENT_MEMORY_CHANGE; - state_info.memory_changed = false; - } - if (state_info.registers_changed) { - event = event | MCD_CORE_EVENT_REGISTER_CHANGE; - state_info.registers_changed = false; - } - if (state_info.target_was_stopped) { - event = event | MCD_CORE_EVENT_STOPPED; - state_info.target_was_stopped = false; - } + /* TODO: add event information */ + uint32_t event = 0; /* send data */ g_string_printf(mcdserver_state.str_buf, "%s=%s.%s=%u.%s=%u.%s=%u.%s=%lu.%s=%s.%s=%s.", @@ -1863,7 +1844,7 @@ void handle_write_memory(GArray *params, void *user_ctx) mcd_put_packet(TCP_EXECUTION_ERROR); return; } - /* read memory */ + /* write memory */ mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, len); if (mcd_write_memory(cpu, mem_address, mcdserver_state.mem_buf->data, len) != 0) { @@ -1879,7 +1860,7 @@ int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr) int bp_type = 0; CPUClass *cc = CPU_GET_CLASS(cpu); if (cc->gdb_stop_before_watchpoint) { - //bp_type |= BP_STOP_BEFORE_ACCESS; + /* bp_type |= BP_STOP_BEFORE_ACCESS; */ } int return_value = 0; switch (type) { @@ -1909,7 +1890,7 @@ int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr) int bp_type = 0; CPUClass *cc = CPU_GET_CLASS(cpu); if (cc->gdb_stop_before_watchpoint) { - //bp_type |= BP_STOP_BEFORE_ACCESS; + /* bp_type |= BP_STOP_BEFORE_ACCESS; */ } int return_value = 0; switch (type) { diff --git a/mcdstub/mcdstub.h b/mcdstub/mcdstub.h index d3f15da180..5412b59423 100644 --- a/mcdstub/mcdstub.h +++ b/mcdstub/mcdstub.h @@ -12,20 +12,6 @@ #define MCD_TRIG_OPT_DATA_IS_CONDITION 0x00000008 #define MCD_TRIG_ACTION_DBG_DEBUG 0x00000001 -typedef uint32_t mcd_core_event_et; -/* TODO: replace mcd defines with custom layer */ -enum { - MCD_CORE_EVENT_NONE = 0x00000000, - MCD_CORE_EVENT_MEMORY_CHANGE = 0x00000001, - MCD_CORE_EVENT_REGISTER_CHANGE = 0x00000002, - MCD_CORE_EVENT_TRACE_CHANGE = 0x00000004, - MCD_CORE_EVENT_TRIGGER_CHANGE = 0x00000008, - MCD_CORE_EVENT_STOPPED = 0x00000010, - MCD_CORE_EVENT_CHL_PENDING = 0x00000020, - MCD_CORE_EVENT_CUSTOM_LO = 0x00010000, - MCD_CORE_EVENT_CUSTOM_HI = 0x40000000, -}; - /* schema defines */ #define ARG_SCHEMA_QRYHANDLE 'q' #define ARG_SCHEMA_STRING 's' @@ -187,88 +173,649 @@ static inline int tohex(int v) void mcd_sigterm_handler(int signal); #endif +/** + * \defgroup mcdstub Main mcdstub functions + * All architecture independent mcdstub functions. + */ + +/** + * \addtogroup mcdstub + * @{ + */ + +/** + * \brief Initializes the mcdserver_state struct. + * + * This function allocates memory for the mcdserver_state struct and sets + * all of its members to their inital values. This includes setting the + * cpu_state to halted and initializing the query functions with \ref + * init_query_cmds_table. + */ void mcd_init_mcdserver_state(void); +/** + * \brief Initializes all query functions. + * + * This function adds all query functions to the mcd_query_cmds_table. This + * includes their command string, handler function and parameter schema. + * @param[out] mcd_query_cmds_table Lookup table with all query commands. + */ void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table); +/** + * \brief Initializes the resets info. + * + * This function currently only adds all theoretical possible resets to the + * resets GArray. None of the resets work at the moment. The resets are: + * "full_system_reset", "gpr_reset" and "memory_reset". + * @param[out] resets GArray with possible resets. + */ int init_resets(GArray *resets); +/** + * \brief Initializes the trigger info. + * + * This function adds the types of trigger, their possible options and actions + * to the trigger struct. + * @param[out] trigger Struct with all trigger info. + */ int init_trigger(mcd_trigger_into_st *trigger); +/** + * \brief Resets the mcdserver_state struct. + * + * This function deletes all processes connected to the mcdserver_state. + */ void reset_mcdserver_state(void); +/** + * \brief Sorts all processes and calls \ref mcd_create_default_process. + * + * This function sorts all connected processes with the qsort function. + * Afterwards, it creates a new process with \ref mcd_create_default_process. + * @param[in] s A MCDState object. + */ void create_processes(MCDState *s); +/** + * \brief Creates a default process for debugging. + * + * This function creates a new, not yet attached, process with an ID one above + * the previous maximum ID. + * @param[in] s A MCDState object. + */ void mcd_create_default_process(MCDState *s); +/** + * \brief Returns the CPU cluster of the child object. + * + * @param[in] child Object with unknown CPU cluster. + * @param[in] opaque Pointer to an MCDState object. + */ int find_cpu_clusters(Object *child, void *opaque); +/** + * \brief Compares process IDs. + * + * This function returns -1 if process "a" has a ower process ID than "b". + * If "b" has a lower ID than "a" 1 is returned and if they are qual 0 is + * returned. + * @param[in] a Process a. + * @param[in] b Process b. + */ int pid_order(const void *a, const void *b); +/** + * \brief Returns the maximum packet length of a TCP packet. + */ int mcd_chr_can_receive(void *opaque); +/** + * \brief Handles receiving a TCP packet. + * + * This function gets called by QEMU when a TCP packet is received. + * It iterates over that packet an calls \ref mcd_read_byte for each char + * of the packet. + * @param[in] buf Content of the packet. + * @param[in] size Length of the packet. + */ void mcd_chr_receive(void *opaque, const uint8_t *buf, int size); +/** + * \brief Handles a TCP client connect. + * + * This function gets called by QEMU when a TCP cliet connects to the opened + * TCP port. It attaches the first process. From here on TCP packets can be + * exchanged. + * @param[in] event Type of event. + */ void mcd_chr_event(void *opaque, QEMUChrEvent event); +/** + * \brief Returns true if debugging the selected accelerator is supported. + */ bool mcd_supports_guest_debug(void); +/** + * \brief Handles a state change of the QEMU VM. + * + * This function is called when the QEMU VM goes through a state transition. + * It stores the runstate the CPU is in to the cpu_state and when in + * \c RUN_STATE_DEBUG it collects additional data on what watchpoint was hit. + * This function also resets the singlestep behavior. + * @param[in] running True if he VM is running. + * @param[in] state The new (and active) VM run state. + */ void mcd_vm_state_change(void *opaque, bool running, RunState state); +/** + * \brief Calls \ref mcd_put_packet_binary with buf and length of buf. + * + * @param[in] buf TCP packet data. + */ int mcd_put_packet(const char *buf); -int mcd_put_packet_binary(const char *buf, int len, bool dump); +/** + * \brief Adds footer and header to the TCP packet data in buf. + * + * Besides adding header and footer, this function also stores the complete TCP + * packet in the last_packet member of the mcdserver_state. Then the packet + * gets send with the \ref mcd_put_buffer function. + * @param[in] buf TCP packet data. + * @param[in] len TCP packet length. + */ +int mcd_put_packet_binary(const char *buf, int len); +/** + * \brief Always returns true, currently needed for copatibility. + */ bool mcd_got_immediate_ack(void); +/** + * \brief Sends the buf as TCP packet with qemu_chr_fe_write_all. + * + * @param[in] buf TCP packet data. + * @param[in] len TCP packet length. + */ void mcd_put_buffer(const uint8_t *buf, int len); +/** + * \brief Returns the process of the provided CPU. + * + * @param[in] cpu The CPU state. + */ MCDProcess *mcd_get_cpu_process(CPUState *cpu); +/** + * \brief Returns the process ID of the provided CPU. + * + * @param[in] cpu The CPU state. + */ uint32_t mcd_get_cpu_pid(CPUState *cpu); +/** + * \brief Returns the process of the provided pid. + * + * @param[in] pid The process ID. + */ MCDProcess *mcd_get_process(uint32_t pid); +/** + * \brief Returns the first CPU with an attached process. + */ CPUState *mcd_first_attached_cpu(void); +/** + * \brief Returns the first CPU with an attached process starting after the + * provided cpu. + * + * @param[in] cpu The CPU to start from. + */ CPUState *mcd_next_attached_cpu(CPUState *cpu); +/** + * \brief Resends the last packet if not acknowledged and extracts the data + * from a received TCP packet. + * + * In case the last sent packet was not acknowledged from the mcdstub, + * this function resends it. + * If it was acknowledged this function parses the incoming packet + * byte by byte. + * It extracts the data in the packet and sends an + * acknowledging response when finished. Then \ref mcd_handle_packet gets + * called. + * @param[in] ch Character of the received TCP packet, which should be parsed. + */ void mcd_read_byte(uint8_t ch); +/** + * \brief Evaluates the type of received packet and chooses the correct handler. + * + * This function takes the first character of the line_buf to determine the + * type of packet. Then it selects the correct handler function and parameter + * schema. With this info it calls \ref run_cmd_parser. + * @param[in] line_buf TCP packet data. + */ int mcd_handle_packet(const char *line_buf); +/** + * \brief Calls \ref mcd_put_packet with the str_buf of the mcdserver_state. + */ void mcd_put_strbuf(void); +/** + * \brief Terminates QEMU. + * + * If the mcdserver_state has not been initialized the function exits before + * terminating QEMU. Terminting is done with the qemu_chr_fe_deinit function. + * @param[in] code An exitcode, which can be used in the future. + */ void mcd_exit(int code); +/** + * \brief Prepares the mcdserver_state before executing TCP packet functions. + * + * This function empties the str_buf and mem_buf of the mcdserver_state and + * then calls \ref process_string_cmd. In case this function fails, an empty + * TCP packet is sent back the MCD Shared Library. + * @param[in] data TCP packet data. + * @param[in] cmd Handler function (can be an array of functions). + */ void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd); +/** + * \brief Collects all parameters from the data and calls the correct handler. + * + * The parameters are extracted with the \ref cmd_parse_params function. + * This function selects the command in the cmds array, which fits the start of + * the data string. This way the correct commands is selected. + * @param[in] data TCP packet data. + * @param[in] cmds Array of possible commands. + * @param[in] num_cmds Number of commands in the cmds array. + */ int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds); +/** + * \brief Extracts all parameters from a TCP packet. + * + * This function uses the schema parameter to determine which type of parameter + * to expect. It then extracts that parameter from the data and stores it in + * the params GArray. + * @param[in] data TCP packet data. + * @param[in] schema List of expected parameters for the packet. + * @param[out] params GArray with all extracted parameters. + */ int cmd_parse_params(const char *data, const char *schema, GArray *params); +/** + * \brief Handler for the VM start TCP packet. + * + * Evaluates whether all cores or just a perticular core should get started and + * calls \ref mcd_vm_start or \ref mcd_cpu_start respectively. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_vm_start(GArray *params, void *user_ctx); +/** + * \brief Handler for the VM step TCP packet. + * + * Calls \ref mcd_cpu_sstep for the CPU which sould be stepped. Stepping all + * CPUs is currently not supported. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_vm_step(GArray *params, void *user_ctx); +/** + * \brief Handler for the VM stop TCP packet. + * + * Always calls \ref mcd_vm_stop and stops all cores. Stopping individual cores + * is currently not supported + * @param[in] params GArray with all TCP packet parameters. + */ void handle_vm_stop(GArray *params, void *user_ctx); +/** + * \brief Handler for all TCP query packets. + * + * Calls \ref process_string_cmd with all query functions in the + * mcd_query_cmds_table. \ref process_string_cmd then selects the correct one. + * This function just passes on the TCP packet data string from the parameters. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_gen_query(GArray *params, void *user_ctx); +/** + * \brief Returns the internal CPU index plus one. + * + * @param[in] cpu CPU of interest. + */ int mcd_get_cpu_index(CPUState *cpu); -CPUState *mcd_get_cpu(uint32_t i_cpu_index); +/** + * \brief Returns the CPU the index i_cpu_index. + * + * @param[in] cpu_index Index of the desired CPU. + */ +CPUState *mcd_get_cpu(uint32_t cpu_index); +/** + * \brief Handler for the core query. + * + * This function sends the type of core and number of cores currently + * simulated by QEMU. It also sends a device name for the MCD data structure. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_cores(GArray *params, void *user_ctx); +/** + * \brief Handler for the system query. + * + * Sends the system name, which is "qemu-system". + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_system(GArray *params, void *user_ctx); +/** + * \brief Returns the first CPU in the provided process. + * + * @param[in] process The process to look in. + */ CPUState *get_first_cpu_in_process(MCDProcess *process); +/** + * \brief Returns the CPU with an index equal to the thread_id. + * + * @param[in] thread_id ID of the desired CPU. + */ CPUState *find_cpu(uint32_t thread_id); +/** + * \brief Handler for opening a core. + * + * This function initializes all data for the core with the ID provided in + * the first parameter. In has a swtich case for different architectures. + * Currently only 32-Bit ARM is supported. The data includes memory spaces, + * register groups and registers themselves. They get stored into GLists where + * every entry in the list corresponds to one opened core. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_open_core(GArray *params, void *user_ctx); +/** + * \brief Handler for the first reset query. + * + * This function sends the first reset name and ID. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_reset_f(GArray *params, void *user_ctx); +/** + * \brief Handler for all consecutive reset queries. + * + * This functions sends all consecutive reset names and IDs. It uses the + * query_index parameter to determine which reset is queried next. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_reset_c(GArray *params, void *user_ctx); +/** + * \brief Handler for closing the MCD server. + * + * This function detaches the debugger (process) and frees up memory. + * Then it start the QEMU VM with \ref mcd_vm_start. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_close_server(GArray *params, void *user_ctx); +/** + * \brief Handler for closing a core. + * + * Frees all memory allocated for core specific information. This includes + * memory spaces, register groups and registers. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_close_core(GArray *params, void *user_ctx); +/** + * \brief Handler for trigger query. + * + * Sends data on the different types of trigger and their options and actions. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_trigger(GArray *params, void *user_ctx); +/** + * \brief Starts all CPUs with the vm_start function. + */ void mcd_vm_start(void); +/** + * \brief Starts the selected CPU with the cpu_resume function. + * + * @param[in] cpu The CPU about to be started. + */ void mcd_cpu_start(CPUState *cpu); +/** + * \brief Performes a step on the selected CPU. + * + * This function first sets the correct single step flags for the CPU with + * cpu_single_step and then starts the CPU with cpu_resume. + * @param[in] cpu The CPU about to be stepped. + */ int mcd_cpu_sstep(CPUState *cpu); +/** + * \brief Brings all CPUs in debug state with the vm_stop function. + */ void mcd_vm_stop(void); +/** + * \brief Handler for the first register group query. + * + * This function sends the first register group name and ID. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_reg_groups_f(GArray *params, void *user_ctx); +/** + * \brief Handler for all consecutive register group queries. + * + * This function sends all consecutive register group names and IDs. It uses + * the query_index parameter to determine which register group is queried next. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_reg_groups_c(GArray *params, void *user_ctx); +/** + * \brief Handler for the first memory space query. + * + * This function sends the first memory space name, ID, type and accessing + * options. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_mem_spaces_f(GArray *params, void *user_ctx); +/** + * \brief Handler for all consecutive memory space queries. + * + * This function sends all consecutive memory space names, IDs, types and + * accessing options. + * It uses the query_index parameter to determine + * which memory space is queried next. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_mem_spaces_c(GArray *params, void *user_ctx); +/** + * \brief Handler for the first register query. + * + * This function sends the first register with all its information. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_regs_f(GArray *params, void *user_ctx); +/** + * \brief Handler for all consecutive register queries. + * + * This function sends all consecutive registers with all their information. + * It uses the query_index parameter to determine + * which register is queried next. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_regs_c(GArray *params, void *user_ctx); +/** + * \brief Handler for opening the MCD server. + * + * This is the first function that gets called from the MCD Shared Library. + * It initializes core indepent data with the \ref init_resets and + * \reg init_trigger functions. It also send the \c TCP_HANDSHAKE_SUCCESS + * packet back to the library to confirm the mcdstub is ready for further + * communication. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_open_server(GArray *params, void *user_ctx); +/** + * \brief Handler for performing resets. + * + * This function is currently not in use. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_reset(GArray *params, void *user_ctx); +/** + * \brief Handler for the state query. + * + * This function collects all data stored in the + * cpu_state member of the mcdserver_state and formats and sends it to the + * library. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_query_state(GArray *params, void *user_ctx); +/** + * \brief Handler for reading a register. + * + * This function calls \ref mcd_read_register to read a register. The register + * data gets stored in the mem_buf byte array. The data then gets converted + * into a hex string with \ref mcd_memtohex and then send. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_read_register(GArray *params, void *user_ctx); +/** + * \brief Handler for writing a register. + * + * This function converts the incoming hex string data into a byte array with + * \ref mcd_hextomem. Then it calls \ref mcd_write_register to write to the + * register. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_write_register(GArray *params, void *user_ctx); +/** + * \brief Handler for reading memory. + * + * First, this function checks whether reading a secure memory space is + * requested and changes the access mode with \ref arm_mcd_set_scr. + * Then it calls \ref mcd_read_memory to read memory. The collected + * data gets stored in the mem_buf byte array. The data then gets converted + * into a hex string with \ref mcd_memtohex and then send. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_read_memory(GArray *params, void *user_ctx); +/** + * \brief Handler for writing memory. + * + * First, this function checks whether reading a secure memory space is + * requested and changes the access mode with \ref arm_mcd_set_scr. + * Then it converts the incoming hex string data into a byte array with + * \ref mcd_hextomem. Then it calls \ref mcd_write_memory to write to the + * register. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_write_memory(GArray *params, void *user_ctx); +/** + * \brief Reads a registers data and stores it into the buf. + * + * This function collects the register type and internal ID + * (depending on the XML file). Then it calls the architecture specific + * read function. For ARM this is \ref arm_mcd_read_register. + * @param[in] cpu CPU to which the register belongs. + * @param[out] buf Byte array with register data. + * @param[in] reg General ID of the register. + */ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); +/** + * \brief Writes data from the buf to a register. + * + * This function collects the register type and internal ID + * (depending on the XML file). Then it calls the architecture specific + * write function. For ARM this is \ref arm_mcd_write_register. + * @param[in] cpu CPU to which the register belongs. + * @param[in] buf Byte array with register data. + * @param[in] reg General ID of the register. + */ int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg); +/** + * \brief Reads memory data and stores it into the buf. + * + * This function calls cpu_memory_rw_debug or if available + * memory_rw_debug in read mode and passes on all parameters. + * @param[in] cpu CPU to which the memory belongs. + * @param[in] addr Address to start reading. + * @param[out] buf Byte array with memory data. + * @param[in] len Number of bytes to be read. + */ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); +/** + * \brief Writes data from the buf into the memory. + * + * This function calls cpu_memory_rw_debug or if available + * memory_rw_debug in write mode and passes on all parameters. + * @param[in] cpu CPU to which the memory belongs. + * @param[in] addr Address to start writing. + * @param[in] buf Byte array with memory data. + * @param[in] len Number of bytes to be written. + */ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); +/** + * \brief Handler for inserting a break- or watchpoint. + * + * This function extracts the CPU, breakpoint type and address from the + * parameters and calls \ref mcd_breakpoint_insert to insert the breakpoint. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_breakpoint_insert(GArray *params, void *user_ctx); +/** + * \brief Handler for inserting a break- or watchpoint. + * + * This function extracts the CPU, breakpoint type and address from the + * parameters and calls \ref mcd_breakpoint_remove to insert the breakpoint. + * @param[in] params GArray with all TCP packet parameters. + */ void handle_breakpoint_remove(GArray *params, void *user_ctx); +/** + * \brief Inserts a break- or watchpoint. + * + * This function evaluates the received breakpoint type and translates it + * to a known GDB breakpoint type. + * Then it calls cpu_breakpoint_insert or cpu_watchpoint_insert depending on + * the type. + * @param[in] cpu CPU to which the breakpoint should be added. + * @param[in] addr Address of the breakpoint. + * @param[in] type Breakpoint type. + */ int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr); +/** + * \brief Removes a break- or watchpoint. + * + * This function evaluates the received breakpoint type and translates it + * to a known GDB breakpoint type. + * Then it calls cpu_breakpoint_remove or cpu_watchpoint_remove depending on + * the type. + * @param[in] cpu CPU from which the breakpoint should be removed. + * @param[in] addr Address of the breakpoint. + * @param[in] type Breakpoint type. + */ int mcd_breakpoint_remove(CPUState *cpu, int type, vaddr addr); +/** @} */ + /* sycall handling */ void mcd_syscall_reset(void); void mcd_disable_syscalls(void); /* helpers */ + +/** + * \defgroup helperfunctions Helper mcdstub functions + * Supporting functions used throughout the mcdstub. + */ + +/** + * \addtogroup helperfunctions + * @{ + */ + +/** + * \brief Compares a and b and returns zero if they are equal. + * + * @param[in] a Pointer to integer a. + * @param[in] b Pointer to integer b. + */ int int_cmp(gconstpointer a, gconstpointer b); +/** + * \brief Converts a byte array into a hex string. + * + * @param[in] mem Pointer to byte array. + * @param[out] buf Pointer to hex string. + * @param[in] len Number of bytes. + */ void mcd_memtohex(GString *buf, const uint8_t *mem, int len); +/** + * \brief Converts a hex string into a byte array. + * + * @param[out] mem Pointer to byte array. + * @param[in] buf Pointer to hex string. + * @param[in] len Number of bytes. + */ void mcd_hextomem(GByteArray *mem, const char *buf, int len); +/** + * \brief Converts a string into a unsigned 64 bit integer. + * + * @param[in] in Pointer to input string. + */ uint64_t atouint64_t(const char *in); +/** + * \brief Converts a string into a unsigned 32 bit integer. + * + * @param[in] in Pointer to input string. + */ uint32_t atouint32_t(const char *in); +/** @} */ + #endif /* MCDSTUB_INTERNALS_H */ diff --git a/mcdstub/mcdstub_common.h b/mcdstub/mcdstub_common.h index f5175e3979..f6247fce70 100644 --- a/mcdstub/mcdstub_common.h +++ b/mcdstub/mcdstub_common.h @@ -40,7 +40,25 @@ typedef struct mcd_reg_group_st { uint32_t id; } mcd_reg_group_st; +/** + * \addtogroup mcdstub + * @{ + */ + +/** + * \brief Parses a GDB register XML file. + * + * This fuction extracts all registers from the provided xml file and stores + * them into the registers GArray. It extracts the register name, bitsize, type + * and group if they are set. + * @param[in] xml String with contents of the XML file. + * @param[out] registers GArray with stored registers. + * @param[in] reg_type Register type (depending on file). + * @param[in] size Number of characters in the xml string. + */ void parse_reg_xml(const char *xml, int size, GArray* registers, uint8_t reg_type); +/** @} */ + #endif /* MCDSTUB_COMMON_H */ diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index d2a83a3cd9..6c98c34673 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -350,11 +350,6 @@ int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) int nr_address_spaces = cpu->num_ases; uint32_t mem_space_id = 0; - /* - * TODO: atm we can only access physical memory addresses, - * but trace32 needs fake locical spaces to work with - */ - mem_space_id++; mcd_mem_space_st non_secure = { .name = "Non Secure", @@ -413,7 +408,6 @@ int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) }; g_array_append_vals(memspaces, (gconstpointer)&phys_secure, 1); } - /* TODO: get dynamically how the per (CP15) space is called */ mem_space_id++; mcd_mem_space_st gpr = { .name = "GPR Registers", diff --git a/target/arm/mcdstub.h b/target/arm/mcdstub.h index 1321d5dc07..daba7a04d7 100644 --- a/target/arm/mcdstub.h +++ b/target/arm/mcdstub.h @@ -25,19 +25,124 @@ enum { MCD_ARM_REG_TYPE_CPR, }; +/** + * \defgroup armmcdstub ARM mcdstub functions + * All ARM specific functions of the mcdstub. + */ + +/** + * \addtogroup armmcdstub + * @{ + */ + +/** + * \brief Returns the contents of the desired XML file. + * + * @param[in] xmlname Name of the desired XML file. + * @param[in] cs CPU state. + */ const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname); +/** + * \brief Calls the correct read function which writes data into the mem_buf. + * + * Depending on the reg_type of the register one of the following functions + * will get called: arm_mcd_read_gpr_register, arm_mcd_read_vfp_register, + * arm_mcd_read_vfp_sys_register, arm_mcd_read_mve_register and + * arm_mcd_read_cpr_register. In those the data of the requested register will + * be stored as byte array into mem_buf. The function returns zero if no bytes + * were written + * @param[out] mem_buf Byte array for register data. + * @param[in] reg_type Type of register. + * @param[in] n The register ID within its type. + * @param[in] cs CPU state. + */ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, uint32_t n); +/** + * \brief Calls the correct write function which writes data from the mem_buf. + * + * Depending on the reg_type of the register one of the following functions + * will get called: arm_mcd_write_gpr_register, arm_mcd_write_vfp_register, + * arm_mcd_write_vfp_sys_register, arm_mcd_write_mve_register and + * arm_mcd_write_cpr_register. In those the register data from mem_buf will + * be written. The function returns zero if no bytes were written. + * @param[in] mem_buf Byte array for register data. + * @param[in] reg_type Type of register. + * @param[in] n The register ID within its type. + * @param[in] cs CPU state. + */ int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, uint32_t n); +/** + * \brief Returns the opcode for a coprocessor register. + * + * This function uses the opc1, opc2, crm and crn members of the register to + * create the opcode. The formular for creating the opcode is determined by ARM. + * @param[in] n The register ID of the CP register. + * @param[in] cs CPU state. + */ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); +/** + * \brief Sets the scr_el3 register according to the secure parameter. + * + * If secure is true, the first bit of the scr_el3 register gets set to 0, + * if not it gets set to 1. + * @param[in] secure True when secure is requested. + * @param[in] cs CPU state. + */ int arm_mcd_set_scr(CPUState *cs, bool secure); +/** + * \brief Stores all 32-Bit ARM specific memory spaces. + * + * This function stores the memory spaces into the memspaces GArray. + * It only stores secure memory spaces if the CPU has more than one address + * space. It also stores a GPR and a CP15 register memory space. + * @param[out] memspaces GArray of memory spaces. + * @param[in] cpu CPU state. + */ int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces); +/** + * \brief Parses the GPR registers. + * + * This function parses the core XML file, which includes the GPR registers. + * The regsters get stored in a GArray and a GPR register group is stored in a + * second GArray. + * @param[out] reggroups GArray of register groups. + * @param[out] registers GArray of registers. + * @param[in] cc The CPU class. + * @param[in,out] current_group_id The current group ID. It increases after + * each group. + */ int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups, GArray *registers, int *current_group_id); +/** + * \brief Parses all but the GPR registers. + * + * This function parses all XML files except for the core XML file. + * The regsters get stored in a GArray and if the system-registers.xml file is + * parsed, it also adds a CP15 register group. + * @param[out] reggroups GArray of register groups. + * @param[out] registers GArray of registers. + * @param[in] cpu The CPU state. + * @param[in,out] current_group_id The current group ID. It increases after + * each added group. + */ int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray *registers, int *current_group_id); +/** + * \brief Adds additional data to parsed registers. + * + * This function is called, after \ref arm_mcd_parse_core_xml_file and + * \ref arm_mcd_parse_core_xml_file. It adds additional data for all already + * parsed registers. The registers get a correct ID, group, memory space and + * opcode, if they are CP15 registers. + * @param[in] reggroups GArray of register groups. + * @param[in,out] registers GArray of registers. + * @param[in] cpu The CPU state. + */ int arm_mcd_get_additional_register_info(GArray *reggroups, GArray *registers, CPUState *cpu); +/** @} */ + #endif /* ARM_MCDSTUB_H */ From patchwork Fri Oct 6 09:06:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844296 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22dx11wqz1yqH for ; Fri, 6 Oct 2023 20:08:21 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognw-00011J-CZ; Fri, 06 Oct 2023 05:07:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognf-0008Qi-NL for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:11 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognd-00014V-7h for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:10 -0400 Received: (qmail 20012 invoked by uid 484); 6 Oct 2023 09:06:57 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 4e-06 secs); 06 Oct 2023 09:06:57 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:56 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 26/29] moved all mcd related header files into include/mcdstub Date: Fri, 6 Oct 2023 11:06:07 +0200 Message-Id: <20231006090610.26171-27-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- target/arm/mcdstub.h => include/mcdstub/arm_mcdstub.h | 2 +- {mcdstub => include/mcdstub}/mcd_shared_defines.h | 0 {mcdstub => include/mcdstub}/mcdstub.h | 0 {mcdstub => include/mcdstub}/mcdstub_common.h | 0 mcdstub/mcd_syscalls.c | 2 +- mcdstub/mcdstub.c | 6 +++--- target/arm/mcdstub.c | 3 ++- 7 files changed, 7 insertions(+), 6 deletions(-) rename target/arm/mcdstub.h => include/mcdstub/arm_mcdstub.h (99%) rename {mcdstub => include/mcdstub}/mcd_shared_defines.h (100%) rename {mcdstub => include/mcdstub}/mcdstub.h (100%) rename {mcdstub => include/mcdstub}/mcdstub_common.h (100%) diff --git a/target/arm/mcdstub.h b/include/mcdstub/arm_mcdstub.h similarity index 99% rename from target/arm/mcdstub.h rename to include/mcdstub/arm_mcdstub.h index daba7a04d7..3db271150a 100644 --- a/target/arm/mcdstub.h +++ b/include/mcdstub/arm_mcdstub.h @@ -2,7 +2,7 @@ #define ARM_MCDSTUB_H #include "hw/core/cpu.h" -#include "mcdstub/mcdstub_common.h" +#include "mcdstub_common.h" /* just used for the register xml files */ #include "exec/gdbstub.h" diff --git a/mcdstub/mcd_shared_defines.h b/include/mcdstub/mcd_shared_defines.h similarity index 100% rename from mcdstub/mcd_shared_defines.h rename to include/mcdstub/mcd_shared_defines.h diff --git a/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h similarity index 100% rename from mcdstub/mcdstub.h rename to include/mcdstub/mcdstub.h diff --git a/mcdstub/mcdstub_common.h b/include/mcdstub/mcdstub_common.h similarity index 100% rename from mcdstub/mcdstub_common.h rename to include/mcdstub/mcdstub_common.h diff --git a/mcdstub/mcd_syscalls.c b/mcdstub/mcd_syscalls.c index eaa6853335..e363a249ca 100644 --- a/mcdstub/mcd_syscalls.c +++ b/mcdstub/mcd_syscalls.c @@ -3,7 +3,7 @@ #include "semihosting/semihost.h" #include "sysemu/runstate.h" #include "mcdstub/syscalls.h" -#include "mcdstub.h" +#include "mcdstub/mcdstub.h" typedef struct { char syscall_buf[256]; diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index a468a7d7b8..4f9fafe749 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -25,11 +25,11 @@ #include "monitor/monitor.h" /* mcdstub header files */ -#include "mcd_shared_defines.h" -#include "mcdstub.h" +#include "mcdstub/mcd_shared_defines.h" +#include "mcdstub/mcdstub.h" /* architecture specific stubs */ -#include "target/arm/mcdstub.h" +#include "mcdstub/arm_mcdstub.h" typedef struct { CharBackend chr; diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index 6c98c34673..1b82b9d439 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -4,7 +4,8 @@ #include "sysemu/tcg.h" #include "internals.h" #include "cpregs.h" -#include "mcdstub.h" + +#include "mcdstub/arm_mcdstub.h" static inline int mcd_get_reg32(GByteArray *buf, uint32_t val) { From patchwork Fri Oct 6 09:06:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844302 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22ft5ZTMz1yqH for ; Fri, 6 Oct 2023 20:09:10 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qognw-00015W-Vk; Fri, 06 Oct 2023 05:07:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogni-00006q-7l for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:18 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogng-00014k-IM for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:13 -0400 Received: (qmail 20040 invoked by uid 484); 6 Oct 2023 09:06:59 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.146627 secs); 06 Oct 2023 09:06:59 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:06:58 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 27/29] MCD stub entry added to maintainers file Date: Fri, 6 Oct 2023 11:06:08 +0200 Message-Id: <20231006090610.26171-28-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder Acked-by: Alex Bennée --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 81625f036b..b6bc8201bb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2832,6 +2832,15 @@ F: tests/tcg/multiarch/gdbstub/ F: scripts/feature_to_c.sh F: scripts/probe-gdb-support.py +MCD stub +M: Nicolas Eder +R: Alex Bennée +S: Maintained +F: mcdstub/* +F: include/exec/mcdstub.h +F: include/mcdstub/* +F: target/arm/mcdstub.c + Memory API M: Paolo Bonzini M: Peter Xu From patchwork Fri Oct 6 09:06:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844298 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22f861Sgz1yqF for ; Fri, 6 Oct 2023 20:08:32 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogny-0001Dr-2l; Fri, 06 Oct 2023 05:07:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognk-00007G-JG for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:18 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qogni-000158-4Q for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:16 -0400 Received: (qmail 20078 invoked by uid 484); 6 Oct 2023 09:07:01 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.279629 secs); 06 Oct 2023 09:07:01 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:07:00 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 28/29] added description to out-commented gdb function Date: Fri, 6 Oct 2023 11:06:09 +0200 Message-Id: <20231006090610.26171-29-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- softmmu/cpus.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/softmmu/cpus.c b/softmmu/cpus.c index b1807e6d7b..5d0657bbe5 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -306,7 +306,10 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - /*gdb_set_stop_cpu(cpu);*/ + /* + * TODO: was gdb_set_stop_cpu(cpu), need to abstract options to + * a QOM class. + */ qemu_system_debug_request(); cpu->stopped = true; } From patchwork Fri Oct 6 09:06:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "nicolas.eder@lauterbach.com" X-Patchwork-Id: 1844301 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4S22fs68NWz1yqF for ; Fri, 6 Oct 2023 20:09:09 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qogny-0001Jz-Vx; Fri, 06 Oct 2023 05:07:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognq-0000Vi-Bz for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:23 -0400 Received: from smtp1.lauterbach.com ([62.154.241.196]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qognk-00015P-OJ for qemu-devel@nongnu.org; Fri, 06 Oct 2023 05:07:22 -0400 Received: (qmail 20108 invoked by uid 484); 6 Oct 2023 09:07:03 -0000 X-Qmail-Scanner-Diagnostics: from nedpc1.intern.lauterbach.com by smtp1.lauterbach.com (envelope-from , uid 484) with qmail-scanner-2.11 (mhr: 1.0. clamdscan: 0.99/21437. spamassassin: 3.4.0. Clear:RC:1(10.2.11.92):. Processed in 0.215779 secs); 06 Oct 2023 09:07:03 -0000 Received: from nedpc1.intern.lauterbach.com (Authenticated_SSL:neder@[10.2.11.92]) (envelope-sender ) by smtp1.lauterbach.com (qmail-ldap-1.03) with TLS_AES_256_GCM_SHA384 encrypted SMTP for ; 6 Oct 2023 09:07:02 -0000 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?utf-8?q?Alex_Benn=C3=A9e?= , Nicolas Eder Subject: [PATCH v2 29/29] introducing the DebugClass. It is used to abstract the gdb/mcd set_stop_cpu function. Date: Fri, 6 Oct 2023 11:06:10 +0200 Message-Id: <20231006090610.26171-30-nicolas.eder@lauterbach.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231006090610.26171-1-nicolas.eder@lauterbach.com> References: <20231006090610.26171-1-nicolas.eder@lauterbach.com> MIME-Version: 1.0 X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass client-ip=62.154.241.196; envelope-from=nicolas.eder@lauterbach.com; helo=smtp1.lauterbach.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: neder --- MAINTAINERS | 3 + debug/debug-common.c | 42 ++++++++++++ debug/debug-gdb.c | 24 +++++++ debug/debug-mcd.c | 25 +++++++ gdbstub/meson.build | 4 +- gdbstub/softmmu.c | 4 ++ gdbstub/user.c | 2 + include/exec/gdbstub.h | 5 ++ include/hw/boards.h | 1 + include/mcdstub/arm_mcdstub.h | 25 +++---- include/mcdstub/mcdstub.h | 122 ++++++++++++++++++---------------- include/qemu/debug.h | 19 ++++++ include/qemu/typedefs.h | 2 + mcdstub/mcdstub.c | 51 +++++++++----- mcdstub/meson.build | 4 +- softmmu/cpus.c | 12 ++-- target/arm/mcdstub.c | 17 +---- 17 files changed, 247 insertions(+), 115 deletions(-) create mode 100644 debug/debug-common.c create mode 100644 debug/debug-gdb.c create mode 100644 debug/debug-mcd.c create mode 100644 include/qemu/debug.h diff --git a/MAINTAINERS b/MAINTAINERS index b6bc8201bb..b2a1d2bfc6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2839,6 +2839,9 @@ S: Maintained F: mcdstub/* F: include/exec/mcdstub.h F: include/mcdstub/* +F: include/qemu/debug.h +F: debug/debug-common.c +F: debug/debug-mcd.c F: target/arm/mcdstub.c Memory API diff --git a/debug/debug-common.c b/debug/debug-common.c new file mode 100644 index 0000000000..8f41b4e6cb --- /dev/null +++ b/debug/debug-common.c @@ -0,0 +1,42 @@ +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.h" +#include "qemu/debug.h" +#include "qom/object_interfaces.h" + +static void debug_instance_init(Object *obj) +{ +} + +static void debug_finalize(Object *obj) +{ +} + +static void debug_class_init(ObjectClass *oc, void *data) +{ +} + +static const TypeInfo debug_info = { + .name = TYPE_DEBUG, + .parent = TYPE_OBJECT, + .instance_size = sizeof(DebugState), + .instance_init = debug_instance_init, + .instance_finalize = debug_finalize, + .class_size = sizeof(DebugClass), + .class_init = debug_class_init +}; + +static void debug_register_types(void) +{ + type_register_static(&debug_info); +} + +type_init(debug_register_types); diff --git a/debug/debug-gdb.c b/debug/debug-gdb.c new file mode 100644 index 0000000000..9c7bcda95f --- /dev/null +++ b/debug/debug-gdb.c @@ -0,0 +1,24 @@ +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.h" +#include "exec/gdbstub.h" +#include "qemu/debug.h" + +void gdb_init_debug_class(void) +{ + Object *obj; + obj = object_new(TYPE_DEBUG); + DebugState *ds = DEBUG(obj); + DebugClass *dc = DEBUG_GET_CLASS(ds); + dc->set_stop_cpu = gdb_set_stop_cpu; + MachineState *ms = MACHINE(qdev_get_machine()); + ms->debug_state = ds; +} diff --git a/debug/debug-mcd.c b/debug/debug-mcd.c new file mode 100644 index 0000000000..2d3a31be15 --- /dev/null +++ b/debug/debug-mcd.c @@ -0,0 +1,25 @@ +#include "qemu/osdep.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/cpu/cluster.h" +#include "hw/boards.h" +#include "sysemu/hw_accel.h" +#include "sysemu/runstate.h" +#include "exec/replay-core.h" +#include "exec/hwaddr.h" +#include "mcdstub/mcdstub.h" +#include "qemu/debug.h" +#include "qom/object_interfaces.h" + +void mcd_init_debug_class(void) +{ + Object *obj; + obj = object_new(TYPE_DEBUG); + DebugState *ds = DEBUG(obj); + DebugClass *dc = DEBUG_GET_CLASS(ds); + dc->set_stop_cpu = mcd_set_stop_cpu; + MachineState *ms = MACHINE(qdev_get_machine()); + ms->debug_state = ds; +} diff --git a/gdbstub/meson.build b/gdbstub/meson.build index a5a1f4e433..e4ee9e5035 100644 --- a/gdbstub/meson.build +++ b/gdbstub/meson.build @@ -11,8 +11,8 @@ gdb_user_ss = ss.source_set() gdb_system_ss = ss.source_set() # We build two versions of gdbstub, one for each mode -gdb_user_ss.add(files('gdbstub.c', 'user.c')) -gdb_system_ss.add(files('gdbstub.c', 'softmmu.c')) +gdb_user_ss.add(files('gdbstub.c', 'user.c', '../debug/debug-gdb.c')) +gdb_system_ss.add(files('gdbstub.c', 'softmmu.c', '../debug/debug-gdb.c')) gdb_user_ss = gdb_user_ss.apply(config_targetos, strict: false) gdb_system_ss = gdb_system_ss.apply(config_targetos, strict: false) diff --git a/gdbstub/softmmu.c b/gdbstub/softmmu.c index 9f0b8b5497..27af26d308 100644 --- a/gdbstub/softmmu.c +++ b/gdbstub/softmmu.c @@ -14,6 +14,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/cutils.h" +#include "qemu/debug.h" #include "exec/gdbstub.h" #include "gdbstub/syscalls.h" #include "exec/hwaddr.h" @@ -405,6 +406,9 @@ int gdbserver_start(const char *device) gdbserver_system_state.mon_chr = mon_chr; gdb_syscall_reset(); + /* create new debug object */ + gdb_init_debug_class(); + return 0; } diff --git a/gdbstub/user.c b/gdbstub/user.c index 7ab6e5d975..ecffc354b1 100644 --- a/gdbstub/user.c +++ b/gdbstub/user.c @@ -326,8 +326,10 @@ int gdbserver_start(const char *port_or_path) } if (port > 0 && gdb_accept_tcp(gdb_fd)) { + gdb_init_debug_class(); return 0; } else if (gdb_accept_socket(gdb_fd)) { + gdb_init_debug_class(); gdbserver_user_state.socket_path = g_strdup(port_or_path); return 0; } diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index 16a139043f..d0d4feebef 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -51,4 +51,9 @@ bool gdb_has_xml(void); /* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */ extern const char *const xml_builtin[][2]; +/** + * gdb_init_debug_class() - initialize gdb-specific DebugClass + */ +void gdb_init_debug_class(void); + #endif diff --git a/include/hw/boards.h b/include/hw/boards.h index 55a64a13fd..e37cddab26 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -380,6 +380,7 @@ struct MachineState { CpuTopology smp; struct NVDIMMState *nvdimms_state; struct NumaState *numa_state; + DebugState *debug_state; }; #define DEFINE_MACHINE(namestr, machine_initfn) \ diff --git a/include/mcdstub/arm_mcdstub.h b/include/mcdstub/arm_mcdstub.h index 3db271150a..93bf71e133 100644 --- a/include/mcdstub/arm_mcdstub.h +++ b/include/mcdstub/arm_mcdstub.h @@ -37,14 +37,14 @@ enum { /** * \brief Returns the contents of the desired XML file. - * + * * @param[in] xmlname Name of the desired XML file. * @param[in] cs CPU state. */ const char *arm_mcd_get_dynamic_xml(CPUState *cs, const char *xmlname); /** * \brief Calls the correct read function which writes data into the mem_buf. - * + * * Depending on the reg_type of the register one of the following functions * will get called: arm_mcd_read_gpr_register, arm_mcd_read_vfp_register, * arm_mcd_read_vfp_sys_register, arm_mcd_read_mve_register and @@ -60,7 +60,7 @@ int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, uint32_t n); /** * \brief Calls the correct write function which writes data from the mem_buf. - * + * * Depending on the reg_type of the register one of the following functions * will get called: arm_mcd_write_gpr_register, arm_mcd_write_vfp_register, * arm_mcd_write_vfp_sys_register, arm_mcd_write_mve_register and @@ -75,25 +75,16 @@ int arm_mcd_write_register(CPUState *cs, GByteArray *mem_buf, uint8_t reg_type, uint32_t n); /** * \brief Returns the opcode for a coprocessor register. - * + * * This function uses the opc1, opc2, crm and crn members of the register to * create the opcode. The formular for creating the opcode is determined by ARM. * @param[in] n The register ID of the CP register. * @param[in] cs CPU state. */ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n); -/** - * \brief Sets the scr_el3 register according to the secure parameter. - * - * If secure is true, the first bit of the scr_el3 register gets set to 0, - * if not it gets set to 1. - * @param[in] secure True when secure is requested. - * @param[in] cs CPU state. - */ -int arm_mcd_set_scr(CPUState *cs, bool secure); /** * \brief Stores all 32-Bit ARM specific memory spaces. - * + * * This function stores the memory spaces into the memspaces GArray. * It only stores secure memory spaces if the CPU has more than one address * space. It also stores a GPR and a CP15 register memory space. @@ -103,7 +94,7 @@ int arm_mcd_set_scr(CPUState *cs, bool secure); int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces); /** * \brief Parses the GPR registers. - * + * * This function parses the core XML file, which includes the GPR registers. * The regsters get stored in a GArray and a GPR register group is stored in a * second GArray. @@ -117,7 +108,7 @@ int arm_mcd_parse_core_xml_file(CPUClass *cc, GArray *reggroups, GArray *registers, int *current_group_id); /** * \brief Parses all but the GPR registers. - * + * * This function parses all XML files except for the core XML file. * The regsters get stored in a GArray and if the system-registers.xml file is * parsed, it also adds a CP15 register group. @@ -131,7 +122,7 @@ int arm_mcd_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArray *registers, int *current_group_id); /** * \brief Adds additional data to parsed registers. - * + * * This function is called, after \ref arm_mcd_parse_core_xml_file and * \ref arm_mcd_parse_core_xml_file. It adds additional data for all already * parsed registers. The registers get a correct ID, group, memory space and diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h index 5412b59423..88f1ee58a7 100644 --- a/include/mcdstub/mcdstub.h +++ b/include/mcdstub/mcdstub.h @@ -217,6 +217,10 @@ int init_resets(GArray *resets); * @param[out] trigger Struct with all trigger info. */ int init_trigger(mcd_trigger_into_st *trigger); +/** + * mcd_init_debug_class() - initialize mcd-specific DebugClass + */ +void mcd_init_debug_class(void); /** * \brief Resets the mcdserver_state struct. * @@ -251,7 +255,7 @@ int find_cpu_clusters(Object *child, void *opaque); * * This function returns -1 if process "a" has a ower process ID than "b". * If "b" has a lower ID than "a" 1 is returned and if they are qual 0 is - * returned. + * returned. * @param[in] a Process a. * @param[in] b Process b. */ @@ -262,7 +266,7 @@ int pid_order(const void *a, const void *b); int mcd_chr_can_receive(void *opaque); /** * \brief Handles receiving a TCP packet. - * + * * This function gets called by QEMU when a TCP packet is received. * It iterates over that packet an calls \ref mcd_read_byte for each char * of the packet. @@ -272,7 +276,7 @@ int mcd_chr_can_receive(void *opaque); void mcd_chr_receive(void *opaque, const uint8_t *buf, int size); /** * \brief Handles a TCP client connect. - * + * * This function gets called by QEMU when a TCP cliet connects to the opened * TCP port. It attaches the first process. From here on TCP packets can be * exchanged. @@ -285,7 +289,7 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event); bool mcd_supports_guest_debug(void); /** * \brief Handles a state change of the QEMU VM. - * + * * This function is called when the QEMU VM goes through a state transition. * It stores the runstate the CPU is in to the cpu_state and when in * \c RUN_STATE_DEBUG it collects additional data on what watchpoint was hit. @@ -296,13 +300,13 @@ bool mcd_supports_guest_debug(void); void mcd_vm_state_change(void *opaque, bool running, RunState state); /** * \brief Calls \ref mcd_put_packet_binary with buf and length of buf. - * + * * @param[in] buf TCP packet data. */ int mcd_put_packet(const char *buf); /** * \brief Adds footer and header to the TCP packet data in buf. - * + * * Besides adding header and footer, this function also stores the complete TCP * packet in the last_packet member of the mcdserver_state. Then the packet * gets send with the \ref mcd_put_buffer function. @@ -316,26 +320,30 @@ int mcd_put_packet_binary(const char *buf, int len); bool mcd_got_immediate_ack(void); /** * \brief Sends the buf as TCP packet with qemu_chr_fe_write_all. - * + * * @param[in] buf TCP packet data. * @param[in] len TCP packet length. */ void mcd_put_buffer(const uint8_t *buf, int len); /** * \brief Returns the process of the provided CPU. - * + * * @param[in] cpu The CPU state. */ MCDProcess *mcd_get_cpu_process(CPUState *cpu); +/** + * \brief Sets c_cpu to the just stopped CPU. + */ +void mcd_set_stop_cpu(CPUState *cpu); /** * \brief Returns the process ID of the provided CPU. - * + * * @param[in] cpu The CPU state. */ uint32_t mcd_get_cpu_pid(CPUState *cpu); /** * \brief Returns the process of the provided pid. - * + * * @param[in] pid The process ID. */ MCDProcess *mcd_get_process(uint32_t pid); @@ -344,16 +352,16 @@ MCDProcess *mcd_get_process(uint32_t pid); */ CPUState *mcd_first_attached_cpu(void); /** - * \brief Returns the first CPU with an attached process starting after the + * \brief Returns the first CPU with an attached process starting after the * provided cpu. - * + * * @param[in] cpu The CPU to start from. */ CPUState *mcd_next_attached_cpu(CPUState *cpu); /** * \brief Resends the last packet if not acknowledged and extracts the data * from a received TCP packet. - * + * * In case the last sent packet was not acknowledged from the mcdstub, * this function resends it. * If it was acknowledged this function parses the incoming packet @@ -366,7 +374,7 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu); void mcd_read_byte(uint8_t ch); /** * \brief Evaluates the type of received packet and chooses the correct handler. - * + * * This function takes the first character of the line_buf to determine the * type of packet. Then it selects the correct handler function and parameter * schema. With this info it calls \ref run_cmd_parser. @@ -379,7 +387,7 @@ int mcd_handle_packet(const char *line_buf); void mcd_put_strbuf(void); /** * \brief Terminates QEMU. - * + * * If the mcdserver_state has not been initialized the function exits before * terminating QEMU. Terminting is done with the qemu_chr_fe_deinit function. * @param[in] code An exitcode, which can be used in the future. @@ -387,7 +395,7 @@ void mcd_put_strbuf(void); void mcd_exit(int code); /** * \brief Prepares the mcdserver_state before executing TCP packet functions. - * + * * This function empties the str_buf and mem_buf of the mcdserver_state and * then calls \ref process_string_cmd. In case this function fails, an empty * TCP packet is sent back the MCD Shared Library. @@ -397,7 +405,7 @@ void mcd_exit(int code); void run_cmd_parser(const char *data, const MCDCmdParseEntry *cmd); /** * \brief Collects all parameters from the data and calls the correct handler. - * + * * The parameters are extracted with the \ref cmd_parse_params function. * This function selects the command in the cmds array, which fits the start of * the data string. This way the correct commands is selected. @@ -409,7 +417,7 @@ int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParseEntry *cmds, int num_cmds); /** * \brief Extracts all parameters from a TCP packet. - * + * * This function uses the schema parameter to determine which type of parameter * to expect. It then extracts that parameter from the data and stores it in * the params GArray. @@ -420,7 +428,7 @@ int process_string_cmd(void *user_ctx, const char *data, int cmd_parse_params(const char *data, const char *schema, GArray *params); /** * \brief Handler for the VM start TCP packet. - * + * * Evaluates whether all cores or just a perticular core should get started and * calls \ref mcd_vm_start or \ref mcd_cpu_start respectively. * @param[in] params GArray with all TCP packet parameters. @@ -428,7 +436,7 @@ int cmd_parse_params(const char *data, const char *schema, GArray *params); void handle_vm_start(GArray *params, void *user_ctx); /** * \brief Handler for the VM step TCP packet. - * + * * Calls \ref mcd_cpu_sstep for the CPU which sould be stepped. Stepping all * CPUs is currently not supported. * @param[in] params GArray with all TCP packet parameters. @@ -436,7 +444,7 @@ void handle_vm_start(GArray *params, void *user_ctx); void handle_vm_step(GArray *params, void *user_ctx); /** * \brief Handler for the VM stop TCP packet. - * + * * Always calls \ref mcd_vm_stop and stops all cores. Stopping individual cores * is currently not supported * @param[in] params GArray with all TCP packet parameters. @@ -444,7 +452,7 @@ void handle_vm_step(GArray *params, void *user_ctx); void handle_vm_stop(GArray *params, void *user_ctx); /** * \brief Handler for all TCP query packets. - * + * * Calls \ref process_string_cmd with all query functions in the * mcd_query_cmds_table. \ref process_string_cmd then selects the correct one. * This function just passes on the TCP packet data string from the parameters. @@ -453,19 +461,19 @@ void handle_vm_stop(GArray *params, void *user_ctx); void handle_gen_query(GArray *params, void *user_ctx); /** * \brief Returns the internal CPU index plus one. - * + * * @param[in] cpu CPU of interest. */ int mcd_get_cpu_index(CPUState *cpu); /** * \brief Returns the CPU the index i_cpu_index. - * + * * @param[in] cpu_index Index of the desired CPU. */ CPUState *mcd_get_cpu(uint32_t cpu_index); /** * \brief Handler for the core query. - * + * * This function sends the type of core and number of cores currently * simulated by QEMU. It also sends a device name for the MCD data structure. * @param[in] params GArray with all TCP packet parameters. @@ -473,26 +481,26 @@ CPUState *mcd_get_cpu(uint32_t cpu_index); void handle_query_cores(GArray *params, void *user_ctx); /** * \brief Handler for the system query. - * + * * Sends the system name, which is "qemu-system". * @param[in] params GArray with all TCP packet parameters. */ void handle_query_system(GArray *params, void *user_ctx); /** * \brief Returns the first CPU in the provided process. - * + * * @param[in] process The process to look in. */ CPUState *get_first_cpu_in_process(MCDProcess *process); /** * \brief Returns the CPU with an index equal to the thread_id. - * + * * @param[in] thread_id ID of the desired CPU. */ CPUState *find_cpu(uint32_t thread_id); /** * \brief Handler for opening a core. - * + * * This function initializes all data for the core with the ID provided in * the first parameter. In has a swtich case for different architectures. * Currently only 32-Bit ARM is supported. The data includes memory spaces, @@ -503,14 +511,14 @@ CPUState *find_cpu(uint32_t thread_id); void handle_open_core(GArray *params, void *user_ctx); /** * \brief Handler for the first reset query. - * + * * This function sends the first reset name and ID. * @param[in] params GArray with all TCP packet parameters. */ void handle_query_reset_f(GArray *params, void *user_ctx); /** * \brief Handler for all consecutive reset queries. - * + * * This functions sends all consecutive reset names and IDs. It uses the * query_index parameter to determine which reset is queried next. * @param[in] params GArray with all TCP packet parameters. @@ -518,7 +526,7 @@ void handle_query_reset_f(GArray *params, void *user_ctx); void handle_query_reset_c(GArray *params, void *user_ctx); /** * \brief Handler for closing the MCD server. - * + * * This function detaches the debugger (process) and frees up memory. * Then it start the QEMU VM with \ref mcd_vm_start. * @param[in] params GArray with all TCP packet parameters. @@ -526,7 +534,7 @@ void handle_query_reset_c(GArray *params, void *user_ctx); void handle_close_server(GArray *params, void *user_ctx); /** * \brief Handler for closing a core. - * + * * Frees all memory allocated for core specific information. This includes * memory spaces, register groups and registers. * @param[in] params GArray with all TCP packet parameters. @@ -534,7 +542,7 @@ void handle_close_server(GArray *params, void *user_ctx); void handle_close_core(GArray *params, void *user_ctx); /** * \brief Handler for trigger query. - * + * * Sends data on the different types of trigger and their options and actions. * @param[in] params GArray with all TCP packet parameters. */ @@ -545,13 +553,13 @@ void handle_query_trigger(GArray *params, void *user_ctx); void mcd_vm_start(void); /** * \brief Starts the selected CPU with the cpu_resume function. - * + * * @param[in] cpu The CPU about to be started. */ void mcd_cpu_start(CPUState *cpu); /** * \brief Performes a step on the selected CPU. - * + * * This function first sets the correct single step flags for the CPU with * cpu_single_step and then starts the CPU with cpu_resume. * @param[in] cpu The CPU about to be stepped. @@ -563,14 +571,14 @@ int mcd_cpu_sstep(CPUState *cpu); void mcd_vm_stop(void); /** * \brief Handler for the first register group query. - * + * * This function sends the first register group name and ID. * @param[in] params GArray with all TCP packet parameters. */ void handle_query_reg_groups_f(GArray *params, void *user_ctx); /** * \brief Handler for all consecutive register group queries. - * + * * This function sends all consecutive register group names and IDs. It uses * the query_index parameter to determine which register group is queried next. * @param[in] params GArray with all TCP packet parameters. @@ -578,7 +586,7 @@ void handle_query_reg_groups_f(GArray *params, void *user_ctx); void handle_query_reg_groups_c(GArray *params, void *user_ctx); /** * \brief Handler for the first memory space query. - * + * * This function sends the first memory space name, ID, type and accessing * options. * @param[in] params GArray with all TCP packet parameters. @@ -586,7 +594,7 @@ void handle_query_reg_groups_c(GArray *params, void *user_ctx); void handle_query_mem_spaces_f(GArray *params, void *user_ctx); /** * \brief Handler for all consecutive memory space queries. - * + * * This function sends all consecutive memory space names, IDs, types and * accessing options. * It uses the query_index parameter to determine @@ -596,14 +604,14 @@ void handle_query_mem_spaces_f(GArray *params, void *user_ctx); void handle_query_mem_spaces_c(GArray *params, void *user_ctx); /** * \brief Handler for the first register query. - * + * * This function sends the first register with all its information. * @param[in] params GArray with all TCP packet parameters. */ void handle_query_regs_f(GArray *params, void *user_ctx); /** * \brief Handler for all consecutive register queries. - * + * * This function sends all consecutive registers with all their information. * It uses the query_index parameter to determine * which register is queried next. @@ -612,7 +620,7 @@ void handle_query_regs_f(GArray *params, void *user_ctx); void handle_query_regs_c(GArray *params, void *user_ctx); /** * \brief Handler for opening the MCD server. - * + * * This is the first function that gets called from the MCD Shared Library. * It initializes core indepent data with the \ref init_resets and * \reg init_trigger functions. It also send the \c TCP_HANDSHAKE_SUCCESS @@ -623,14 +631,14 @@ void handle_query_regs_c(GArray *params, void *user_ctx); void handle_open_server(GArray *params, void *user_ctx); /** * \brief Handler for performing resets. - * + * * This function is currently not in use. * @param[in] params GArray with all TCP packet parameters. */ void handle_reset(GArray *params, void *user_ctx); /** * \brief Handler for the state query. - * + * * This function collects all data stored in the * cpu_state member of the mcdserver_state and formats and sends it to the * library. @@ -639,7 +647,7 @@ void handle_reset(GArray *params, void *user_ctx); void handle_query_state(GArray *params, void *user_ctx); /** * \brief Handler for reading a register. - * + * * This function calls \ref mcd_read_register to read a register. The register * data gets stored in the mem_buf byte array. The data then gets converted * into a hex string with \ref mcd_memtohex and then send. @@ -648,7 +656,7 @@ void handle_query_state(GArray *params, void *user_ctx); void handle_read_register(GArray *params, void *user_ctx); /** * \brief Handler for writing a register. - * + * * This function converts the incoming hex string data into a byte array with * \ref mcd_hextomem. Then it calls \ref mcd_write_register to write to the * register. @@ -657,7 +665,7 @@ void handle_read_register(GArray *params, void *user_ctx); void handle_write_register(GArray *params, void *user_ctx); /** * \brief Handler for reading memory. - * + * * First, this function checks whether reading a secure memory space is * requested and changes the access mode with \ref arm_mcd_set_scr. * Then it calls \ref mcd_read_memory to read memory. The collected @@ -668,7 +676,7 @@ void handle_write_register(GArray *params, void *user_ctx); void handle_read_memory(GArray *params, void *user_ctx); /** * \brief Handler for writing memory. - * + * * First, this function checks whether reading a secure memory space is * requested and changes the access mode with \ref arm_mcd_set_scr. * Then it converts the incoming hex string data into a byte array with @@ -679,7 +687,7 @@ void handle_read_memory(GArray *params, void *user_ctx); void handle_write_memory(GArray *params, void *user_ctx); /** * \brief Reads a registers data and stores it into the buf. - * + * * This function collects the register type and internal ID * (depending on the XML file). Then it calls the architecture specific * read function. For ARM this is \ref arm_mcd_read_register. @@ -690,7 +698,7 @@ void handle_write_memory(GArray *params, void *user_ctx); int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); /** * \brief Writes data from the buf to a register. - * + * * This function collects the register type and internal ID * (depending on the XML file). Then it calls the architecture specific * write function. For ARM this is \ref arm_mcd_write_register. @@ -701,7 +709,7 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf, int reg); int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg); /** * \brief Reads memory data and stores it into the buf. - * + * * This function calls cpu_memory_rw_debug or if available * memory_rw_debug in read mode and passes on all parameters. * @param[in] cpu CPU to which the memory belongs. @@ -712,7 +720,7 @@ int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg); int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); /** * \brief Writes data from the buf into the memory. - * + * * This function calls cpu_memory_rw_debug or if available * memory_rw_debug in write mode and passes on all parameters. * @param[in] cpu CPU to which the memory belongs. @@ -723,7 +731,7 @@ int mcd_read_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); /** * \brief Handler for inserting a break- or watchpoint. - * + * * This function extracts the CPU, breakpoint type and address from the * parameters and calls \ref mcd_breakpoint_insert to insert the breakpoint. * @param[in] params GArray with all TCP packet parameters. @@ -731,7 +739,7 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len); void handle_breakpoint_insert(GArray *params, void *user_ctx); /** * \brief Handler for inserting a break- or watchpoint. - * + * * This function extracts the CPU, breakpoint type and address from the * parameters and calls \ref mcd_breakpoint_remove to insert the breakpoint. * @param[in] params GArray with all TCP packet parameters. @@ -739,7 +747,7 @@ void handle_breakpoint_insert(GArray *params, void *user_ctx); void handle_breakpoint_remove(GArray *params, void *user_ctx); /** * \brief Inserts a break- or watchpoint. - * + * * This function evaluates the received breakpoint type and translates it * to a known GDB breakpoint type. * Then it calls cpu_breakpoint_insert or cpu_watchpoint_insert depending on @@ -751,7 +759,7 @@ void handle_breakpoint_remove(GArray *params, void *user_ctx); int mcd_breakpoint_insert(CPUState *cpu, int type, vaddr addr); /** * \brief Removes a break- or watchpoint. - * + * * This function evaluates the received breakpoint type and translates it * to a known GDB breakpoint type. * Then it calls cpu_breakpoint_remove or cpu_watchpoint_remove depending on diff --git a/include/qemu/debug.h b/include/qemu/debug.h new file mode 100644 index 0000000000..870f3ea152 --- /dev/null +++ b/include/qemu/debug.h @@ -0,0 +1,19 @@ +#ifndef QEMU_DEBUG_H +#define QEMU_DEBUG_H + +#include "qom/object.h" +#include "qemu/typedefs.h" + +struct DebugClass { + ObjectClass parent_class; + void (*set_stop_cpu)(CPUState *cpu); +}; + +struct DebugState { + Object parent_obj; +}; + +#define TYPE_DEBUG "debug" +OBJECT_DECLARE_TYPE(DebugState, DebugClass, DEBUG) + +#endif /* QEMU_DEBUG_H */ diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 5abdbc3874..e48b544173 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -46,6 +46,8 @@ typedef struct CpuInfoFast CpuInfoFast; typedef struct CPUJumpCache CPUJumpCache; typedef struct CPUState CPUState; typedef struct CPUTLBEntryFull CPUTLBEntryFull; +typedef struct DebugClass DebugClass; +typedef struct DebugState DebugState; typedef struct DeviceListener DeviceListener; typedef struct DeviceState DeviceState; typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot; diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c index 4f9fafe749..7f6c869023 100644 --- a/mcdstub/mcdstub.c +++ b/mcdstub/mcdstub.c @@ -7,6 +7,7 @@ #include "qemu/cutils.h" #include "qemu/module.h" #include "qemu/error-report.h" +#include "qemu/debug.h" #include "exec/mcdstub.h" #include "mcdstub/syscalls.h" #include "hw/cpu/cluster.h" @@ -67,6 +68,14 @@ void mcd_init_mcdserver_state(void) .info_str = STATE_STR_INIT_HALTED, }; mcdserver_state.cpu_state = cpu_state; + + /* create new debug object */ + mcd_init_debug_class(); + } + +void mcd_set_stop_cpu(CPUState *cpu) +{ + mcdserver_state.c_cpu = cpu; } void init_query_cmds_table(MCDCmdParseEntry *mcd_query_cmds_table) @@ -1804,19 +1813,22 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint8_t *buf, int len) void handle_read_memory(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; uint64_t mem_address = get_param(params, 2)->data_uint64_t; uint32_t len = get_param(params, 3)->data_uint32_t; CPUState *cpu = mcd_get_cpu(cpu_id); - /* check if the mem space is secure */ - GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); - mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, - mem_space_id - 1); - if (arm_mcd_set_scr(cpu, space.is_secure)) { - mcd_put_packet(TCP_EXECUTION_ERROR); - return; - } + /* + * TODO: select to correct address space + * uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; + * GArray *memspaces = + * g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + * mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, + * mem_space_id - 1); + * if (arm_mcd_set_scr(cpu, space.is_secure)) { + * mcd_put_packet(TCP_EXECUTION_ERROR); + * return; + * } + */ /* read memory */ g_byte_array_set_size(mcdserver_state.mem_buf, len); if (mcd_read_memory(cpu, mem_address, mcdserver_state.mem_buf->data, @@ -1832,18 +1844,21 @@ void handle_read_memory(GArray *params, void *user_ctx) void handle_write_memory(GArray *params, void *user_ctx) { uint32_t cpu_id = get_param(params, 0)->cpu_id; - uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; uint64_t mem_address = get_param(params, 2)->data_uint64_t; uint32_t len = get_param(params, 3)->data_uint32_t; CPUState *cpu = mcd_get_cpu(cpu_id); - /* check if the mem space is secure */ - GArray *memspaces = g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); - mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, - mem_space_id - 1); - if (arm_mcd_set_scr(cpu, space.is_secure)) { - mcd_put_packet(TCP_EXECUTION_ERROR); - return; - } + /* + * TODO: select to correct address space + * uint32_t mem_space_id = get_param(params, 1)->data_uint32_t; + * GArray *memspaces = + * g_list_nth_data(mcdserver_state.all_memspaces, cpu_id); + * mcd_mem_space_st space = g_array_index(memspaces, mcd_mem_space_st, + * mem_space_id - 1); + * if (arm_mcd_set_scr(cpu, space.is_secure)) { + * mcd_put_packet(TCP_EXECUTION_ERROR); + * return; + * } + */ /* write memory */ mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, len); if (mcd_write_memory(cpu, mem_address, diff --git a/mcdstub/meson.build b/mcdstub/meson.build index 6b2f970eae..aad35234a9 100644 --- a/mcdstub/meson.build +++ b/mcdstub/meson.build @@ -4,7 +4,7 @@ mcd_system_ss = ss.source_set() # only system emulation is supported over mcd -mcd_system_ss.add(files('mcdstub.c')) +mcd_system_ss.add(files('mcdstub.c', '../debug/debug-mcd.c')) mcd_system_ss = mcd_system_ss.apply(config_host, strict: false) @@ -16,4 +16,4 @@ libmcd_softmmu = static_library('mcd_softmmu', mcd_softmmu = declare_dependency(link_whole: libmcd_softmmu) system_ss.add(mcd_softmmu) -common_ss.add(files('mcd_syscalls.c')) +common_ss.add(files('../debug/debug-common.c', 'mcd_syscalls.c')) diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 5d0657bbe5..734173096a 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "monitor/monitor.h" #include "qemu/coroutine-tls.h" +#include "qemu/debug.h" #include "qapi/error.h" #include "qapi/qapi-commands-machine.h" #include "qapi/qapi-commands-misc.h" @@ -306,10 +307,13 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - /* - * TODO: was gdb_set_stop_cpu(cpu), need to abstract options to - * a QOM class. - */ + MachineState *ms = MACHINE(qdev_get_machine()); + DebugState *ds = ms->debug_state; + DebugClass *dc = DEBUG_GET_CLASS(ds); + + if (dc->set_stop_cpu) { + dc->set_stop_cpu(cpu); + } qemu_system_debug_request(); cpu->stopped = true; } diff --git a/target/arm/mcdstub.c b/target/arm/mcdstub.c index 1b82b9d439..6faf2d7649 100644 --- a/target/arm/mcdstub.c +++ b/target/arm/mcdstub.c @@ -4,6 +4,7 @@ #include "sysemu/tcg.h" #include "internals.h" #include "cpregs.h" +#include "qemu/debug.h" #include "mcdstub/arm_mcdstub.h" @@ -332,20 +333,6 @@ uint16_t arm_mcd_get_opcode(CPUState *cs, uint32_t n) return 0; } -int arm_mcd_set_scr(CPUState *cs, bool secure) -{ - /* switches between secure and non secure mode */ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - /* set bit 0 to 1 if non secure, to 0 if secure*/ - if (secure) { - env->cp15.scr_el3 &= 0xFFFFFFFE; - } else { - env->cp15.scr_el3 |= 1; - } - return 0; -} - int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) { int nr_address_spaces = cpu->num_ases; @@ -379,7 +366,7 @@ int arm_mcd_store_mem_spaces(CPUState *cpu, GArray *memspaces) .is_secure = false, }; g_array_append_vals(memspaces, (gconstpointer)&phys_non_secure, 1); - if(nr_address_spaces > 1) { + if (nr_address_spaces > 1) { mem_space_id++; mcd_mem_space_st secure = { .name = "Secure",