diff mbox series

[v2,4/4] hw/intc/loongarch_extioi: Add vmstate post_load support

Message ID 20231215100333.3933632-5-maobibo@loongson.cn (mailing list archive)
State New, archived
Headers show
Series hw/loongarch/virt: Set iocsr address space per-board rather percpu | expand

Commit Message

bibo mao Dec. 15, 2023, 10:03 a.m. UTC
There are elements sw_ipmap and sw_coremap, which is usd to speed
up irq injection flow. They are saved and restored in vmstate during
migration, indeed they can calculated from hw registers. Here
post_load is added for get sw_ipmap and sw_coremap from extioi hw
state.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 hw/intc/loongarch_extioi.c | 120 +++++++++++++++++++++++--------------
 1 file changed, 76 insertions(+), 44 deletions(-)

Comments

gaosong Jan. 9, 2024, 2:36 a.m. UTC | #1
在 2023/12/15 下午6:03, Bibo Mao 写道:
> There are elements sw_ipmap and sw_coremap, which is usd to speed
> up irq injection flow. They are saved and restored in vmstate during
> migration, indeed they can calculated from hw registers. Here
> post_load is added for get sw_ipmap and sw_coremap from extioi hw
> state.
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>   hw/intc/loongarch_extioi.c | 120 +++++++++++++++++++++++--------------
>   1 file changed, 76 insertions(+), 44 deletions(-)

Reviewed-by: Song Gao <gaosong@loongson.cn>

Thanks.
Song Gao
> diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
> index d9d5066c3f..e0fd57f962 100644
> --- a/hw/intc/loongarch_extioi.c
> +++ b/hw/intc/loongarch_extioi.c
> @@ -130,12 +130,66 @@ static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\
>       }
>   }
>   
> +static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
> +                                            uint64_t val, bool notify)
> +{
> +    int i, cpu;
> +
> +    /*
> +     * loongarch only support little endian,
> +     * so we paresd the value with little endian.
> +     */
> +    val = cpu_to_le64(val);
> +
> +    for (i = 0; i < 4; i++) {
> +        cpu = val & 0xff;
> +        cpu = ctz32(cpu);
> +        cpu = (cpu >= 4) ? 0 : cpu;
> +        val = val >> 8;
> +
> +        if (s->sw_coremap[irq + i] == cpu) {
> +            continue;
> +        }
> +
> +        if (notify && test_bit(irq, (unsigned long *)s->isr)) {
> +            /*
> +             * lower irq at old cpu and raise irq at new cpu
> +             */
> +            extioi_update_irq(s, irq + i, 0);
> +            s->sw_coremap[irq + i] = cpu;
> +            extioi_update_irq(s, irq + i, 1);
> +        } else {
> +            s->sw_coremap[irq + i] = cpu;
> +        }
> +    }
> +}
> +
> +static inline void extioi_update_sw_ipmap(LoongArchExtIOI *s, int index,
> +                                          uint64_t val)
> +{
> +    int i;
> +    uint8_t ipnum;
> +
> +    /*
> +     * loongarch only support little endian,
> +     * so we paresd the value with little endian.
> +     */
> +    val = cpu_to_le64(val);
> +    for (i = 0; i < 4; i++) {
> +        ipnum = val & 0xff;
> +        ipnum = ctz32(ipnum);
> +        ipnum = (ipnum >= 4) ? 0 : ipnum;
> +        s->sw_ipmap[index * 4 + i] = ipnum;
> +        val = val >> 8;
> +    }
> +}
> +
>   static MemTxResult extioi_writew(void *opaque, hwaddr addr,
>                             uint64_t val, unsigned size,
>                             MemTxAttrs attrs)
>   {
>       LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> -    int i, cpu, index, old_data, irq;
> +    int cpu, index, old_data, irq;
>       uint32_t offset;
>   
>       trace_loongarch_extioi_writew(addr, val);
> @@ -153,20 +207,7 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr,
>            */
>           index = (offset - EXTIOI_IPMAP_START) >> 2;
>           s->ipmap[index] = val;
> -        /*
> -         * loongarch only support little endian,
> -         * so we paresd the value with little endian.
> -         */
> -        val = cpu_to_le64(val);
> -        for (i = 0; i < 4; i++) {
> -            uint8_t ipnum;
> -            ipnum = val & 0xff;
> -            ipnum = ctz32(ipnum);
> -            ipnum = (ipnum >= 4) ? 0 : ipnum;
> -            s->sw_ipmap[index * 4 + i] = ipnum;
> -            val = val >> 8;
> -        }
> -
> +        extioi_update_sw_ipmap(s, index, val);
>           break;
>       case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
>           index = (offset - EXTIOI_ENABLE_START) >> 2;
> @@ -205,33 +246,8 @@ static MemTxResult extioi_writew(void *opaque, hwaddr addr,
>           irq = offset - EXTIOI_COREMAP_START;
>           index = irq / 4;
>           s->coremap[index] = val;
> -        /*
> -         * loongarch only support little endian,
> -         * so we paresd the value with little endian.
> -         */
> -        val = cpu_to_le64(val);
> -
> -        for (i = 0; i < 4; i++) {
> -            cpu = val & 0xff;
> -            cpu = ctz32(cpu);
> -            cpu = (cpu >= 4) ? 0 : cpu;
> -            val = val >> 8;
> -
> -            if (s->sw_coremap[irq + i] == cpu) {
> -                continue;
> -            }
> -
> -            if (test_bit(irq, (unsigned long *)s->isr)) {
> -                /*
> -                 * lower irq at old cpu and raise irq at new cpu
> -                 */
> -                extioi_update_irq(s, irq + i, 0);
> -                s->sw_coremap[irq + i] = cpu;
> -                extioi_update_irq(s, irq + i, 1);
> -            } else {
> -                s->sw_coremap[irq + i] = cpu;
> -            }
> -        }
> +
> +        extioi_update_sw_coremap(s, irq, val, true);
>           break;
>       default:
>           break;
> @@ -288,6 +304,23 @@ static void loongarch_extioi_finalize(Object *obj)
>       g_free(s->cpu);
>   }
>   
> +static int vmstate_extioi_post_load(void *opaque, int version_id)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    int i, start_irq;
> +
> +    for (i = 0; i < (EXTIOI_IRQS / 4); i++) {
> +        start_irq = i * 4;
> +        extioi_update_sw_coremap(s, start_irq, s->coremap[i], false);
> +    }
> +
> +    for (i = 0; i < (EXTIOI_IRQS_IPMAP_SIZE / 4); i++) {
> +        extioi_update_sw_ipmap(s, i, s->ipmap[i]);
> +    }
> +
> +    return 0;
> +}
> +
>   static const VMStateDescription vmstate_extioi_core = {
>       .name = "extioi-core",
>       .version_id = 1,
> @@ -302,6 +335,7 @@ static const VMStateDescription vmstate_loongarch_extioi = {
>       .name = TYPE_LOONGARCH_EXTIOI,
>       .version_id = 2,
>       .minimum_version_id = 2,
> +    .post_load = vmstate_extioi_post_load,
>       .fields = (VMStateField[]) {
>           VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
>           VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
> @@ -310,8 +344,6 @@ static const VMStateDescription vmstate_loongarch_extioi = {
>           VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOI, EXTIOI_IRQS / 32),
>           VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE / 4),
>           VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOI, EXTIOI_IRQS / 4),
> -        VMSTATE_UINT8_ARRAY(sw_ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE),
> -        VMSTATE_UINT8_ARRAY(sw_coremap, LoongArchExtIOI, EXTIOI_IRQS),
>   
>           VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
>                            vmstate_extioi_core, ExtIOICore),
diff mbox series

