[PATCH 2/5] target/riscv/tcg/debug.c: add Debug 1.0 'pending' bit

Daniel Henrique Barboza posted 5 patches 1 month, 1 week ago
Maintainers: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>, Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Chao Liu <chao.liu@processmission.com>
[PATCH 2/5] target/riscv/tcg/debug.c: add Debug 1.0 'pending' bit
Posted by Daniel Henrique Barboza 1 month, 1 week ago
We need to set the 'pending' bit when 'count' reaches 0, clearing it right
after the trigger fires.

This is 1.0 exclusive behavior so no changes are needed when running Debug
0.13.

Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
---
 target/riscv/tcg/debug.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/target/riscv/tcg/debug.c b/target/riscv/tcg/debug.c
index 3c0fe70101..2191928761 100644
--- a/target/riscv/tcg/debug.c
+++ b/target/riscv/tcg/debug.c
@@ -77,6 +77,11 @@ static int access_size[SIZE_NUM] = {
     [6 ... 15] = -1,
 };
 
+static bool debug_trigger_version_1_0(CPURISCVState *env)
+{
+    return riscv_cpu_cfg(env)->ext_sdtrig;
+}
+
 static inline target_ulong extract_trigger_type(CPURISCVState *env,
                                                 target_ulong tdata1)
 {
@@ -684,6 +689,17 @@ itrigger_set_count(CPURISCVState *env, int index, int value)
                                    ITRIGGER_COUNT, value);
 }
 
+static inline void
+itrigger_set_pending(CPURISCVState *env, int index, int val)
+{
+    if (!debug_trigger_version_1_0(env)) {
+        return;
+    }
+
+    env->tdata1[index] = set_field(env->tdata1[index],
+                                   ITRIGGER_PENDING, val);
+}
+
 static bool check_itrigger_priv(CPURISCVState *env, int index)
 {
     target_ulong tdata1 = env->tdata1[index];
@@ -735,8 +751,25 @@ void helper_itrigger_match(CPURISCVState *env)
         }
         itrigger_set_count(env, i, count--);
         if (!count) {
+            /*
+             * From the 1.0 spec: "When pending is set, the trigger
+             * fires just before any further instructions are executed
+             * in a mode where the trigger is enabled. As the trigger
+             * fires, pending is cleared."
+             *
+             * And: "This bit becomes set when count is decremented
+             * from 1 to 0. It is cleared when the trigger fires,
+             * which will happen just before executing the next
+             * instruction in one of the enabled modes".
+             *
+             * Note that itrigger_set_pending() is a no-op if we're
+             * running debug 0.13.
+             */
+            itrigger_set_pending(env, i, 1);
+
             env->itrigger_enabled = riscv_itrigger_enabled(env);
             do_trigger_action(env, i);
+            itrigger_set_pending(env, i, 0);
         }
     }
 }
-- 
2.43.0
Re: [PATCH 2/5] target/riscv/tcg/debug.c: add Debug 1.0 'pending' bit
Posted by Alistair Francis 3 weeks ago
On Wed, 2026-08-05 at 15:25 -0300, Daniel Henrique Barboza wrote:
> We need to set the 'pending' bit when 'count' reaches 0, clearing it
> right
> after the trigger fires.
> 
> This is 1.0 exclusive behavior so no changes are needed when running
> Debug
> 0.13.
> 
> Signed-off-by: Daniel Henrique Barboza
> <daniel.barboza@oss.qualcomm.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/riscv/tcg/debug.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/target/riscv/tcg/debug.c b/target/riscv/tcg/debug.c
> index 3c0fe70101..2191928761 100644
> --- a/target/riscv/tcg/debug.c
> +++ b/target/riscv/tcg/debug.c
> @@ -77,6 +77,11 @@ static int access_size[SIZE_NUM] = {
>      [6 ... 15] = -1,
>  };
>  
> +static bool debug_trigger_version_1_0(CPURISCVState *env)
> +{
> +    return riscv_cpu_cfg(env)->ext_sdtrig;
> +}
> +
>  static inline target_ulong extract_trigger_type(CPURISCVState *env,
>                                                  target_ulong tdata1)
>  {
> @@ -684,6 +689,17 @@ itrigger_set_count(CPURISCVState *env, int
> index, int value)
>                                     ITRIGGER_COUNT, value);
>  }
>  
> +static inline void
> +itrigger_set_pending(CPURISCVState *env, int index, int val)
> +{
> +    if (!debug_trigger_version_1_0(env)) {
> +        return;
> +    }
> +
> +    env->tdata1[index] = set_field(env->tdata1[index],
> +                                   ITRIGGER_PENDING, val);
> +}
> +
>  static bool check_itrigger_priv(CPURISCVState *env, int index)
>  {
>      target_ulong tdata1 = env->tdata1[index];
> @@ -735,8 +751,25 @@ void helper_itrigger_match(CPURISCVState *env)
>          }
>          itrigger_set_count(env, i, count--);
>          if (!count) {
> +            /*
> +             * From the 1.0 spec: "When pending is set, the trigger
> +             * fires just before any further instructions are
> executed
> +             * in a mode where the trigger is enabled. As the
> trigger
> +             * fires, pending is cleared."
> +             *
> +             * And: "This bit becomes set when count is decremented
> +             * from 1 to 0. It is cleared when the trigger fires,
> +             * which will happen just before executing the next
> +             * instruction in one of the enabled modes".
> +             *
> +             * Note that itrigger_set_pending() is a no-op if we're
> +             * running debug 0.13.
> +             */
> +            itrigger_set_pending(env, i, 1);
> +
>              env->itrigger_enabled = riscv_itrigger_enabled(env);
>              do_trigger_action(env, i);
> +            itrigger_set_pending(env, i, 0);
>          }
>      }
>  }