This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 6ea3bc1217043f2d88e3e61740df618494955f1a
Author: Huang Qi <[email protected]>
AuthorDate: Wed Jul 31 15:56:51 2024 +0800

    riscv/debug: Add support for steppoint
    
    Steppoint can be implemented by icount(instruction count)
    from RISC-V debug extension, but it may not implemented in all RISC-V cores.
    
    Unfortunately, the currently supported RISC-V cores do not implement it.
    
    Signed-off-by: Huang Qi <[email protected]>
---
 arch/risc-v/src/common/riscv_debug.c | 188 +++++++++++++++++++++--------------
 1 file changed, 112 insertions(+), 76 deletions(-)

diff --git a/arch/risc-v/src/common/riscv_debug.c 
b/arch/risc-v/src/common/riscv_debug.c
index 8599e6695d..ac330b1bf4 100644
--- a/arch/risc-v/src/common/riscv_debug.c
+++ b/arch/risc-v/src/common/riscv_debug.c
@@ -78,12 +78,12 @@
  * Private Type
  ****************************************************************************/
 
-/* Trigger Match Control, from version 0.13.2.
+/* Represent the tdata1 register, from the RISC-V Debug Specification 0.13.2
  * Read https://riscv.org/wp-content/uploads/2019/03/riscv-debug-release.pdf
  * for more information
  */
 
-union mcontrol
+union tdata1
 {
   uintptr_t reg;
   struct
@@ -109,7 +109,21 @@ union mcontrol
       uintptr_t maskmax : 6;
       uintptr_t dmode : 1;
       uintptr_t type : 4;
-    };
+    } match;
+
+  struct
+    {
+      uintptr_t action: 6;
+      uintptr_t u : 1;
+      uintptr_t s : 1;
+      uintptr_t reserved0 : 1;
+      uintptr_t m : 1;
+      uintptr_t count : 14;
+      uintptr_t hit : 1;
+      uintptr_t reserved1 : sizeof(uintptr_t) * 8 - 30;
+      uintptr_t dmode : 1;
+      uintptr_t type : 4;
+    } icount;
 };
 
 struct riscv_debug_trigger
@@ -190,7 +204,7 @@ static int riscv_debug_handler(int irq, void *context, void 
*arg)
 
 static int riscv_debug_init(void)
 {
-  union mcontrol mc;
+  union tdata1 reg;
 
   /* Attach the debug exception handler */
 
@@ -223,22 +237,23 @@ static int riscv_debug_init(void)
 
   WRITE_CSR(CSR_TSELECT, 0);
 
-  mc.reg = READ_CSR(CSR_TDATA1);
+  reg.reg = READ_CSR(CSR_TDATA1);
 
   /* REVISIT: NAPOT match is supported and tested on
    * QEMU and ESP32C3, prefer to use it.
    */
 
-  mc.match = MATCH_TYPE_TOPBITS;
+  reg.match.type = TRIGGER_TYPE_ADDRESS_DATA;
+  reg.match.match = MATCH_TYPE_TOPBITS;
 
   /* Write it to tdata1 and read back
    * to check if the NAPOT is supported
    */
 
-  WRITE_CSR(CSR_TDATA1, mc.reg);
-  mc.reg = READ_CSR(CSR_TDATA1);
+  WRITE_CSR(CSR_TDATA1, reg.reg);
+  reg.reg = READ_CSR(CSR_TDATA1);
 
-  if (mc.match == MATCH_TYPE_TOPBITS)
+  if (reg.match.match == MATCH_TYPE_TOPBITS)
     {
       g_support_napot = true;
     }
@@ -257,87 +272,38 @@ static int riscv_debug_init(void)
 }
 
 /****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: up_debugpoint_add
+ * Name: riscv_debug_setup_match
  ****************************************************************************/
 
