From nobody Tue Feb 10 15:44:28 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1696583233027217.03939255184798; Fri, 6 Oct 2023 02:07:13 -0700 (PDT) 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 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 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 From: Nicolas Eder To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Christian.Boenig@lauterbach.com, =?UTF-8?q?Alex=20Benn=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 Content-Transfer-Encoding: quoted-printable X-Qmail-Scanner-2.11: added fake Content-Type header Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1696583233459100009 Content-Type: text/plain; charset="utf-8" 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 @@ =20 #define DEFAULT_MCDSTUB_PORT "1235" #define TYPE_CHARDEV_MCD "chardev-mcd" -#define MX_INPUT_LENGTH 9 -#define MCD_TCP_DATALEN 80 =20 -/* 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); =20 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_ =20 typedef void (*gdb_syscall_complete_cb)(CPUState *cpu, uint64_t ret, int e= rr); =20 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 t= he tcp connection to trace32, - * as well as function declarations for all functios used inside the mcdst= ub - */ - #ifndef MCDSTUB_INTERNALS_H #define MCDSTUB_INTERNALS_H =20 @@ -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" =20 #define MAX_PACKET_LENGTH 1024 =20 // 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 =20 +typedef uint32_t mcd_trig_type_et; +// TODO: replace mcd defines with custom layer +enum { + MCD_TRIG_TYPE_UNDEFINED =3D 0x00000000, /**< Undefined trigger type. = */ + MCD_TRIG_TYPE_IP =3D 0x00000001, /**< Trigger on a changing instru= ction pointer. */ + MCD_TRIG_TYPE_READ =3D 0x00000002, /**< Trigger on a read data acces= s to a specific address or address range. */ + MCD_TRIG_TYPE_WRITE =3D 0x00000004, /**< Trigger on a write data acce= ss to a specific address or address range. */ + MCD_TRIG_TYPE_RW =3D 0x00000008, /**< Trigger on a read or a write= data access to a specific address or + address range. = */ + MCD_TRIG_TYPE_NOCYCLE =3D 0x00000010, /**< Trigger on core information = other than an IP or data compare trigger. */ + MCD_TRIG_TYPE_TRIG_BUS =3D 0x00000020, /**< Trigger on a trigger bus com= bination. */ + MCD_TRIG_TYPE_COUNTER =3D 0x00000040, /**< Trigger on an elapsed trigge= r counter. */ + MCD_TRIG_TYPE_CUSTOM =3D 0x00000080, /**< Custom trigger using standar= d format as defined by \ref mcd_trig_custom_st. */ + MCD_TRIG_TYPE_CUSTOM_LO =3D 0x00010000, /**< Begin Range: User defined tr= igger types. */ + MCD_TRIG_TYPE_CUSTOM_HI =3D 0x40000000, /**< End Range: User defined tr= igger types. */ +}; + typedef uint32_t mcd_core_event_et; +// TODO: replace mcd defines with custom layer enum { MCD_CORE_EVENT_NONE =3D 0x00000000, /**< No since the last p= oll. */ MCD_CORE_EVENT_MEMORY_CHANGE =3D 0x00000001, /**< Memory content has = changed. */ @@ -50,10 +59,11 @@ enum { #define RESET_GPR "gpr_reset" #define RESET_MEMORY "memory_reset" =20 -// more -#define QUERY_TOTAL_NUMBER 12 //FIXME: set this to a usefull value in the = end +// misc +#define QUERY_TOTAL_NUMBER 12=20 #define CMD_SCHEMA_LENGTH 5 #define MCD_SYSTEM_NAME "qemu-system" + // tcp query packet values templates #define DEVICE_NAME_TEMPLATE(s) "qemu-" #s "-device" =20 @@ -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" =20 -// 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; =20 -/* - * 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 th= is uint32_t pid; bool attached; =20 @@ -99,35 +105,16 @@ typedef struct MCDCmdParseEntry { char schema[CMD_SCHEMA_LENGTH]; } MCDCmdParseEntry; =20 -typedef enum MCDThreadIdKind { - GDB_ONE_THREAD =3D 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; =20 #define get_param(p, i) (&g_array_index(p, MCDCmdVariant, i)) =20 - -/* - * 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 as= sume 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; =20 - // 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; =20 -// Inline utility function, convert from int to hex and back - - static inline int fromhex(int v) { if (v >=3D '0' && v <=3D '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 MCDCmdParse= Entry *cmd); int process_string_cmd(void *user_ctx, const char *data, const MCDCmdParse= Entry *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_c= tx); 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); =20 @@ -337,7 +318,7 @@ int mcd_arm_parse_core_xml_file(CPUClass *cc, GArray* r= eggroups, GArray* registe int mcd_arm_parse_general_xml_files(CPUState *cpu, GArray* reggroups, GArr= ay* registers, int* current_group_id); int mcd_arm_get_additional_register_info(GArray* reggroups, GArray* regist= ers); =20 -/* sycall handling */ +// sycall handling void mcd_syscall_reset(void); void mcd_disable_syscalls(void); =20 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 stub= s for each target. + * This is the main mcdstub. */ =20 #include "mcd_shared_defines.h" =20 -//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" =20 -//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" =20 -//architecture specific stuff +// architecture specific stubs #include "target/arm/mcdstub.h" =20 // FIXME: delete the following line and check if it worked @@ -39,7 +35,6 @@ =20 typedef struct { CharBackend chr; - //Chardev *mon_chr; } MCDSystemState; =20 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 =3D accel_supported_gdbstub_sste= p_flags(); mcdserver_state.sstep_flags =3D SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOT= IMER; mcdserver_state.sstep_flags &=3D mcdserver_state.supported_sstep_flags; @@ -106,7 +99,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_c= mds_table) { .handler =3D handle_query_reset_c, .cmd =3D 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] =3D query_reset_c; cmd_number++; =20 @@ -121,7 +114,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_= cmds_table) { .handler =3D handle_query_mem_spaces_f, .cmd =3D QUERY_ARG_MEMORY QUERY_FIRST, }; - strcpy(query_mem_spaces_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENU= M, '\0' }); + strcpy(query_mem_spaces_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0'= }); mcd_query_cmds_table[cmd_number] =3D query_mem_spaces_f; cmd_number++; =20 @@ -129,7 +122,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_= cmds_table) { .handler =3D handle_query_mem_spaces_c, .cmd =3D QUERY_ARG_MEMORY QUERY_CONSEQUTIVE, }; - strcpy(query_mem_spaces_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHAN= DLE, '\0' }); + strcpy(query_mem_spaces_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\= 0' }); mcd_query_cmds_table[cmd_number] =3D query_mem_spaces_c; cmd_number++; =20 @@ -137,7 +130,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_= cmds_table) { .handler =3D handle_query_reg_groups_f, .cmd =3D QUERY_ARG_REGGROUP QUERY_FIRST, }; - strcpy(query_reg_groups_f.schema, (char[2]) { (char) ARG_SCHEMA_CORENU= M, '\0' }); + strcpy(query_reg_groups_f.schema, (char[2]) { ARG_SCHEMA_CORENUM, '\0'= }); mcd_query_cmds_table[cmd_number] =3D query_reg_groups_f; cmd_number++; =20 @@ -145,7 +138,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_= cmds_table) { .handler =3D handle_query_reg_groups_c, .cmd =3D QUERY_ARG_REGGROUP QUERY_CONSEQUTIVE, }; - strcpy(query_reg_groups_c.schema, (char[2]) { (char) ARG_SCHEMA_QRYHAN= DLE, '\0' }); + strcpy(query_reg_groups_c.schema, (char[2]) { ARG_SCHEMA_QRYHANDLE, '\= 0' }); mcd_query_cmds_table[cmd_number] =3D query_reg_groups_c; cmd_number++; =20 @@ -153,7 +146,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_= cmds_table) { .handler =3D handle_query_regs_f, .cmd =3D 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] =3D query_regs_f; cmd_number++; =20 @@ -161,7 +154,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_= cmds_table) { .handler =3D handle_query_regs_c, .cmd =3D 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] =3D query_regs_c; cmd_number++; =20 @@ -169,7 +162,7 @@ void init_query_cmds_table(MCDCmdParseEntry* mcd_query_= cmds_table) { .handler =3D handle_query_state, .cmd =3D 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] =3D query_state; } =20 @@ -258,12 +251,8 @@ int pid_order(const void *a, const void *b) =20 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 =3D NULL; - //Chardev *mon_chr; =20 if (!first_cpu) { error_report("mcdstub: meaningless to attach to a " @@ -271,7 +260,6 @@ int mcdserver_start(const char *device) return -1; } =20 - // 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; } =20 - //if device =3D=3D default -> set device =3D tcp::1235 + // if device =3D=3D default -> set device =3D tcp::1235 if (strcmp(device, "default") =3D=3D 0) { device =3D "tcp::1235"; } @@ -303,7 +291,6 @@ int mcdserver_start(const char *device) sigaction(SIGINT, &act, NULL); } #endif - =20 chr =3D 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(); =20 qemu_add_vm_change_state_handler(mcd_vm_state_change, NULL); - - /* Initialize a monitor terminal for mcd */ - //mon_chr =3D 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 =3D mcdserver_system_state.mon_chr; reset_mcdserver_state(); } =20 @@ -334,7 +316,6 @@ int mcdserver_start(const char *device) NULL, &mcdserver_state, NULL, true); } mcdserver_state.state =3D chr ? RS_IDLE : RS_INACTIVE; - //mcdserver_system_state.mon_chr =3D mon_chr; mcd_syscall_reset(); =20 return 0; @@ -360,107 +341,80 @@ void mcd_read_byte(uint8_t ch) uint8_t reply; =20 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 =3D=3D 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_st= ate.last_packet->len); } else if (ch =3D=3D TCP_ACKNOWLEDGED) { - //the previous packet was acknowledged - //trace_gdbstub_io_got_ack(); + // the previous packet was acknowledged } =20 if (ch =3D=3D TCP_ACKNOWLEDGED || ch =3D=3D TCP_COMMAND_START) { - //either acknowledged or a new communication starts -> we disc= ard previous communication + // either acknowledged or a new communication starts -> discar= d previous packet g_byte_array_set_size(mcdserver_state.last_packet, 0); } if (ch !=3D TCP_COMMAND_START) { - // we only continue if we are processing a new commant. otherw= ise 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 =3D=3D TCP_COMMAND_START) { - /* start of command packet */ - mcdserver_state.line_buf_index =3D 0; - mcdserver_state.line_sum =3D 0; - mcdserver_state.state =3D RS_GETLINE; - } - else { - //new communication has to start with a $ - //trace_gdbstub_err_garbage(ch); - } - break; - case RS_GETLINE: - if (ch =3D=3D TCP_COMMAND_END) { - /* end of command, start of checksum*/ - mcdserver_state.line_buf[mcdserver_state.line_buf_index++]= =3D 0; - //mcdserver_state.line_sum +=3D ch; - mcdserver_state.state =3D RS_DATAEND; - } - else if (mcdserver_state.line_buf_index >=3D sizeof(mcdserver_= state.line_buf) - 1) { - //the input string is too long for the linebuffer! - //trace_gdbstub_err_overrun(); - mcdserver_state.state =3D 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++]= =3D ch; - mcdserver_state.line_sum +=3D 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 =3D=3D TCP_WAS_NOT_LAST) { - // ~ indicates that there is an additional package coming - //acknowledged -> send + - reply =3D TCP_ACKNOWLEDGED; - mcd_put_buffer(&reply, 1); - mcdserver_state.state =3D mcd_handle_packet(mcdserver_stat= e.line_buf); - } - else if (ch =3D=3D TCP_WAS_LAST) { - //acknowledged -> send + - // | indicates that there is no additional package coming - reply =3D TCP_ACKNOWLEDGED; - mcd_put_buffer(&reply, 1); - mcdserver_state.state =3D mcd_handle_packet(mcdserver_stat= e.line_buf); - } - else { - //trace_gdbstub_err_checksum_incorrect(mcdserver_state.lin= e_sum, mcdserver_state.line_csum); - //not acknowledged -> send - - reply =3D TCP_NOT_ACKNOWLEDGED; - mcd_put_buffer(&reply, 1); - //waiting for package to get resent - mcdserver_state.state =3D RS_IDLE; - } - break; - default: - abort(); + + switch(mcdserver_state.state) { + case RS_IDLE: + if (ch =3D=3D TCP_COMMAND_START) { + // start of command packet + mcdserver_state.line_buf_index =3D 0; + mcdserver_state.line_sum =3D 0; + mcdserver_state.state =3D RS_GETLINE; + } + break; + case RS_GETLINE: + if (ch =3D=3D TCP_COMMAND_END) { + // end of command + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] =3D= 0; + mcdserver_state.state =3D RS_DATAEND; + } + else if (mcdserver_state.line_buf_index >=3D sizeof(mcdserver_stat= e.line_buf) - 1) { + // the input string is too long for the linebuffer! + mcdserver_state.state =3D RS_IDLE; + } + else { + // copy the content to the line_buf + mcdserver_state.line_buf[mcdserver_state.line_buf_index++] =3D= ch; + mcdserver_state.line_sum +=3D ch; + } + break; + case RS_DATAEND: + if (ch =3D=3D TCP_WAS_NOT_LAST) { + reply =3D TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state =3D mcd_handle_packet(mcdserver_state.li= ne_buf); + } + else if (ch =3D=3D TCP_WAS_LAST) { + reply =3D TCP_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + mcdserver_state.state =3D mcd_handle_packet(mcdserver_state.li= ne_buf); } - //} + else { + // not acknowledged! + reply =3D TCP_NOT_ACKNOWLEDGED; + mcd_put_buffer(&reply, 1); + // waiting for package to get resent + mcdserver_state.state =3D RS_IDLE; + } + break; + default: + abort(); + } } =20 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 char= acter in the line_buf const MCDCmdParseEntry *cmd_parser =3D NULL; =20 switch (line_buf[0]) { case TCP_CHAR_OPEN_SERVER: - // handshake and lookup initialization { static MCDCmdParseEntry open_server_cmd_desc =3D { .handler =3D 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 =3D { .handler =3D handle_vm_start, @@ -479,8 +432,17 @@ int mcd_handle_packet(const char *line_buf) cmd_parser =3D &go_cmd_desc; } break; + case TCP_CHAR_STEP: + { + static MCDCmdParseEntry step_cmd_desc =3D { + .handler =3D handle_vm_step, + }; + step_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_STEP, '\0' }; + strcpy(step_cmd_desc.schema, (char[2]) { ARG_SCHEMA_CORENUM, '= \0' }); + cmd_parser =3D &step_cmd_desc; + } + break; case TCP_CHAR_BREAK: - // go command { static MCDCmdParseEntry break_cmd_desc =3D { .handler =3D 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 =3D { .handler =3D handle_gen_query, @@ -550,7 +511,7 @@ int mcd_handle_packet(const char *line_buf) .handler =3D handle_read_register, }; read_reg_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_READ_REGISTER, = '\0' }; - strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENU= M, ARG_SCHEMA_INT, '\0' }); + strcpy(read_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_CORENU= M, ARG_SCHEMA_UINT64_T, '\0' }); cmd_parser =3D &read_reg_cmd_desc; } break; @@ -560,7 +521,7 @@ int mcd_handle_packet(const char *line_buf) .handler =3D handle_write_register, }; write_reg_cmd_desc.cmd =3D (char[2]) { TCP_CHAR_WRITE_REGISTER= , '\0' }; - strcpy(write_reg_cmd_desc.schema, (char[3]) { ARG_SCHEMA_COREN= UM, ARG_SCHEMA_INT, '\0' }); + strcpy(write_reg_cmd_desc.schema, (char[5]) { ARG_SCHEMA_COREN= UM, ARG_SCHEMA_UINT64_T, ARG_SCHEMA_INT, ARG_SCHEMA_HEXDATA, '\0' }); cmd_parser =3D &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; } =20 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); } =20 @@ -599,21 +560,29 @@ int mcd_handle_packet(const char *line_buf) } =20 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(); } =20 +void handle_vm_step(GArray *params, void *user_ctx) { + // TODO: add partial restart with arguments and so on + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + + CPUState *cpu =3D 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(); } =20 -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) } } =20 -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 MCDCmdParse= Entry *cmd) g_string_set_size(mcdserver_state.str_buf, 0); g_byte_array_set_size(mcdserver_state.mem_buf, 0); =20 - /* 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 *sc= hema, GArray *params) { const char *remaining_data =3D data; =20 for (int i =3D 0; ihandler && cmd->cmd); =20 - // if data and command are different continue + // continue if data and command are different if (strncmp(data, cmd->cmd, strlen(cmd->cmd))) { continue; } =20 - // 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 comma= nd name + // extract data for parameters if (cmd_parse_params(&data[strlen(cmd->cmd)], cmd->schema, par= ams)) { return -1; } } =20 - // 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 *da= ta, const MCDCmdParseEntry return -1; } =20 -void mcd_exit(int code) -{ - char buf[4]; - +void mcd_exit(int code) { + // terminate qemu if (!mcdserver_state.init) { return; } =20 - //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); } =20 -void mcd_chr_event(void *opaque, QEMUChrEvent event) -{ +void mcd_chr_event(void *opaque, QEMUChrEvent event) { int i; MCDState *s =3D (MCDState *) opaque; =20 @@ -771,19 +724,13 @@ void mcd_chr_event(void *opaque, QEMUChrEvent event) } =20 s->c_cpu =3D mcd_first_attached_cpu(); - - //vm_stop(RUN_STATE_PAUSED); - //TODO: this might not be necessary - //replay_gdb_attached(); - //gdb_has_xml =3D false; break; default: break; } } =20 -bool mcd_supports_guest_debug(void) -{ +bool mcd_supports_guest_debug(void) { const AccelOpsClass *ops =3D cpus_get_accel(); if (ops->supports_guest_debug) { return ops->supports_guest_debug(); @@ -792,29 +739,23 @@ bool mcd_supports_guest_debug(void) } =20 #ifndef _WIN32 -void mcd_sigterm_handler(int signal) -{ +void mcd_sigterm_handler(int signal) { if (runstate_is_running()) { vm_stop(RUN_STATE_PAUSED); } } #endif =20 -void mcd_vm_state_change(void *opaque, bool running, RunState state) -{ +void mcd_vm_state_change(void *opaque, bool running, RunState state) { CPUState *cpu =3D mcdserver_state.c_cpu; =20 - // update cpu state - mcdserver_state.vm_previous_state =3D mcdserver_state.vm_current_state; - mcdserver_state.vm_current_state =3D state; - if (mcdserver_state.state =3D=3D RS_INACTIVE) { return; } =20 if (cpu =3D=3D NULL) { if (running) { - // this is the case if qemu starts the vm before any mcd is co= nnected + // this is the case if qemu starts the vm before a mcd client = is connected const char *mcd_state; mcd_state =3D CORE_STATE_RUNNING; const char *info_str; @@ -857,8 +798,13 @@ void mcd_vm_state_change(void *opaque, bool running, R= unState state) stop_str =3D STATE_STR_BREAK_UNKNOWN; } cpu->watchpoint_hit =3D 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 =3D STATE_STEP_PERFORMED; + } + else { trig_id =3D MCD_TRIG_TYPE_IP; stop_str =3D STATE_STR_BREAK_HW; tb_flush(cpu); @@ -870,47 +816,40 @@ void mcd_vm_state_change(void *opaque, bool running, = RunState state) stop_str =3D ""; break; case RUN_STATE_WATCHDOG: + printf("runstate watchdog hit\n"); info_str =3D STATE_STR_UNKNOWN(cpu->cpu_index); mcd_state =3D CORE_STATE_UNKNOWN; stop_str =3D ""; - printf("runstate watchdog hit\n"); break; default: info_str =3D STATE_STR_UNKNOWN(cpu->cpu_index); mcd_state =3D CORE_STATE_UNKNOWN; stop_str =3D ""; - // we don't care; break; } =20 + // set state for c_cpu mcdserver_state.cpu_state.state =3D mcd_state; mcdserver_state.cpu_state.trig_id =3D trig_id; mcdserver_state.cpu_state.stop_str =3D stop_str; mcdserver_state.cpu_state.info_str =3D info_str; - - /* disable single step if it was enabled */ - cpu_single_step(cpu, 0); } =20 -int mcd_put_packet(const char *buf) -{ +int mcd_put_packet(const char *buf) { return mcd_put_packet_binary(buf, strlen(buf), false); } =20 -void mcd_put_strbuf(void) -{ +void mcd_put_strbuf(void) { mcd_put_packet(mcdserver_state.str_buf->str); } =20 -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 h= ere!! 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); =20 mcd_put_buffer(mcdserver_state.last_packet->data, mcdserver_state.= last_packet->len); =20 @@ -921,53 +860,28 @@ int mcd_put_packet_binary(const char *buf, int len, b= ool dump) return 0; } =20 -bool mcd_got_immediate_ack(void) -{ +bool mcd_got_immediate_ack(void) { return true; } =20 -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); } =20 -void mcd_set_stop_cpu(CPUState *cpu) -{ - MCDProcess *p =3D mcd_get_cpu_process(cpu); - - if (!p->attached) { - /* - * Having a stop CPU corresponding to a process that is not attach= ed - * confuses GDB. So we ignore the request. - */ - return; - } - //FIXME: we probably can delete this because in the opern_core functio= n we set these two anyway - mcdserver_state.c_cpu =3D cpu; -} - -MCDProcess *mcd_get_cpu_process(CPUState *cpu) -{ +MCDProcess *mcd_get_cpu_process(CPUState *cpu) { return mcd_get_process(mcd_get_cpu_pid(cpu)); } =20 -uint32_t mcd_get_cpu_pid(CPUState *cpu) -{ +uint32_t mcd_get_cpu_pid(CPUState *cpu) { if (cpu->cluster_index =3D=3D UNASSIGNED_CLUSTER_INDEX) { - /* Return the default process' PID */ + // Return the default process' PID int index =3D 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; } =20 -MCDProcess *mcd_get_process(uint32_t pid) -{ +MCDProcess *mcd_get_process(uint32_t pid) { int i; =20 if (!pid) { @@ -997,8 +911,7 @@ CPUState* mcd_get_cpu(uint32_t i_cpu_index) { return cpu; } =20 -CPUState *mcd_first_attached_cpu(void) -{ +CPUState *mcd_first_attached_cpu(void) { CPUState *cpu =3D first_cpu; MCDProcess *process =3D mcd_get_cpu_process(cpu); =20 @@ -1009,8 +922,7 @@ CPUState *mcd_first_attached_cpu(void) return cpu; } =20 -CPUState *mcd_next_attached_cpu(CPUState *cpu) -{ +CPUState *mcd_next_attached_cpu(CPUState *cpu) { cpu =3D CPU_NEXT(cpu); =20 while (cpu) { @@ -1024,14 +936,11 @@ CPUState *mcd_next_attached_cpu(CPUState *cpu) return cpu; } =20 -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; } =20 -CPUState *get_first_cpu_in_process(MCDProcess *process) -{ +CPUState *get_first_cpu_in_process(MCDProcess *process) { CPUState *cpu; =20 CPU_FOREACH(cpu) { @@ -1043,8 +952,7 @@ CPUState *get_first_cpu_in_process(MCDProcess *process) return NULL; } =20 -CPUState *find_cpu(uint32_t thread_id) -{ +CPUState *find_cpu(uint32_t thread_id) { CPUState *cpu; =20 CPU_FOREACH(cpu) { @@ -1080,7 +988,7 @@ void parse_reg_xml(const char *xml, int size, GArray* = registers) { c_ptr =3D &c; =20 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) { } =20 int int_cmp(gconstpointer a, gconstpointer b) { - int a_int =3D *(int*)a; - int b_int =3D *(int*)b; - if (a_int =3D=3D b_int) { + if (*(int*)a =3D=3D *(int*)b) { return 0; } else { @@ -1285,7 +1191,7 @@ int init_trigger(mcd_trigger_st* trigger) { } =20 void handle_open_server(GArray *params, void *user_ctx) { - // initialize some core-independent data + // initialize core-independent data int return_value =3D 0; mcdserver_state.resets =3D g_array_new(false, true, sizeof(mcd_reset_s= t)); return_value =3D init_resets(mcdserver_state.resets); @@ -1301,8 +1207,6 @@ void handle_query_system(GArray *params, void *user_c= tx) { } =20 void handle_query_cores(GArray *params, void *user_ctx) { - //TODO: add cluster support: in gdb each inferior (process) handles on= e cluster we might want to have sth similar here - // get first cpu CPUState *cpu =3D mcd_first_attached_cpu(); if (!cpu) { @@ -1316,10 +1220,9 @@ void handle_query_cores(GArray *params, void *user_c= tx) { gchar *arch =3D cc->gdb_arch_name(cpu); =20 int nr_cores =3D cpu->nr_cores; - char device_name[] =3D DEVICE_NAME_TEMPLATE(arch); g_string_printf(mcdserver_state.str_buf, "%s=3D%s.%s=3D%s.%s=3D%d.", - TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TCP_AR= GUMENT_AMOUNT_CORE, nr_cores); + TCP_ARGUMENT_DEVICE, device_name, TCP_ARGUMENT_CORE, cpu_model, TC= P_ARGUMENT_AMOUNT_CORE, nr_cores); mcd_put_strbuf(); g_free(arch); } @@ -1441,7 +1344,6 @@ int mcd_arm_get_additional_register_info(GArray* regg= roups, GArray* registers) { } =20 void handle_open_core(GArray *params, void *user_ctx) { - // get the cpu whith the given id uint32_t cpu_id =3D get_param(params, 0)->cpu_id; CPUState *cpu =3D mcd_get_cpu(cpu_id); mcdserver_state.c_cpu =3D cpu; @@ -1501,9 +1403,7 @@ void handle_open_core(GArray *params, void *user_ctx)= { } =20 void handle_query_reset_f(GArray *params, void *user_ctx) { - // resetting has to be done over a monitor (look ar Rcmd) so we tell M= CD that we can reset but this still need to be implemented - // we only support one reset over this monitor and that would be a ful= l "system_restart" - // reset options are the same for every cpu! + // TODO: vull reset over the qemu monitor =20 // 1. check length int nb_resets =3D mcdserver_state.resets->len; @@ -1518,7 +1418,6 @@ void handle_query_reset_f(GArray *params, void *user_= ctx) { mcd_reset_st reset =3D g_array_index(mcdserver_state.resets, mcd_reset= _st, 0); g_string_append_printf(mcdserver_state.str_buf, "%s=3D%s.%s=3D%d.", TC= P_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); - // TODO: we still need to implement the gpr and memory reset here! } =20 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 =3D g_array_index(mcdserver_state.resets, mcd_reset= _st, query_index); g_string_append_printf(mcdserver_state.str_buf, "%s=3D%s.%s=3D%d.", TC= P_ARGUMENT_NAME, reset.name, TCP_ARGUMENT_ID, reset.id); mcd_put_strbuf(); - // TODO: we still need to implement the gpr and memory reset here! } =20 void handle_close_core(GArray *params, void *user_ctx) { @@ -1575,7 +1473,7 @@ void handle_close_server(GArray *params, void *user_c= tx) { mcdserver_state.c_cpu =3D 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) { } } =20 +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); } } =20 @@ -1724,7 +1627,7 @@ void handle_query_regs_f(GArray *params, void *user_c= tx) { } =20 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 =3D get_param(params, 0)->query_handle; uint32_t cpu_id =3D mcdserver_state.query_cpu_id; @@ -1750,16 +1653,12 @@ void handle_query_regs_c(GArray *params, void *user= _ctx) { } =20 void handle_reset(GArray *params, void *user_ctx) { - int reset_id =3D get_param(params, 0)->data_int; - //int bool_halt_after_reset =3D get_param(params, 1)->data_int; - if (reset_id>=3D0) { - //fun for the compiler - } + //int reset_id =3D get_param(params, 0)->data_int; + // TODO: implement resets } =20 void handle_query_state(GArray *params, void *user_ctx) { - // send state from correct core - //uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + // TODO: multicore support // get state info mcd_cpu_state_st state_info =3D mcdserver_state.cpu_state; mcd_core_event_et event =3D MCD_CORE_EVENT_NONE; @@ -1795,6 +1694,19 @@ int mcd_read_register(CPUState *cpu, GByteArray *buf= , int reg) { } } =20 +int mcd_write_register(CPUState *cpu, GByteArray *buf, int reg) { + CPUClass *cc =3D CPU_GET_CLASS(cpu); + gchar *arch =3D cc->gdb_arch_name(cpu); + if (strcmp(arch, "arm")=3D=3D0) { + 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 =3D 0; i < len; i++) { @@ -1817,18 +1729,28 @@ void mcd_hextomem(GByteArray *mem, const char *buf,= int len) { =20 void handle_read_register(GArray *params, void *user_ctx) { uint32_t cpu_id =3D get_param(params, 0)->cpu_id; - int reg_num =3D get_param(params, 1)->data_int; + uint64_t reg_num =3D get_param(params, 1)->data_int; int reg_size; =20 CPUState *cpu =3D mcd_get_cpu(cpu_id); - reg_size =3D 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, r= eg_size); mcd_put_strbuf(); } =20 void handle_write_register(GArray *params, void *user_ctx) { + uint32_t cpu_id =3D get_param(params, 0)->cpu_id; + uint64_t reg_num =3D get_param(params, 1)->data_int; + uint32_t reg_size =3D get_param(params, 2)->data_int; =20 + CPUState *cpu =3D mcd_get_cpu(cpu_id); + mcd_hextomem(mcdserver_state.mem_buf, mcdserver_state.str_buf->str, re= g_size); + if (mcd_write_register(cpu, mcdserver_state.mem_buf, reg_num)=3D=3D0) { + mcd_put_packet(TCP_EXECUTION_ERROR); + } + else { + mcd_put_packet(TCP_EXECUTION_SUCCESS); + } } =20 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 =3D 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); } =20 @@ -1848,7 +1769,6 @@ int mcd_write_memory(CPUState *cpu, hwaddr addr, uint= 8_t *buf, int len) { //TODO: add physical mem cpu_physical_memory_read(addr, buf, len); cc =3D 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); } =20 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 =3D 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 @@ =20 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 =3D 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) =20 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 =3D 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 c= har *xmlname) } =20 int arm_mcd_read_register(CPUState *cs, GByteArray *mem_buf, int n) { - //CPUClass *cc =3D CPU_GET_CLASS(cpu); - //CPUArchState *env =3D cpu->env_ptr; - ARMCPU *cpu =3D ARM_CPU(cs); CPUARMState *env =3D &cpu->env; =20 @@ -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 =3D ARM_CPU(cs); + CPUARMState *env =3D &cpu->env; + uint32_t tmp; + + tmp =3D ldl_p(mem_buf); + tmp =3D *((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 =3D=3D 15) { + tmp &=3D ~1; + } + + if (n < 16) { + /* Core integer register. */ + if (n =3D=3D 13 && arm_feature(env, ARM_FEATURE_M)) { + /* M profile SP low bits are always 0 */ + tmp &=3D ~3; + } + env->regs[n] =3D 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 @@ =20 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); =20 #endif /* ARM_MCDSTUB_H */ --=20 2.34.1