diff mbox series

[v2,33/43] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)

Message ID 20220425091027.2877892-34-yangxiaojuan@loongson.cn (mailing list archive)
State New, archived
Headers show
Series Add LoongArch softmmu support | expand

Commit Message

Xiaojuan Yang April 25, 2022, 9:10 a.m. UTC
This patch realize PCH-MSI interrupt controller.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 hw/intc/Kconfig                     |  5 ++
 hw/intc/loongarch_pch_msi.c         | 75 +++++++++++++++++++++++++++++
 hw/intc/meson.build                 |  1 +
 hw/intc/trace-events                |  3 ++
 hw/loongarch/Kconfig                |  1 +
 include/hw/intc/loongarch_pch_msi.h | 20 ++++++++
 6 files changed, 105 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_msi.c
 create mode 100644 include/hw/intc/loongarch_pch_msi.h

Comments

Richard Henderson April 27, 2022, 2:01 a.m. UTC | #1
On 4/25/22 02:10, Xiaojuan Yang wrote:
> +static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
> +                                    uint64_t val, unsigned size)
> +{
> +    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
> +    int irq_num = val & 0xff;
> +
> +    trace_loongarch_msi_set_irq(irq_num);
> +    qemu_set_irq(s->pch_msi_irq[irq_num - PCH_PIC_IRQ_NUM], 1);
> +}

This needs to be bounded properly -- irq_num >= PCH_PIC_IRQ_NUM -- since 'val' is under 
the control of the guest.


> +static void pch_msi_irq_handler(void *opaque, int irq, int level)
> +{
> +    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
> +
> +    qemu_set_irq(s->pch_msi_irq[irq], level);
> +}

You should be able to connect the gpio lines directly, rather than having a pass-through 
function like this.  I think this is sysbus_pass_irq.


r~
Mark Cave-Ayland April 28, 2022, 7:40 a.m. UTC | #2
On 27/04/2022 03:01, Richard Henderson wrote:

> On 4/25/22 02:10, Xiaojuan Yang wrote:
>> +static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
>> +                                    uint64_t val, unsigned size)
>> +{
>> +    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
>> +    int irq_num = val & 0xff;
>> +
>> +    trace_loongarch_msi_set_irq(irq_num);
>> +    qemu_set_irq(s->pch_msi_irq[irq_num - PCH_PIC_IRQ_NUM], 1);
>> +}
> 
> This needs to be bounded properly -- irq_num >= PCH_PIC_IRQ_NUM -- since 'val' is 
> under the control of the guest.
> 
> 
>> +static void pch_msi_irq_handler(void *opaque, int irq, int level)
>> +{
>> +    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
>> +
>> +    qemu_set_irq(s->pch_msi_irq[irq], level);
>> +}
> 
> You should be able to connect the gpio lines directly, rather than having a 
> pass-through function like this.  I think this is sysbus_pass_irq.

The *_pass() functions don't work for this case because they directly alias the gpios 
onto another device i.e. an input still remains an input on the target device, rather 
than becoming an output. So I think this is still required here.

However your comment above about PCH_PIC_IRQ_NUM has made me realise that it is 
possible to improve the wiring of the IRQs here, so I'll follow up with replies on a 
few more patches separately.


ATB,

Mark.
Mark Cave-Ayland April 28, 2022, 8:16 a.m. UTC | #3
On 25/04/2022 10:10, Xiaojuan Yang wrote:

> This patch realize PCH-MSI interrupt controller.
> 
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   hw/intc/Kconfig                     |  5 ++
>   hw/intc/loongarch_pch_msi.c         | 75 +++++++++++++++++++++++++++++
>   hw/intc/meson.build                 |  1 +
>   hw/intc/trace-events                |  3 ++
>   hw/loongarch/Kconfig                |  1 +
>   include/hw/intc/loongarch_pch_msi.h | 20 ++++++++
>   6 files changed, 105 insertions(+)
>   create mode 100644 hw/intc/loongarch_pch_msi.c
>   create mode 100644 include/hw/intc/loongarch_pch_msi.h
> 
> diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
> index 1fbba2e728..71c04c328e 100644
> --- a/hw/intc/Kconfig
> +++ b/hw/intc/Kconfig
> @@ -91,3 +91,8 @@ config LOONGARCH_IPI
>   config LOONGARCH_PCH_PIC
>       bool
>       select UNIMP
> +
> +config LOONGARCH_PCH_MSI
> +    select MSI_NONBROKEN
> +    bool
> +    select UNIMP
> diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c
> new file mode 100644
> index 0000000000..57a894f3e5
> --- /dev/null
> +++ b/hw/intc/loongarch_pch_msi.c
> @@ -0,0 +1,75 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU Loongson 7A1000 msi interrupt controller.
> + *
> + * Copyright (C) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "hw/irq.h"
> +#include "hw/intc/loongarch_pch_msi.h"
> +#include "hw/intc/loongarch_pch_pic.h"
> +#include "hw/pci/msi.h"
> +#include "hw/misc/unimp.h"
> +#include "migration/vmstate.h"
> +#include "trace.h"
> +
> +static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    return 0;
> +}
> +
> +static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
> +                                    uint64_t val, unsigned size)
> +{
> +    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
> +    int irq_num = val & 0xff;
> +
> +    trace_loongarch_msi_set_irq(irq_num);
> +    qemu_set_irq(s->pch_msi_irq[irq_num - PCH_PIC_IRQ_NUM], 1);
> +}