-int up_debugpoint_add(int type, void *addr, size_t size,
-                      debug_callback_t callback, void *arg)
+static uintptr_t riscv_debug_setup_match(int type, void *addr, size_t size)
 {
-  int slot;
-  union mcontrol mc;
-  int ret = OK;
-  uintptr_t addr_napot;
-
-  /* Initialize the debug module if it is not initialized yet */
-
-  if (g_debug_initiliazed == false)
-    {
-      ret = riscv_debug_init();
-      if (ret < 0)
-        {
-          return ret;
-        }
-
-      g_debug_initiliazed = true;
-    }
-
-  /* Find a free slot */
-
-  slot = riscv_debug_find_slot(0, 0, 0);
-  if (slot < 0)
-    {
-      return slot;
-    }
-
-  /* Select the trigger */
-
-  WRITE_CSR(CSR_TSELECT, slot);
-
-  /* Fetch the current setting from tdata1 */
-
-  mc.reg = READ_CSR(CSR_TDATA1);
-
-  /* Configure trigger */
-
-  mc.m = 1;
-  mc.u = 1;
-  mc.hit = 0;
-  mc.dmode = DMODE_TYPE_BOTH;
-  mc.action = ACTION_TYPE_EXCEPTION;
-
-  mc.execute = 0;
-  mc.load = 0;
-  mc.store = 0;
+  union tdata1 reg;
+  uintptr_t    addr_napot;
 
   if (type == DEBUGPOINT_BREAKPOINT)
     {
-      mc.execute = 1;
+      reg.match.execute = 1;
     }
   else if (type == DEBUGPOINT_WATCHPOINT_RO)
     {
-      mc.load = 1;
+      reg.match.load = 1;
     }
   else if (type == DEBUGPOINT_WATCHPOINT_WO)
     {
-      mc.store = 1;
+      reg.match.store = 1;
     }
   else if (type == DEBUGPOINT_WATCHPOINT_RW)
     {
-      mc.load = 1;
-      mc.store = 1;
+      reg.match.load = 1;
+      reg.match.store = 1;
     }
-  else
-    {
-      /* DEBUGPOINT_STEPPOINT is not supported since current test platform
-       * such as QEMU don't implemented yet.
-       */
 
-      return -ENOTSUP;
-    }
+  reg.match.type = TRIGGER_TYPE_ADDRESS_DATA;
+  reg.match.m = 1;
+  reg.match.u = 1;
+  reg.match.hit = 0;
+  reg.match.dmode = DMODE_TYPE_BOTH;
+  reg.match.action = ACTION_TYPE_EXCEPTION;
 
   /* From RISC-V Debug Specification:
    * tdata1(mcontrol) match = 0 : Exact byte match
@@ -359,17 +325,87 @@ int up_debugpoint_add(int type, void *addr, size_t size,
 
   if (size > 1 && g_support_napot)
     {
-      mc.match = MATCH_TYPE_TOPBITS;
+      reg.match.match = MATCH_TYPE_TOPBITS;
       addr_napot = ((uintptr_t)addr & ~(size - 1)) |
                     ((size - 1) >> 1);
       WRITE_CSR(CSR_TDATA2, addr_napot);
     }
   else
     {
-      mc.match = MATCH_TYPE_EQUAL;
+      reg.match.match = MATCH_TYPE_EQUAL;
       WRITE_CSR(CSR_TDATA2, (uintptr_t)addr);
     }
 
+  return reg.reg;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_debugpoint_add
+ ****************************************************************************/
+
+int up_debugpoint_add(int type, void *addr, size_t size,
+                      debug_callback_t callback, void *arg)
+{
+  int slot;
+  union tdata1 reg;
+  int ret = OK;
+
+  /* Initialize the debug module if it is not initialized yet */
+
+  if (g_debug_initiliazed == false)
+    {
+      ret = riscv_debug_init();
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      g_debug_initiliazed = true;
+    }
+
+  /* Find a free slot */
+
+  slot = riscv_debug_find_slot(0, 0, 0);
+  if (slot < 0)
+    {
+      return slot;
+    }
+
+  /* Select the trigger */
+
+  WRITE_CSR(CSR_TSELECT, slot);
+
+  switch (type)
+    {
+      case DEBUGPOINT_STEPPOINT:
+        /* NOTICE: STEPPOINT implemented but not tested since no such
+         * hardware that implemented icount is available.
+         */
+
+        reg.reg = 0;
+        reg.icount.type = TRIGGER_TYPE_ICOUNT;
+        reg.icount.dmode = DMODE_TYPE_BOTH;
+        reg.icount.count = 1;
+        reg.icount.hit = 0;
+        reg.icount.m = 1;
+        reg.icount.s = 1;
+        reg.icount.u = 1;
+        reg.icount.action = ACTION_TYPE_EXCEPTION;
+        break;
+      case DEBUGPOINT_BREAKPOINT:
+      case DEBUGPOINT_WATCHPOINT_RO:
+      case DEBUGPOINT_WATCHPOINT_RW:
+      case DEBUGPOINT_WATCHPOINT_WO:
+        reg.reg = riscv_debug_setup_match(type, addr, size);
+        break;
+      default:
+        return -EINVAL;
+    }
+
   /* Register the callback and arg */
 
   g_trigger_map[slot].type     = type;
@@ -377,7 +413,7 @@ int up_debugpoint_add(int type, void *addr, size_t size,
   g_trigger_map[slot].size     = size;
   g_trigger_map[slot].callback = callback;
   g_trigger_map[slot].arg      = arg;
-  WRITE_CSR(CSR_TDATA1, mc.reg);
+  WRITE_CSR(CSR_TDATA1, reg.reg);
 
   return 0;
 }

Reply via email to