Patch

diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index d9d5066c3f..e0fd57f962 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -130,12 +130,66 @@  static inline void extioi_enable_irq(LoongArchExtIOI *s, int index,\
     }
 }
 
+static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
+                                            uint64_t val, bool notify)
+{
+    int i, cpu;
+
+    /*
+     * loongarch only support little endian,
+     * so we paresd the value with little endian.
+     */
+    val = cpu_to_le64(val);
+
+    for (i = 0; i < 4; i++) {
+        cpu = val & 0xff;
+        cpu = ctz32(cpu);
+        cpu = (cpu >= 4) ? 0 : cpu;
+        val = val >> 8;
+
+        if (s->sw_coremap[irq + i] == cpu) {
+            continue;
+        }
+
+        if (notify && test_bit(irq, (unsigned long *)s->isr)) {
+            /*
+             * lower irq at old cpu and raise irq at new cpu
+             */
+            extioi_update_irq(s, irq + i, 0);
+            s->sw_coremap[irq + i] = cpu;
+            extioi_update_irq(s, irq + i, 1);
+        } else {
+            s->sw_coremap[irq + i] = cpu;
+        }
+    }
+}
+
+static inline void extioi_update_sw_ipmap(LoongArchExtIOI *s, int index,
+                                          uint64_t val)
+{
+    int i;
+    uint8_t ipnum;
+
+    /*
+     * loongarch only support little endian,
+     * so we paresd the value with little endian.
+     */
+    val = cpu_to_le64(val);
+    for (i = 0; i < 4; i++) {
+        ipnum = val & 0xff;
+        ipnum = ctz32(ipnum);
+        ipnum = (ipnum >= 4) ? 0 : ipnum;
+        s->sw_ipmap[index * 4 + i] = ipnum;
+        val = val >> 8;
+    }
+}
+
 static MemTxResult extioi_writew(void *opaque, hwaddr addr,
                           uint64_t val, unsigned size,
                           MemTxAttrs attrs)
 {
     LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
-    int i, cpu, index, old_data, irq;
+    int cpu, index, old_data, irq;
     uint32_t offset;
 
     trace_loongarch_extioi_writew(addr, val);
@@ -153,20 +207,7 @@  static MemTxResult extioi_writew(void *opaque, hwaddr addr,
          */
         index = (offset - EXTIOI_IPMAP_START) >> 2;
         s->ipmap[index] = val;
-        /*
-         * loongarch only support little endian,
-         * so we paresd the value with little endian.
-         */
-        val = cpu_to_le64(val);
-        for (i = 0; i < 4; i++) {
-            uint8_t ipnum;
-            ipnum = val & 0xff;
-            ipnum = ctz32(ipnum);
-            ipnum = (ipnum >= 4) ? 0 : ipnum;
-            s->sw_ipmap[index * 4 + i] = ipnum;
-            val = val >> 8;
-        }
-
+        extioi_update_sw_ipmap(s, index, val);
         break;
     case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
         index = (offset - EXTIOI_ENABLE_START) >> 2;
@@ -205,33 +246,8 @@  static MemTxResult extioi_writew(void *opaque, hwaddr addr,
         irq = offset - EXTIOI_COREMAP_START;
         index = irq / 4;
         s->coremap[index] = val;
-        /*
-         * loongarch only support little endian,
-         * so we paresd the value with little endian.
-         */
-        val = cpu_to_le64(val);
-
-        for (i = 0; i < 4; i++) {
-            cpu = val & 0xff;
-            cpu = ctz32(cpu);
-            cpu = (cpu >= 4) ? 0 : cpu;
-            val = val >> 8;
-
-            if (s->sw_coremap[irq + i] == cpu) {
-                continue;
-            }
-
-            if (test_bit(irq, (unsigned long *)s->isr)) {
-                /*
-                 * lower irq at old cpu and raise irq at new cpu
-                 */
-                extioi_update_irq(s, irq + i, 0);
-                s->sw_coremap[irq + i] = cpu;
-                extioi_update_irq(s, irq + i, 1);
-            } else {
-                s->sw_coremap[irq + i] = cpu;
-            }
-        }
+
+        extioi_update_sw_coremap(s, irq, val, true);
         break;
     default:
         break;
@@ -288,6 +304,23 @@  static void loongarch_extioi_finalize(Object *obj)
     g_free(s->cpu);
 }
 
+static int vmstate_extioi_post_load(void *opaque, int version_id)
+{
+    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+    int i, start_irq;
+
+    for (i = 0; i < (EXTIOI_IRQS / 4); i++) {
+        start_irq = i * 4;
+        extioi_update_sw_coremap(s, start_irq, s->coremap[i], false);
+    }
+
+    for (i = 0; i < (EXTIOI_IRQS_IPMAP_SIZE / 4); i++) {
+        extioi_update_sw_ipmap(s, i, s->ipmap[i]);
+    }
+
+    return 0;
+}
+
 static const VMStateDescription vmstate_extioi_core = {
     .name = "extioi-core",
     .version_id = 1,
@@ -302,6 +335,7 @@  static const VMStateDescription vmstate_loongarch_extioi = {
     .name = TYPE_LOONGARCH_EXTIOI,
     .version_id = 2,
     .minimum_version_id = 2,
+    .post_load = vmstate_extioi_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
         VMSTATE_UINT32_ARRAY(nodetype, LoongArchExtIOI,
@@ -310,8 +344,6 @@  static const VMStateDescription vmstate_loongarch_extioi = {
         VMSTATE_UINT32_ARRAY(isr, LoongArchExtIOI, EXTIOI_IRQS / 32),
         VMSTATE_UINT32_ARRAY(ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE / 4),
         VMSTATE_UINT32_ARRAY(coremap, LoongArchExtIOI, EXTIOI_IRQS / 4),
-        VMSTATE_UINT8_ARRAY(sw_ipmap, LoongArchExtIOI, EXTIOI_IRQS_IPMAP_SIZE),
-        VMSTATE_UINT8_ARRAY(sw_coremap, LoongArchExtIOI, EXTIOI_IRQS),
 
         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
                          vmstate_extioi_core, ExtIOICore),