This really looks wrong to me: the PCI-MSI device has PCH_PIC_IRQ_NUM IRQs which are 
wired up to EIOINTC with an offset of PCH_MSI_IRQ_START already. What you're saying 
here is that you're manually setting the PCI-MSI IRQs using their EIOINTC IRQ number 
instead of their input IRQ number?

I think what you would want here is just:

    assert(irq_num < PCH_MSI_IRQ_NUM);
    trace_loongarch_msi_set_irq(irq_num);
    qemu_set_irq(s->pch_msi_irq[irq_num], 1);

Otherwise the PCH-MSI device has awareness of IRQ hierarchy outside of itself. 
Presumably this is some kind of testing interface?

> +static const MemoryRegionOps loongarch_pch_msi_ops = {
> +    .read  = loongarch_msi_mem_read,
> +    .write = loongarch_msi_mem_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void pch_msi_irq_handler(void *opaque, int irq, int level)
> +{
> +    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
> +
> +    qemu_set_irq(s->pch_msi_irq[irq], level);
> +}
> +
> +static void loongarch_pch_msi_init(Object *obj)
> +{
> +    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(obj);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +    int i;
> +
> +    memory_region_init_io(&s->msi_mmio, obj, &loongarch_pch_msi_ops,
> +                          s, TYPE_LOONGARCH_PCH_MSI, 0x8);
> +    sysbus_init_mmio(sbd, &s->msi_mmio);
> +    msi_nonbroken = true;
> +
> +    for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
> +        sysbus_init_irq(sbd, &s->pch_msi_irq[i]);
> +    }
> +    qdev_init_gpio_in(DEVICE(obj), pch_msi_irq_handler, PCH_MSI_IRQ_NUM);
> +}

Again I'd simply use GPIOs instead of sysbus_init_irq() here, similar to the example 
given in my reply to the PCH-PIC patch.

