---
include/mcdstub/mcdstub.h | 53 ++++++++++++++++++++
mcdstub/mcdstub.c | 101 ++++++++++++++++++++++++++++++++++++++
2 files changed, 154 insertions(+)
diff --git a/include/mcdstub/mcdstub.h b/include/mcdstub/mcdstub.h
index 85ca8b3b62..0375cf7311 100644
--- a/include/mcdstub/mcdstub.h
+++ b/include/mcdstub/mcdstub.h
@@ -439,6 +439,33 @@ int process_string_cmd(void *user_ctx, const char *data,
*/
int cmd_parse_params(const char *data, const char *schema, GArray *params);
+/**
+ * handle_vm_start() - Handler for the VM start TCP packet.
+ *
+ * Evaluates whether all cores or just a perticular core should get started and
+ * calls :c:func:`mcd_vm_start` or :c:func:`mcd_cpu_start` respectively.
+ * @params: GArray with all TCP packet parameters.
+ */
+void handle_vm_start(GArray *params, void *user_ctx);
+
+/**
+ * handle_vm_step() - Handler for the VM step TCP packet.
+ *
+ * Calls :c:func:`mcd_cpu_sstep` for the CPU which sould be stepped.
+ * Stepping all CPUs is currently not supported.
+ * @params: GArray with all TCP packet parameters.
+ */
+void handle_vm_step(GArray *params, void *user_ctx);
+
+/**
+ * handle_vm_stop() - Handler for the VM stop TCP packet.
+ *
+ * Always calls :c:func:`mcd_vm_stop` and stops all cores. Stopping individual
+ * cores is currently not supported.
+ * @params: GArray with all TCP packet parameters.
+ */
+void handle_vm_stop(GArray *params, void *user_ctx);
+
/**
* handle_gen_query() - Handler for all TCP query packets.
*
@@ -550,6 +577,32 @@ void handle_close_core(GArray *params, void *user_ctx);
*/
void handle_query_trigger(GArray *params, void *user_ctx);
+/**
+ * mcd_vm_start() - Starts all CPUs with the vm_start function.
+ */
+void mcd_vm_start(void);
+
+/**
+ * mcd_cpu_start() - Starts the selected CPU with the cpu_resume function.
+ *
+ * @cpu: The CPU about to be started.
+ */
+void mcd_cpu_start(CPUState *cpu);
+
+/**
+ * mcd_cpu_sstep() - 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.
+ * @cpu: The CPU about to be stepped.
+ */
+int mcd_cpu_sstep(CPUState *cpu);
+
+/**
+ * mcd_vm_stop() - Brings all CPUs in debug state with the vm_stop function.
+ */
+void mcd_vm_stop(void);
+
/**
* handle_query_reg_groups_f() - Handler for the first register group query.
*
diff --git a/mcdstub/mcdstub.c b/mcdstub/mcdstub.c
index cd2f5db8e4..6313459bac 100644
--- a/mcdstub/mcdstub.c
+++ b/mcdstub/mcdstub.c
@@ -432,6 +432,37 @@ int mcd_handle_packet(const char *line_buf)
cmd_parser = &open_server_cmd_desc;
}
break;
+ case TCP_CHAR_GO:
+ {
+ static MCDCmdParseEntry go_cmd_desc = {
+ .handler = handle_vm_start,
+ };
+ go_cmd_desc.cmd = (char[2]) { TCP_CHAR_GO, '\0' };
+ strcpy(go_cmd_desc.schema,
+ (char[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' });
+ 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[3]) { ARG_SCHEMA_INT, ARG_SCHEMA_CORENUM, '\0' });
+ cmd_parser = &step_cmd_desc;
+ }
+ break;
+ case TCP_CHAR_BREAK:
+ {
+ static MCDCmdParseEntry break_cmd_desc = {
+ .handler = handle_vm_stop,
+ };
+ break_cmd_desc.cmd = (char[2]) { TCP_CHAR_BREAK, '\0' };
+ cmd_parser = &break_cmd_desc;
+ }
+ break;
case TCP_CHAR_KILLQEMU:
/* kill qemu completely */
error_report("QEMU: Terminated via MCDstub");
@@ -494,6 +525,40 @@ int mcd_handle_packet(const char *line_buf)
return RS_IDLE;
}
+void handle_vm_start(GArray *params, void *user_ctx)
+{
+ 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)
+{
+ 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 core dependant break option */
+ mcd_vm_stop();
+}
+
void handle_gen_query(GArray *params, void *user_ctx)
{
if (!params->len) {
@@ -1286,6 +1351,42 @@ void handle_query_trigger(GArray *params, void *user_ctx)
mcd_put_strbuf();
}
+void mcd_vm_start(void)
+{
+ if (!runstate_needs_reset() && !runstate_is_running()) {
+ vm_start();
+ }
+}
+
+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);
+ if (!runstate_needs_reset() && !runstate_is_running() &&
+ !vm_prepare_start(true)) {
+ qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
+ cpu_resume(cpu);
+ }
+ return 0;
+}
+
+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 */
--
2.34.1