[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 03/29] TCP packet handling added
From: |
Nicolas Eder |
Subject: |
[PATCH v2 03/29] TCP packet handling added |
Date: |
Fri, 6 Oct 2023 11:05:44 +0200 |
From: neder <nicolas.eder@lauterbach.com>
---
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();
+ }
+}
--
2.34.1
- [PATCH v2 00/29] first version of mcdstub, Nicolas Eder, 2023/10/06
- [PATCH v2 02/29] TCP chardev added, handshake with TRACE32 working, Nicolas Eder, 2023/10/06
- [PATCH v2 01/29] mcdstub initial commit, mcdstub file structure added, Nicolas Eder, 2023/10/06
- [PATCH v2 04/29] queries for resets and triggers added, Nicolas Eder, 2023/10/06
- [PATCH v2 06/29] query for registers added, Nicolas Eder, 2023/10/06
- [PATCH v2 03/29] TCP packet handling added,
Nicolas Eder <=
- [PATCH v2 08/29] shared header file added, used for TCP packet data, Nicolas Eder, 2023/10/06
- [PATCH v2 05/29] queries for memory spaces and register groups added, Nicolas Eder, 2023/10/06
- [PATCH v2 09/29] memory and register query data now stored per core, Nicolas Eder, 2023/10/06
- [PATCH v2 07/29] query data preparation improved, Nicolas Eder, 2023/10/06
- [PATCH v2 10/29] handler for resets added, Nicolas Eder, 2023/10/06
- [PATCH v2 11/29] query for the VM state added, Nicolas Eder, 2023/10/06
- [PATCH v2 12/29] handler for reading registers added, Nicolas Eder, 2023/10/06
- [PATCH v2 16/29] deleting the mcdd startup option, Nicolas Eder, 2023/10/06
- [PATCH v2 15/29] adapting to the qemu coding style, Nicolas Eder, 2023/10/06