> +static const TypeInfo loongarch_pch_msi_info = {
> +    .name          = TYPE_LOONGARCH_PCH_MSI,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(LoongArchPCHMSI),
> +    .instance_init = loongarch_pch_msi_init,
> +};
> +
> +static void loongarch_pch_msi_register_types(void)
> +{
> +    type_register_static(&loongarch_pch_msi_info);
> +}
> +
> +type_init(loongarch_pch_msi_register_types)
> diff --git a/hw/intc/meson.build b/hw/intc/meson.build
> index 960ce81a92..77a30cec33 100644
> --- a/hw/intc/meson.build
> +++ b/hw/intc/meson.build
> @@ -64,3 +64,4 @@ specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))
>   specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
>   specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c'))
>   specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
> +specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index 1f343676ee..8bcc1b6992 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -300,3 +300,6 @@ loongarch_pch_pic_high_readw(unsigned size, uint32_t addr, unsigned long val) "s
>   loongarch_pch_pic_high_writew(unsigned size, uint32_t addr, unsigned long val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
>   loongarch_pch_pic_readb(unsigned size, uint32_t addr, unsigned long val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
>   loongarch_pch_pic_writeb(unsigned size, uint32_t addr, unsigned long val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
> +
> +# loongarch_pch_msi.c
> +loongarch_msi_set_irq(int irq_num) "set msi irq %d"
> diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
> index 2df45f7e8f..d814fc6103 100644
> --- a/hw/loongarch/Kconfig
> +++ b/hw/loongarch/Kconfig
> @@ -4,3 +4,4 @@ config LOONGARCH_VIRT
>       select PCI_EXPRESS_GENERIC_BRIDGE
>       select LOONGARCH_IPI
>       select LOONGARCH_PCH_PIC
> +    select LOONGARCH_PCH_MSI
> diff --git a/include/hw/intc/loongarch_pch_msi.h b/include/hw/intc/loongarch_pch_msi.h
> new file mode 100644
> index 0000000000..f668bfca7a
> --- /dev/null
> +++ b/include/hw/intc/loongarch_pch_msi.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch 7A1000 I/O interrupt controller definitions
> + *
> + * Copyright (C) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi"
> +OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHMSI, LOONGARCH_PCH_MSI)
> +
> +/* Msi irq start start from 64 to 255 */
> +#define PCH_MSI_IRQ_START   64
> +#define PCH_MSI_IRQ_END     255
> +#define PCH_MSI_IRQ_NUM     192
> +
> +struct LoongArchPCHMSI {
> +    SysBusDevice parent_obj;
> +    qemu_irq pch_msi_irq[PCH_MSI_IRQ_NUM];
> +    MemoryRegion msi_mmio;
> +};


ATB,

Mark.
diff mbox series

Patch

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 1fbba2e728..71c04c328e 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -91,3 +91,8 @@  config LOONGARCH_IPI
 config LOONGARCH_PCH_PIC
     bool
     select UNIMP
+
+config LOONGARCH_PCH_MSI
+    select MSI_NONBROKEN
+    bool
+    select UNIMP
diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c
new file mode 100644
index 0000000000..57a894f3e5
--- /dev/null
+++ b/hw/intc/loongarch_pch_msi.c
@@ -0,0 +1,75 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 msi interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0;
+}
+
+static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
+                                    uint64_t val, unsigned size)
+{
+    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+    int irq_num = val & 0xff;
+
+    trace_loongarch_msi_set_irq(irq_num);
+    qemu_set_irq(s->pch_msi_irq[irq_num - PCH_PIC_IRQ_NUM], 1);
+}
+
+static const MemoryRegionOps loongarch_pch_msi_ops = {
+    .read  = loongarch_msi_mem_read,
+    .write = loongarch_msi_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void pch_msi_irq_handler(void *opaque, int irq, int level)
+{
+    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+
+    qemu_set_irq(s->pch_msi_irq[irq], level);
+}
+
+static void loongarch_pch_msi_init(Object *obj)
+{
+    LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    int i;
+
+    memory_region_init_io(&s->msi_mmio, obj, &loongarch_pch_msi_ops,
+                          s, TYPE_LOONGARCH_PCH_MSI, 0x8);
+    sysbus_init_mmio(sbd, &s->msi_mmio);
+    msi_nonbroken = true;
+
+    for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
+        sysbus_init_irq(sbd, &s->pch_msi_irq[i]);
+    }
+    qdev_init_gpio_in(DEVICE(obj), pch_msi_irq_handler, PCH_MSI_IRQ_NUM);
+}
+
+static const TypeInfo loongarch_pch_msi_info = {
+    .name          = TYPE_LOONGARCH_PCH_MSI,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(LoongArchPCHMSI),
+    .instance_init = loongarch_pch_msi_init,
+};
+
+static void loongarch_pch_msi_register_types(void)
+{
+    type_register_static(&loongarch_pch_msi_info);
+}
+
+type_init(loongarch_pch_msi_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 960ce81a92..77a30cec33 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -64,3 +64,4 @@  specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: files('goldfish_pic.c'))
 specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 1f343676ee..8bcc1b6992 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -300,3 +300,6 @@  loongarch_pch_pic_high_readw(unsigned size, uint32_t addr, unsigned long val) "s
 loongarch_pch_pic_high_writew(unsigned size, uint32_t addr, unsigned long val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_readb(unsigned size, uint32_t addr, unsigned long val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_writeb(unsigned size, uint32_t addr, unsigned long val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
+
+# loongarch_pch_msi.c
+loongarch_msi_set_irq(int irq_num) "set msi irq %d"
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 2df45f7e8f..d814fc6103 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -4,3 +4,4 @@  config LOONGARCH_VIRT
     select PCI_EXPRESS_GENERIC_BRIDGE
     select LOONGARCH_IPI
     select LOONGARCH_PCH_PIC
+    select LOONGARCH_PCH_MSI
diff --git a/include/hw/intc/loongarch_pch_msi.h b/include/hw/intc/loongarch_pch_msi.h
new file mode 100644
index 0000000000..f668bfca7a
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_msi.h
@@ -0,0 +1,20 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi"
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHMSI, LOONGARCH_PCH_MSI)
+
+/* Msi irq start start from 64 to 255 */
+#define PCH_MSI_IRQ_START   64
+#define PCH_MSI_IRQ_END     255
+#define PCH_MSI_IRQ_NUM     192
+
+struct LoongArchPCHMSI {
+    SysBusDevice parent_obj;
+    qemu_irq pch_msi_irq[PCH_MSI_IRQ_NUM];
+    MemoryRegion msi_mmio;
+};