diff mbox series

[v2,1/2] hw/intc/loongarch_extioi: Add extioi virt extension definition

Message ID 20240514090756.988096-2-gaosong@loongson.cn
State New
Headers show
Series Add extioi virt extension support | expand

Commit Message

gaosong May 14, 2024, 9:07 a.m. UTC
On LoongArch, IRQs can be routed to four vcpus with hardware extioi.
This patch adds the extioi virt extension definition so that the IRQ can
route to 256 vcpus.

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 include/hw/intc/loongarch_extioi.h | 21 +++++++
 hw/intc/loongarch_extioi.c         | 92 ++++++++++++++++++++++++++++--
 2 files changed, 109 insertions(+), 4 deletions(-)

Comments

Bibo Mao May 16, 2024, 11:10 a.m. UTC | #1
On 2024/5/14 下午5:07, Song Gao wrote:
> On LoongArch, IRQs can be routed to four vcpus with hardware extioi.
> This patch adds the extioi virt extension definition so that the IRQ can
> route to 256 vcpus.
> 
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   include/hw/intc/loongarch_extioi.h | 21 +++++++
>   hw/intc/loongarch_extioi.c         | 92 ++++++++++++++++++++++++++++--
>   2 files changed, 109 insertions(+), 4 deletions(-)
> 
> diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
> index 410c6e1121..d4646fab9f 100644
> --- a/include/hw/intc/loongarch_extioi.h
> +++ b/include/hw/intc/loongarch_extioi.h
> @@ -41,6 +41,24 @@
>   #define EXTIOI_COREMAP_END           (0xD00 - APIC_OFFSET)
>   #define EXTIOI_SIZE                  0x800
>   
> +#define EXTIOI_VIRT_BASE             (0x40000000)
> +#define EXTIOI_VIRT_SIZE             (0x1000)
> +#define EXTIOI_VIRT_FEATURES         (0x0)
> +#define  EXTIOI_HAS_VIRT_EXTENSION     (0)
> +#define  EXTIOI_HAS_ENABLE_OPTION      (1)
> +#define  EXTIOI_HAS_INT_ENCODE         (2)
> +#define  EXTIOI_HAS_CPU_ENCODE         (3)
> +#define  EXTIOI_VIRT_HAS_FEATURES      (BIT(EXTIOI_HAS_VIRT_EXTENSION)  \
> +                                        | BIT(EXTIOI_HAS_ENABLE_OPTION) \
> +                                        | BIT(EXTIOI_HAS_INT_ENCODE)    \
> +                                       | BIT(EXTIOI_HAS_CPU_ENCODE))
> +#define EXTIOI_VIRT_CONFIG           (0x4)
> +#define  EXTIOI_ENABLE                 (1)
> +#define  EXTIOI_ENABLE_INT_ENCODE      (2)
> +#define  EXTIOI_ENABLE_CPU_ENCODE      (3)
> +#define EXTIOI_VIRT_COREMAP_START    (0x40)
> +#define EXTIOI_VIRT_COREMAP_END      (0x240)
> +
>   typedef struct ExtIOICore {
>       uint32_t coreisr[EXTIOI_IRQS_GROUP_COUNT];
>       DECLARE_BITMAP(sw_isr[LS3A_INTC_IP], EXTIOI_IRQS);
> @@ -52,6 +70,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
>   struct LoongArchExtIOI {
>       SysBusDevice parent_obj;
>       uint32_t num_cpu;
> +    uint32_t features;
> +    uint32_t status;
>       /* hardware state */
>       uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
>       uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
> @@ -65,5 +85,6 @@ struct LoongArchExtIOI {
>       qemu_irq irq[EXTIOI_IRQS];
>       ExtIOICore *cpu;
>       MemoryRegion extioi_system_mem;
> +    MemoryRegion virt_extend;
>   };
>   #endif /* LOONGARCH_EXTIOI_H */
> diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
> index 0b358548eb..89afdb1c3c 100644
> --- a/hw/intc/loongarch_extioi.c
> +++ b/hw/intc/loongarch_extioi.c
> @@ -143,10 +143,13 @@ static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
>   
>       for (i = 0; i < 4; i++) {
>           cpu = val & 0xff;
> -        cpu = ctz32(cpu);
> -        cpu = (cpu >= 4) ? 0 : cpu;
>           val = val >> 8;
>   
> +        if (!(s->status & BIT(EXTIOI_ENABLE_CPU_ENCODE))) {
> +            cpu = ctz32(cpu);
> +            cpu = (cpu >= 4) ? 0 : cpu;
> +        }
> +
>           if (s->sw_coremap[irq + i] == cpu) {
>               continue;
>           }
> @@ -265,6 +268,61 @@ static const MemoryRegionOps extioi_ops = {
>       .endianness = DEVICE_LITTLE_ENDIAN,
>   };
>   
> +static MemTxResult extioi_virt_readw(void *opaque, hwaddr addr, uint64_t *data,
> +                                     unsigned size, MemTxAttrs attrs)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +
> +    switch (addr) {
> +    case EXTIOI_VIRT_FEATURES:
> +        *data = s->features;
> +        break;
> +    case EXTIOI_VIRT_CONFIG:
> +        *data = s->status;
> +        break;
> +    default:
> +        break;
> +    }
> +
> +    return MEMTX_OK;
> +}
> +
> +static MemTxResult extioi_virt_writew(void *opaque, hwaddr addr,
> +                          uint64_t val, unsigned size,
> +                          MemTxAttrs attrs)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +
> +    switch (addr) {
> +    case EXTIOI_VIRT_FEATURES:
> +        return MEMTX_ACCESS_ERROR;
> +
> +    case EXTIOI_VIRT_CONFIG:
> +        /*
> +         * extioi features can only be set at disabled status
> +         */
> +        if ((s->status & BIT(EXTIOI_ENABLE)) && val) {
> +            return MEMTX_ACCESS_ERROR;
> +        }
> +
> +        s->status = val & s->features;
> +        break;
> +    default:
> +        break;
> +    }
> +    return MEMTX_OK;
> +}
> +
> +static const MemoryRegionOps extioi_virt_ops = {
> +    .read_with_attrs = extioi_virt_readw,
> +    .write_with_attrs = extioi_virt_writew,
> +    .impl.min_access_size = 4,
> +    .impl.max_access_size = 4,
> +    .valid.min_access_size = 4,
> +    .valid.max_access_size = 8,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
>   static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
>   {
>       LoongArchExtIOI *s = LOONGARCH_EXTIOI(dev);
> @@ -284,6 +342,16 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
>       memory_region_init_io(&s->extioi_system_mem, OBJECT(s), &extioi_ops,
>                             s, "extioi_system_mem", 0x900);
>       sysbus_init_mmio(sbd, &s->extioi_system_mem);
> +
> +    if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
> +        memory_region_init_io(&s->virt_extend, OBJECT(s), &extioi_virt_ops,
> +                              s, "extioi_virt", EXTIOI_VIRT_SIZE);
> +        sysbus_init_mmio(sbd, &s->virt_extend);
> +        s->features |= EXTIOI_VIRT_HAS_FEATURES;
> +    } else {
> +        s->status |= BIT(EXTIOI_ENABLE);
> +    }
> +
>       s->cpu = g_new0(ExtIOICore, s->num_cpu);
>       if (s->cpu == NULL) {
>           error_setg(errp, "Memory allocation for ExtIOICore faile");
> @@ -304,6 +372,16 @@ static void loongarch_extioi_finalize(Object *obj)
>       g_free(s->cpu);
>   }
>   
> +static void loongarch_extioi_reset(DeviceState *d)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(d);
> +
> +    /* use legacy interrupt routing method by default */
> +    if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
> +        s->status = 0;
> +    }
How about clear status without checking with BIT(EXTIOI_HAS_VIRT_EXTENSION)?


> +}
> +
>   static int vmstate_extioi_post_load(void *opaque, int version_id)
>   {
>       LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> @@ -333,8 +411,8 @@ static const VMStateDescription vmstate_extioi_core = {
>   
>   static const VMStateDescription vmstate_loongarch_extioi = {
>       .name = TYPE_LOONGARCH_EXTIOI,
> -    .version_id = 2,
> -    .minimum_version_id = 2,
> +    .version_id = 3,
> +    .minimum_version_id = 3,
>       .post_load = vmstate_extioi_post_load,
>       .fields = (const VMStateField[]) {
>           VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
> @@ -347,12 +425,17 @@ static const VMStateDescription vmstate_loongarch_extioi = {
>   
>           VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
>                            vmstate_extioi_core, ExtIOICore),
> +
It seems that there is redundant empty line.

Regards
Bibo Mao
> +        VMSTATE_UINT32(features, LoongArchExtIOI),
> +        VMSTATE_UINT32(status, LoongArchExtIOI),
>           VMSTATE_END_OF_LIST()
>       }
>   };
>   
>   static Property extioi_properties[] = {
>       DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOI, num_cpu, 1),
> +    DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOI, features,
> +                    EXTIOI_HAS_VIRT_EXTENSION, 0),
>       DEFINE_PROP_END_OF_LIST(),
>   };
>   
> @@ -361,6 +444,7 @@ static void loongarch_extioi_class_init(ObjectClass *klass, void *data)
>       DeviceClass *dc = DEVICE_CLASS(klass);
>   
>       dc->realize = loongarch_extioi_realize;
> +    dc->reset   = loongarch_extioi_reset;
>       device_class_set_props(dc, extioi_properties);
>       dc->vmsd = &vmstate_loongarch_extioi;
>   }
>
diff mbox series

