Răsfoiți Sursa

hw/intc/loongarch_ipi: Fix mail send and any send function

By the document of ipi mailsend device, byte is written only when the mask bit
is 0. The original code discards mask bit and overwrite the data always, this
patch fixes the issue.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Message-Id: <20220705064901.2353349-3-yangxiaojuan@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Xiaojuan Yang 3 ani în urmă
părinte
comite
bf7ce37f8f
1 a modificat fișierele cu 31 adăugiri și 23 ștergeri
  1. 31 23
      hw/intc/loongarch_ipi.c

+ 31 - 23
hw/intc/loongarch_ipi.c

@@ -50,35 +50,45 @@ static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size)
     return ret;
     return ret;
 }
 }
 
 
-static int get_ipi_data(target_ulong val)
+static void send_ipi_data(CPULoongArchState *env, target_ulong val, target_ulong addr)
 {
 {
-    int i, mask, data;
+    int i, mask = 0, data = 0;
 
 
-    data = val >> 32;
-    mask = (val >> 27) & 0xf;
-
-    for (i = 0; i < 4; i++) {
-        if ((mask >> i) & 1) {
-            data &= ~(0xff << (i * 8));
+    /*
+     * bit 27-30 is mask for byte writing,
+     * if the mask is 0, we need not to do anything.
+     */
+    if ((val >> 27) & 0xf) {
+        data = address_space_ldl(&env->address_space_iocsr, addr,
+                                 MEMTXATTRS_UNSPECIFIED, NULL);
+        for (i = 0; i < 4; i++) {
+            /* get mask for byte writing */
+            if (val & (0x1 << (27 + i))) {
+                mask |= 0xff << (i * 8);
+            }
         }
         }
     }
     }
-    return data;
+
+    data &= mask;
+    data |= (val >> 32) & ~mask;
+    address_space_stl(&env->address_space_iocsr, addr,
+                      data, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 }
 
 
 static void ipi_send(uint64_t val)
 static void ipi_send(uint64_t val)
 {
 {
     int cpuid, data;
     int cpuid, data;
     CPULoongArchState *env;
     CPULoongArchState *env;
+    CPUState *cs;
+    LoongArchCPU *cpu;
 
 
     cpuid = (val >> 16) & 0x3ff;
     cpuid = (val >> 16) & 0x3ff;
     /* IPI status vector */
     /* IPI status vector */
     data = 1 << (val & 0x1f);
     data = 1 << (val & 0x1f);
-    qemu_mutex_lock_iothread();
-    CPUState *cs = qemu_get_cpu(cpuid);
-    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    cs = qemu_get_cpu(cpuid);
+    cpu = LOONGARCH_CPU(cs);
     env = &cpu->env;
     env = &cpu->env;
     loongarch_cpu_set_irq(cpu, IRQ_IPI, 1);
     loongarch_cpu_set_irq(cpu, IRQ_IPI, 1);
-    qemu_mutex_unlock_iothread();
     address_space_stl(&env->address_space_iocsr, 0x1008,
     address_space_stl(&env->address_space_iocsr, 0x1008,
                       data, MEMTXATTRS_UNSPECIFIED, NULL);
                       data, MEMTXATTRS_UNSPECIFIED, NULL);
 
 
@@ -86,23 +96,23 @@ static void ipi_send(uint64_t val)
 
 
 static void mail_send(uint64_t val)
 static void mail_send(uint64_t val)
 {
 {
-    int cpuid, data;
+    int cpuid;
     hwaddr addr;
     hwaddr addr;
     CPULoongArchState *env;
     CPULoongArchState *env;
+    CPUState *cs;
+    LoongArchCPU *cpu;
 
 
     cpuid = (val >> 16) & 0x3ff;
     cpuid = (val >> 16) & 0x3ff;
     addr = 0x1020 + (val & 0x1c);
     addr = 0x1020 + (val & 0x1c);
-    CPUState *cs = qemu_get_cpu(cpuid);
-    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    cs = qemu_get_cpu(cpuid);
+    cpu = LOONGARCH_CPU(cs);
     env = &cpu->env;
     env = &cpu->env;
-    data = get_ipi_data(val);
-    address_space_stl(&env->address_space_iocsr, addr,
-                      data, MEMTXATTRS_UNSPECIFIED, NULL);
+    send_ipi_data(env, val, addr);
 }
 }
 
 
 static void any_send(uint64_t val)
 static void any_send(uint64_t val)
 {
 {
-    int cpuid, data;
+    int cpuid;
     hwaddr addr;
     hwaddr addr;
     CPULoongArchState *env;
     CPULoongArchState *env;
 
 
@@ -111,9 +121,7 @@ static void any_send(uint64_t val)
     CPUState *cs = qemu_get_cpu(cpuid);
     CPUState *cs = qemu_get_cpu(cpuid);
     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
     env = &cpu->env;
     env = &cpu->env;
-    data = get_ipi_data(val);
-    address_space_stl(&env->address_space_iocsr, addr,
-                      data, MEMTXATTRS_UNSPECIFIED, NULL);
+    send_ipi_data(env, val, addr);
 }
 }
 
 
 static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
 static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,