[PATCH] hw/intc/loongarch_dintc: Add loongarch_dintc_cpu_by_arch_id() function

Bibo Mao posted 1 patch 1 month, 2 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260811084331.23526-1-maobibo@loongson.cn
Maintainers: Song Gao <17746591750@163.com>, Bibo Mao <maobibo@loongson.cn>, Xianglai Li <lixianglai@loongson.cn>, Jiaxun Yang <jiaxun.yang@flygoat.com>
hw/intc/loongarch_dintc.c | 49 +++++++++++++++++++++++----------------
1 file changed, 29 insertions(+), 20 deletions(-)
[PATCH] hw/intc/loongarch_dintc: Add loongarch_dintc_cpu_by_arch_id() function
Posted by Bibo Mao 1 month, 2 weeks ago
Similar with IPI, add function loongarch_dintc_cpu_by_arch_id() for
dintc driver. It searches dintc device from physical CPUID, also it
used binary search method, rather than one by one with common API
cpu_by_arch_id().

And use this newly added API in loongarch_dintc_get_cpu() and
loongarch_dintc_mem_write().

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 hw/intc/loongarch_dintc.c | 49 +++++++++++++++++++++++----------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/hw/intc/loongarch_dintc.c b/hw/intc/loongarch_dintc.c
index e40292887c..68c1cfce43 100644
--- a/hw/intc/loongarch_dintc.c
+++ b/hw/intc/loongarch_dintc.c
@@ -26,6 +26,25 @@ FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
 FIELD(MSG_ADDR, CPU_NUM, 12, 8)
 FIELD(MSG_ADDR, FIX, 28, 12)
 