Patch

diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
index 410c6e1121..d4646fab9f 100644
--- a/include/hw/intc/loongarch_extioi.h
+++ b/include/hw/intc/loongarch_extioi.h
@@ -41,6 +41,24 @@ 
 #define EXTIOI_COREMAP_END           (0xD00 - APIC_OFFSET)
 #define EXTIOI_SIZE                  0x800
 
+#define EXTIOI_VIRT_BASE             (0x40000000)
+#define EXTIOI_VIRT_SIZE             (0x1000)
+#define EXTIOI_VIRT_FEATURES         (0x0)
+#define  EXTIOI_HAS_VIRT_EXTENSION     (0)
+#define  EXTIOI_HAS_ENABLE_OPTION      (1)
+#define  EXTIOI_HAS_INT_ENCODE         (2)
+#define  EXTIOI_HAS_CPU_ENCODE         (3)
+#define  EXTIOI_VIRT_HAS_FEATURES      (BIT(EXTIOI_HAS_VIRT_EXTENSION)  \
+                                        | BIT(EXTIOI_HAS_ENABLE_OPTION) \
+                                        | BIT(EXTIOI_HAS_INT_ENCODE)    \
+                                       | BIT(EXTIOI_HAS_CPU_ENCODE))
+#define EXTIOI_VIRT_CONFIG           (0x4)
+#define  EXTIOI_ENABLE                 (1)
+#define  EXTIOI_ENABLE_INT_ENCODE      (2)
+#define  EXTIOI_ENABLE_CPU_ENCODE      (3)
+#define EXTIOI_VIRT_COREMAP_START    (0x40)
+#define EXTIOI_VIRT_COREMAP_END      (0x240)
+
 typedef struct ExtIOICore {
     uint32_t coreisr[EXTIOI_IRQS_GROUP_COUNT];
     DECLARE_BITMAP(sw_isr[LS3A_INTC_IP], EXTIOI_IRQS);
@@ -52,6 +70,8 @@  OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
 struct LoongArchExtIOI {
     SysBusDevice parent_obj;
     uint32_t num_cpu;
+    uint32_t features;
+    uint32_t status;
     /* hardware state */
     uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
     uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
@@ -65,5 +85,6 @@  struct LoongArchExtIOI {
     qemu_irq irq[EXTIOI_IRQS];
     ExtIOICore *cpu;
     MemoryRegion extioi_system_mem;
+    MemoryRegion virt_extend;
 };
 #endif /* LOONGARCH_EXTIOI_H */
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index 0b358548eb..89afdb1c3c 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -143,10 +143,13 @@  static inline void extioi_update_sw_coremap(LoongArchExtIOI *s, int irq,
 
     for (i = 0; i < 4; i++) {
         cpu = val & 0xff;
-        cpu = ctz32(cpu);
-        cpu = (cpu >= 4) ? 0 : cpu;
         val = val >> 8;
 
+        if (!(s->status & BIT(EXTIOI_ENABLE_CPU_ENCODE))) {
+            cpu = ctz32(cpu);
+            cpu = (cpu >= 4) ? 0 : cpu;
+        }
+
         if (s->sw_coremap[irq + i] == cpu) {
             continue;
         }
@@ -265,6 +268,61 @@  static const MemoryRegionOps extioi_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static MemTxResult extioi_virt_readw(void *opaque, hwaddr addr, uint64_t *data,
+                                     unsigned size, MemTxAttrs attrs)
+{
+    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+
+    switch (addr) {
+    case EXTIOI_VIRT_FEATURES:
+        *data = s->features;
+        break;
+    case EXTIOI_VIRT_CONFIG:
+        *data = s->status;
+        break;
+    default:
+        break;
+    }
+
+    return MEMTX_OK;
+}
+
+static MemTxResult extioi_virt_writew(void *opaque, hwaddr addr,
+                          uint64_t val, unsigned size,
+                          MemTxAttrs attrs)
+{
+    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+
+    switch (addr) {
+    case EXTIOI_VIRT_FEATURES:
+        return MEMTX_ACCESS_ERROR;
+
+    case EXTIOI_VIRT_CONFIG:
+        /*
+         * extioi features can only be set at disabled status
+         */
+        if ((s->status & BIT(EXTIOI_ENABLE)) && val) {
+            return MEMTX_ACCESS_ERROR;
+        }
+
+        s->status = val & s->features;
+        break;
+    default:
+        break;
+    }
+    return MEMTX_OK;
+}
+
+static const MemoryRegionOps extioi_virt_ops = {
+    .read_with_attrs = extioi_virt_readw,
+    .write_with_attrs = extioi_virt_writew,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 8,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
 {
     LoongArchExtIOI *s = LOONGARCH_EXTIOI(dev);
@@ -284,6 +342,16 @@  static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
     memory_region_init_io(&s->extioi_system_mem, OBJECT(s), &extioi_ops,
                           s, "extioi_system_mem", 0x900);
     sysbus_init_mmio(sbd, &s->extioi_system_mem);
+
+    if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
+        memory_region_init_io(&s->virt_extend, OBJECT(s), &extioi_virt_ops,
+                              s, "extioi_virt", EXTIOI_VIRT_SIZE);
+        sysbus_init_mmio(sbd, &s->virt_extend);
+        s->features |= EXTIOI_VIRT_HAS_FEATURES;
+    } else {
+        s->status |= BIT(EXTIOI_ENABLE);
+    }
+
     s->cpu = g_new0(ExtIOICore, s->num_cpu);
     if (s->cpu == NULL) {
         error_setg(errp, "Memory allocation for ExtIOICore faile");
@@ -304,6 +372,16 @@  static void loongarch_extioi_finalize(Object *obj)
     g_free(s->cpu);
 }
 
+static void loongarch_extioi_reset(DeviceState *d)
+{
+    LoongArchExtIOI *s = LOONGARCH_EXTIOI(d);
+
+    /* use legacy interrupt routing method by default */
+    if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) {
+        s->status = 0;
+    }
+}
+
 static int vmstate_extioi_post_load(void *opaque, int version_id)
 {
     LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
@@ -333,8 +411,8 @@  static const VMStateDescription vmstate_extioi_core = {
 
 static const VMStateDescription vmstate_loongarch_extioi = {
     .name = TYPE_LOONGARCH_EXTIOI,
-    .version_id = 2,
-    .minimum_version_id = 2,
+    .version_id = 3,
+    .minimum_version_id = 3,
     .post_load = vmstate_extioi_post_load,
     .fields = (const VMStateField[]) {
         VMSTATE_UINT32_ARRAY(bounce, LoongArchExtIOI, EXTIOI_IRQS_GROUP_COUNT),
@@ -347,12 +425,17 @@  static const VMStateDescription vmstate_loongarch_extioi = {
 
         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, LoongArchExtIOI, num_cpu,
                          vmstate_extioi_core, ExtIOICore),
+
+        VMSTATE_UINT32(features, LoongArchExtIOI),
+        VMSTATE_UINT32(status, LoongArchExtIOI),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static Property extioi_properties[] = {
     DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOI, num_cpu, 1),
+    DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOI, features,
+                    EXTIOI_HAS_VIRT_EXTENSION, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -361,6 +444,7 @@  static void loongarch_extioi_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->realize = loongarch_extioi_realize;
+    dc->reset   = loongarch_extioi_reset;
     device_class_set_props(dc, extioi_properties);
     dc->vmsd = &vmstate_loongarch_extioi;
 }