[PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt.

Song Gao posted 10 patches 5 months, 1 week ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Song Gao <gaosong@loongson.cn>, Bibo Mao <maobibo@loongson.cn>, Jiaxun Yang <jiaxun.yang@flygoat.com>
There is a newer version of this series
[PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt.
Posted by Song Gao 5 months, 1 week ago
we use CSR_ESTAT and CSR_ECFG bit 15 for msg interrupt.
and loongarch_cpu_do_interrupt support msg interrupts.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu-csr.h |  3 ++-
 target/loongarch/cpu.c     | 35 ++++++++++++++++++++++++++++++-----
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 83f6cb081a..5a00cf3366 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -35,11 +35,12 @@ FIELD(CSR_MISC, DWPL, 16, 3)
 
 #define LOONGARCH_CSR_ECFG           0x4 /* Exception config */
 FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, MSGINT, 14, 1)      /* used for msg */
 FIELD(CSR_ECFG, VS, 16, 3)
 
 #define LOONGARCH_CSR_ESTAT          0x5 /* Exception status */
 FIELD(CSR_ESTAT, IS, 0, 13)
-FIELD(CSR_ESTAT, MSGINT, 14, 1)
+FIELD(CSR_ESTAT, MSGINT, 14, 1)    /* used for msg */
 FIELD(CSR_ESTAT, ECODE, 16, 6)
 FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
 
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 207d11266f..b92463101e 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -117,6 +117,13 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
 #ifndef CONFIG_USER_ONLY
 #include "hw/loongarch/virt.h"
 
+static uint32_t loongarch_cpu_has_interrupt(CPULoongArchState *env)
+{
+    uint32_t ret = 0;
+    ret = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+    ret |= FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
+    return ret;
+}
 void loongarch_cpu_set_irq(void *opaque, int irq, int level)
 {
     LoongArchCPU *cpu = opaque;
@@ -134,21 +141,20 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
                 env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
                 env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
                 env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
-                cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+                env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 1);
                 clear_bit(i, &(env->CSR_MSGIS[i / 64]));
             }
         }
     } else {
        env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
-       env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
-       return;
+       env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
     }
 
     if (kvm_enabled()) {
         kvm_loongarch_set_interrupt(cpu, irq, level);
     } else if (tcg_enabled()) {
         env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
-        if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+        if (loongarch_cpu_has_interrupt(env)) {
             cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
@@ -166,12 +172,24 @@ static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
     return ret;
 }
 
+static inline bool cpu_loongarch_hw_interrupt_msg_pending(CPULoongArchState *env)
+{
+    bool pending_msg = 0;
+    bool status_msg = 0;
+
+    pending_msg = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
+    status_msg = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, MSGINT);
+
+    return (pending_msg & status_msg) != 0;
+}
 /* Check if there is pending and not masked out interrupt */
 static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
 {
     uint32_t pending;
     uint32_t status;
-
+    if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
+        return true;
+    }
     pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
     status  = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
 
@@ -285,6 +303,13 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
         uint32_t vector = 0;
         uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
         pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+        if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
+            env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
+            env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
+            set_pc(env, env->CSR_EENTRY + \
+                   (EXCCODE_EXTERNAL_INT + INT_AVEC) * vec_size);
+            return;
+        }
 
         /* Find the highest-priority interrupt. */
         vector = 31 - clz32(pending);
-- 
2.34.1
Re: [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt.
Posted by Bibo Mao 5 months, 1 week ago

On 2025/6/9 下午6:48, Song Gao wrote:
> we use CSR_ESTAT and CSR_ECFG bit 15 for msg interrupt.
> and loongarch_cpu_do_interrupt support msg interrupts.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   target/loongarch/cpu-csr.h |  3 ++-
>   target/loongarch/cpu.c     | 35 ++++++++++++++++++++++++++++++-----
>   2 files changed, 32 insertions(+), 6 deletions(-)
> 
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 83f6cb081a..5a00cf3366 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -35,11 +35,12 @@ FIELD(CSR_MISC, DWPL, 16, 3)
>   
>   #define LOONGARCH_CSR_ECFG           0x4 /* Exception config */
>   FIELD(CSR_ECFG, LIE, 0, 13)
> +FIELD(CSR_ECFG, MSGINT, 14, 1)      /* used for msg */
how about only modify LIE such as FIELD(CSR_ECFG, LIE, 0, 15)?

>   FIELD(CSR_ECFG, VS, 16, 3)
>   
>   #define LOONGARCH_CSR_ESTAT          0x5 /* Exception status */
>   FIELD(CSR_ESTAT, IS, 0, 13)
> -FIELD(CSR_ESTAT, MSGINT, 14, 1)
> +FIELD(CSR_ESTAT, MSGINT, 14, 1)    /* used for msg */
ditto, how about modify IS such as FIELD(CSR_ESTAT, IS, 0, 15)?

Regards
Bibo Mao
>   FIELD(CSR_ESTAT, ECODE, 16, 6)
>   FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
>   
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 207d11266f..b92463101e 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -117,6 +117,13 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
>   #ifndef CONFIG_USER_ONLY
>   #include "hw/loongarch/virt.h"
>   
> +static uint32_t loongarch_cpu_has_interrupt(CPULoongArchState *env)
> +{
> +    uint32_t ret = 0;
> +    ret = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
> +    ret |= FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
> +    return ret;
> +}
>   void loongarch_cpu_set_irq(void *opaque, int irq, int level)
>   {
>       LoongArchCPU *cpu = opaque;
> @@ -134,21 +141,20 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
>                   env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
>                   env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
>                   env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
> -                cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> +                env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 1);
>                   clear_bit(i, &(env->CSR_MSGIS[i / 64]));
>               }
>           }
>       } else {
>          env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> -       env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
> -       return;
> +       env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
>       }
>   
>       if (kvm_enabled()) {
>           kvm_loongarch_set_interrupt(cpu, irq, level);
>       } else if (tcg_enabled()) {
>           env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
> -        if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
> +        if (loongarch_cpu_has_interrupt(env)) {
>               cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>           } else {
>               cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
> @@ -166,12 +172,24 @@ static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
>       return ret;
>   }
>   
> +static inline bool cpu_loongarch_hw_interrupt_msg_pending(CPULoongArchState *env)
> +{
> +    bool pending_msg = 0;
> +    bool status_msg = 0;
> +
> +    pending_msg = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
> +    status_msg = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, MSGINT);
> +
> +    return (pending_msg & status_msg) != 0;
> +}
>   /* Check if there is pending and not masked out interrupt */
>   static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
>   {
>       uint32_t pending;
>       uint32_t status;
> -
> +    if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
> +        return true;
> +    }
>       pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
>       status  = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
>   
> @@ -285,6 +303,13 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
>           uint32_t vector = 0;
>           uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
>           pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
> +        if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
> +            env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> +            env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
> +            set_pc(env, env->CSR_EENTRY + \
> +                   (EXCCODE_EXTERNAL_INT + INT_AVEC) * vec_size);
> +            return;
> +        }
>   
>           /* Find the highest-priority interrupt. */
>           vector = 31 - clz32(pending);
>