+static int loongarch_dintc_cmp(const void *a, const void *b)
+{
+    DINTCCore *dintc_a = (DINTCCore *)a;
+    DINTCCore *dintc_b = (DINTCCore *)b;
+
+    return dintc_a->arch_id - dintc_b->arch_id;
+}
+
+static DINTCCore *loongarch_dintc_cpu_by_arch_id(LoongArchDINTCState *s,
+                                                 int64_t arch_id)
+{
+    DINTCCore dintc, *found;
+
+    dintc.arch_id = arch_id;
+    found = bsearch(&dintc, s->cpu, s->num_cpu, sizeof(DINTCCore),
+                    loongarch_dintc_cmp);
+    return found;
+}
+
 static uint64_t loongarch_dintc_mem_read(void *opaque,
                                         hwaddr addr, unsigned size)
 {
@@ -49,23 +68,20 @@ static void loongarch_dintc_mem_write(void *opaque, hwaddr addr,
 {
     int irq_num, cpu_num = 0;
     LoongArchDINTCState *s = LOONGARCH_DINTC(opaque);
-    uint64_t msg_addr = addr + VIRT_DINTC_BASE;
+    uint64_t msg_addr = addr + VIRT_DINTC_BASE, arch_id;
+    DINTCCore *core;
     CPUState *cs;
 
-    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
-
-    /* Validate cpu_num against the configured number of CPUs */
-    if (cpu_num >= s->num_cpu) {
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "loongarch-dintc: invalid cpu number%d\n", cpu_num);
-        return;
-    }
-    cs = cpu_by_arch_id(cpu_num);
-    if (!cs) {
+    arch_id = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+    core = loongarch_dintc_cpu_by_arch_id(s, arch_id);
+    if (!core || !core->cpu) {
         qemu_log_mask(LOG_GUEST_ERROR,
-                      "loongarch-dintc: no CPU for arch_id %d\n", cpu_num);
+                      "loongarch-dintc: no CPU for arch_id %"PRId64"\n",
+                      arch_id);
         return;
     }
+    cpu_num = core - s->cpu;
+    cs = core->cpu;
     irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
 
     async_run_on_cpu(cs, do_set_vcpu_dintc_irq,
@@ -135,15 +151,8 @@ static DINTCCore *loongarch_dintc_get_cpu(LoongArchDINTCState *s,
 {
     CPUClass *k = CPU_GET_CLASS(dev);
     uint64_t arch_id = k->get_arch_id(CPU(dev));
-    int i;
-
-    for (i = 0; i < s->num_cpu; i++) {
-        if (s->cpu[i].arch_id == arch_id) {
-            return &s->cpu[i];
-        }
-    }
 
-    return NULL;
+    return loongarch_dintc_cpu_by_arch_id(s, arch_id);
 }
 
 static void loongarch_dintc_cpu_plug(HotplugHandler *hotplug_dev,

base-commit: 3e3ccab106f879b1512f8e0d51a827dd4de30e22
-- 
2.54.0
Re: [PATCH] hw/intc/loongarch_dintc: Add loongarch_dintc_cpu_by_arch_id() function
Posted by Song Gao 1 month, 2 weeks ago
在 2026/8/11 下午4:43, Bibo Mao 写道:
> Similar with IPI, add function loongarch_dintc_cpu_by_arch_id() for
> dintc driver. It searches dintc device from physical CPUID, also it
> used binary search method, rather than one by one with common API
> cpu_by_arch_id().
>
> And use this newly added API in loongarch_dintc_get_cpu() and
> loongarch_dintc_mem_write().
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>   hw/intc/loongarch_dintc.c | 49 +++++++++++++++++++++++----------------
>   1 file changed, 29 insertions(+), 20 deletions(-)
  Reviewed-by:  Song Gao <17746591750@163.com>

Thanks.
Song Gao
> diff --git a/hw/intc/loongarch_dintc.c b/hw/intc/loongarch_dintc.c
> index e40292887c..68c1cfce43 100644
> --- a/hw/intc/loongarch_dintc.c
> +++ b/hw/intc/loongarch_dintc.c
> @@ -26,6 +26,25 @@ FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
>   FIELD(MSG_ADDR, CPU_NUM, 12, 8)
>   FIELD(MSG_ADDR, FIX, 28, 12)
>   
> +static int loongarch_dintc_cmp(const void *a, const void *b)
> +{
> +    DINTCCore *dintc_a = (DINTCCore *)a;
> +    DINTCCore *dintc_b = (DINTCCore *)b;
> +
> +    return dintc_a->arch_id - dintc_b->arch_id;
> +}
> +
> +static DINTCCore *loongarch_dintc_cpu_by_arch_id(LoongArchDINTCState *s,
> +                                                 int64_t arch_id)
> +{
> +    DINTCCore dintc, *found;
> +
> +    dintc.arch_id = arch_id;
> +    found = bsearch(&dintc, s->cpu, s->num_cpu, sizeof(DINTCCore),
> +                    loongarch_dintc_cmp);
> +    return found;
> +}
> +
>   static uint64_t loongarch_dintc_mem_read(void *opaque,
>                                           hwaddr addr, unsigned size)
>   {
> @@ -49,23 +68,20 @@ static void loongarch_dintc_mem_write(void *opaque, hwaddr addr,
>   {
>       int irq_num, cpu_num = 0;
>       LoongArchDINTCState *s = LOONGARCH_DINTC(opaque);
> -    uint64_t msg_addr = addr + VIRT_DINTC_BASE;
> +    uint64_t msg_addr = addr + VIRT_DINTC_BASE, arch_id;
> +    DINTCCore *core;
>       CPUState *cs;
>   
> -    cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> -
> -    /* Validate cpu_num against the configured number of CPUs */
> -    if (cpu_num >= s->num_cpu) {
> -        qemu_log_mask(LOG_GUEST_ERROR,
> -                      "loongarch-dintc: invalid cpu number%d\n", cpu_num);
> -        return;
> -    }
> -    cs = cpu_by_arch_id(cpu_num);
> -    if (!cs) {
> +    arch_id = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> +    core = loongarch_dintc_cpu_by_arch_id(s, arch_id);
> +    if (!core || !core->cpu) {
>           qemu_log_mask(LOG_GUEST_ERROR,
> -                      "loongarch-dintc: no CPU for arch_id %d\n", cpu_num);
> +                      "loongarch-dintc: no CPU for arch_id %"PRId64"\n",
> +                      arch_id);
>           return;
>       }
> +    cpu_num = core - s->cpu;
> +    cs = core->cpu;
>       irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>   
>       async_run_on_cpu(cs, do_set_vcpu_dintc_irq,
> @@ -135,15 +151,8 @@ static DINTCCore *loongarch_dintc_get_cpu(LoongArchDINTCState *s,
>   {
>       CPUClass *k = CPU_GET_CLASS(dev);
>       uint64_t arch_id = k->get_arch_id(CPU(dev));
> -    int i;
> -
> -    for (i = 0; i < s->num_cpu; i++) {
> -        if (s->cpu[i].arch_id == arch_id) {
> -            return &s->cpu[i];
> -        }
> -    }
>   
> -    return NULL;
> +    return loongarch_dintc_cpu_by_arch_id(s, arch_id);
>   }
>   
>   static void loongarch_dintc_cpu_plug(HotplugHandler *hotplug_dev,
>
> base-commit: 3e3ccab106f879b1512f8e0d51a827dd4de30e22