diff mbox series

[v2,17/29] handler for breakpoints and watchpoints added

Message ID 20231006090610.26171-18-nicolas.eder@lauterbach.com
State New
Headers show
Series first version of mcdstub | expand

Commit Message

nicolas.eder@lauterbach.com Oct. 6, 2023, 9:05 a.m. UTC
From: neder <nicolas.eder@lauterbach.com>

---
 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 mbox series

Patch

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;
     }