All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
To: Xiaojuan Yang <yangxiaojuan@loongson.cn>, qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, thuth@redhat.com, philmd@redhat.com,
	richard.henderson@linaro.org, laurent@vivier.eu,
	peterx@redhat.com, f4bug@amsat.org, alex.bennee@linaro.org,
	alistair.francis@wdc.com, maobibo@loongson.cn,
	gaosong@loongson.cn, pbonzini@redhat.com, i.qemu@xen0n.name,
	chenhuacai@loongson.cn
Subject: Re: [RFC PATCH v3 20/27] hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)
Date: Sat, 18 Dec 2021 00:50:38 +0000	[thread overview]
Message-ID: <d639f689-cc25-ac4d-0d2a-760f64103101@ilande.co.uk> (raw)
In-Reply-To: <1638619645-11283-21-git-send-email-yangxiaojuan@loongson.cn>

On 04/12/2021 12:07, Xiaojuan Yang wrote:

> This patch realize the EIOINTC interrupt controller.
> 
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   hw/intc/Kconfig                    |   3 +
>   hw/intc/loongarch_extioi.c         | 499 +++++++++++++++++++++++++++++
>   hw/intc/meson.build                |   1 +
>   hw/intc/trace-events               |   9 +
>   hw/loongarch/Kconfig               |   1 +
>   include/hw/intc/loongarch_extioi.h |  69 ++++
>   6 files changed, 582 insertions(+)
>   create mode 100644 hw/intc/loongarch_extioi.c
>   create mode 100644 include/hw/intc/loongarch_extioi.h
> 
> diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
> index dc5f41f5f5..2868b25005 100644
> --- a/hw/intc/Kconfig
> +++ b/hw/intc/Kconfig
> @@ -85,3 +85,6 @@ config LOONGARCH_PCH_MSI
>       select MSI_NONBROKEN
>       bool
>       select UNIMP
> +
> +config LOONGARCH_EXTIOI
> +    bool
> diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
> new file mode 100644
> index 0000000000..9838f05806
> --- /dev/null
> +++ b/hw/intc/loongarch_extioi.c
> @@ -0,0 +1,499 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Loongson 3A5000 ext interrupt controller emulation
> + *
> + * Copyright (C) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/module.h"
> +#include "qemu/log.h"
> +#include "hw/irq.h"
> +#include "hw/sysbus.h"
> +#include "hw/loongarch/loongarch.h"
> +#include "hw/qdev-properties.h"
> +#include "exec/address-spaces.h"
> +#include "hw/intc/loongarch_extioi.h"
> +#include "migration/vmstate.h"
> +#include "trace.h"
> +
> +static void extioi_update_irq(void *opaque, int irq_num, int level)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    uint8_t  ipnum, cpu;
> +    unsigned long found1, found2;
> +
> +    ipnum = s->sw_ipmap[irq_num];
> +    cpu   = s->sw_coremap[irq_num];
> +    if (level == 1) {
> +        if (test_bit(irq_num, (void *)s->enable) == false) {
> +            return;
> +        }
> +        bitmap_set((void *)s->coreisr[cpu], irq_num, 1);
> +        found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
> +                               EXTIOI_IRQS, 0);
> +        bitmap_set((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1);
> +
> +        if (found1 >= EXTIOI_IRQS) {
> +            qemu_set_irq(s->parent_irq[cpu][ipnum], level);
> +        }
> +    } else {
> +        bitmap_clear((void *)s->coreisr[cpu], irq_num, 1);
> +        found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
> +                               EXTIOI_IRQS, 0);
> +        bitmap_clear((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1);
> +        found2 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
> +                               EXTIOI_IRQS, 0);
> +
> +        if ((found1 < EXTIOI_IRQS) && (found2 >= EXTIOI_IRQS)) {
> +            qemu_set_irq(s->parent_irq[cpu][ipnum], level);
> +        }
> +    }
> +}
> +
> +static void extioi_setirq(void *opaque, int irq, int level)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    trace_extioi_setirq(irq, level);
> +    extioi_update_irq(s, irq, level);
> +}
> +
> +static uint32_t extioi_readb(void *opaque, hwaddr addr)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    uint8_t ret;
> +    int cpu;
> +
> +    offset = addr & 0xffff;
> +
> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
> +        ret = ldub_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
> +    } else if ((offset >= EXTIOI_BOUNCE_START) && (offset < EXTIOI_BOUNCE_END)) {
> +        ret = ldub_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
> +    } else if ((offset >= EXTIOI_COREISR_START) && (offset < EXTIOI_COREISR_END)) {
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +        ret = ldub_p((void *)s->coreisr[cpu] + reg_count);
> +    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) {
> +        ret = ldub_p((void *)&s->ipmap + (offset - EXTIOI_IPMAP_START));
> +    } else if ((offset >= EXTIOI_COREMAP_START) && (offset < EXTIOI_COREMAP_END)) {
> +        ret = ldub_p((void *)s->coremap + (offset - EXTIOI_COREMAP_START));
> +    } else if ((offset >= EXTIOI_NODETYPE_START) && (offset < EXTIOI_NODETYPE_END)) {
> +        ret = ldub_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START));
> +    }
> +
> +    trace_loongarch_extioi_readb((uint32_t)addr, ret);
> +    return ret;
> +}
> +
> +static uint32_t extioi_readw(void *opaque, hwaddr addr)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    uint32_t ret;
> +    int cpu;
> +
> +    offset = addr & 0xffff;
> +
> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
> +        ret = ldl_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
> +    } else if ((offset >= EXTIOI_BOUNCE_START) && (offset < EXTIOI_BOUNCE_END)) {
> +        ret = ldl_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
> +    } else if ((offset >= EXTIOI_COREISR_START) && (offset < EXTIOI_COREISR_END)) {
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +        ret = ldl_p((void *)s->coreisr[cpu] + reg_count);
> +    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) {
> +        ret = ldl_p((void *)&s->ipmap + (offset - EXTIOI_IPMAP_START));
> +    } else if ((offset >= EXTIOI_COREMAP_START) && (offset < EXTIOI_COREMAP_END)) {
> +        ret = ldl_p((void *)s->coremap + (offset - EXTIOI_COREMAP_START));
> +    } else if ((offset >= EXTIOI_NODETYPE_START) && (offset < EXTIOI_NODETYPE_END)) {
> +        ret = ldl_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START));
> +    }
> +
> +    trace_loongarch_extioi_readw((uint32_t)addr, ret);
> +    return ret;
> +}
> +
> +static uint64_t extioi_readl(void *opaque, hwaddr addr)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    uint64_t ret;
> +    int cpu;
> +
> +    offset = addr & 0xffff;
> +
> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
> +        ret = ldq_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
> +    } else if ((offset >= EXTIOI_BOUNCE_START) && (offset < EXTIOI_BOUNCE_END)) {
> +        ret = ldq_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
> +    } else if ((offset >= EXTIOI_COREISR_START) && (offset < EXTIOI_COREISR_END)) {
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +        ret = ldq_p((void *)s->coreisr[cpu] + reg_count);
> +    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) {
> +        ret = ldq_p((void *)&s->ipmap + (offset - EXTIOI_IPMAP_START));
> +    } else if ((offset >= EXTIOI_COREMAP_START) && (offset < EXTIOI_COREMAP_END)) {
> +        ret = ldq_p((void *)s->coremap + (offset - EXTIOI_COREMAP_START));
> +    } else if ((offset >= EXTIOI_NODETYPE_START) && (offset < EXTIOI_NODETYPE_END)) {
> +        ret = ldq_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START));
> +    }
> +
> +    trace_loongarch_extioi_readl((uint32_t)addr, ret);
> +    return ret;
> +}
> +
> +static void extioi_writeb(void *opaque, hwaddr addr, uint32_t val,
> +                          unsigned size)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    uint8_t old_data;
> +    int cpu, i, j, ipnum, level, irqnum, bits;
> +
> +    offset = addr & 0xffff;
> +    val = val & 0xffUL;
> +
> +    trace_loongarch_extioi_writeb(size, (uint32_t)addr, val);
> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
> +        reg_count = (offset - EXTIOI_ENABLE_START);
> +        old_data = ldub_p((void *)s->enable + reg_count);
> +        if (old_data != val) {
> +            stb_p((void *)s->enable + reg_count, val);
> +            old_data = old_data ^ val;
> +            bits = size * 8;
> +            while ((i = find_first_bit((void *)&old_data, bits)) != bits) {
> +                level = test_bit(i, (unsigned long *)&val);
> +                extioi_update_irq(s, i + reg_count * 8, level);
> +                clear_bit(i, (void *)&old_data);
> +            }
> +        }
> +    } else if ((offset >= EXTIOI_BOUNCE_START) && (offset < EXTIOI_BOUNCE_END)) {
> +        stb_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START), val);
> +    } else if ((offset >= EXTIOI_COREISR_START) && (offset < EXTIOI_COREISR_END)) {
> +        reg_count = (offset - EXTIOI_COREISR_START) & 0x1f;
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +
> +        old_data = ldub_p((void *)s->coreisr[cpu] + reg_count);
> +        stb_p((void *)s->coreisr[cpu] + reg_count, (old_data & ~val));
> +
> +        if (old_data != (old_data & ~val)) {
> +            bits = size * 8;
> +
> +            while ((i = find_first_bit((void *)&val, bits)) != bits) {
> +                j = test_bit(i, (unsigned long *)&old_data);
> +                if (j) {
> +                    extioi_update_irq(s, i + reg_count * 8, 0);
> +                }
> +                clear_bit(i, (void *)&val);
> +            }
> +        }
> +    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) {
> +        /* Drop arch.core_ip_mask use s->ipmap */
> +        reg_count = (offset - EXTIOI_IPMAP_START);
> +        stb_p((void *)&s->ipmap + reg_count, val);
> +
> +        /* Routing in groups of 32 interrupt */
> +        while (val) {
> +            ipnum = find_first_bit((void *)&val, 4);
> +            for (i = 0; i < 32; i++) {
> +                irqnum = reg_count * 32 + i;
> +                if (ipnum != 4) {
> +                    s->sw_ipmap[irqnum] = ipnum;
> +                } else {
> +                    s->sw_ipmap[irqnum] = 0;
> +                }
> +            }
> +            val = val >> 8;
> +            reg_count += 1;
> +        }
> +    } else if ((offset >= EXTIOI_COREMAP_START) && (offset < EXTIOI_COREMAP_END)) {
> +        reg_count = (offset - EXTIOI_COREMAP_START);
> +
> +        /* Only map the core */
> +        while (val) {
> +            stb_p((void *)s->coremap + reg_count, val);
> +            s->sw_coremap[reg_count] = val & 0xf;
> +            val = val >> 8;
> +        }
> +    } else if ((offset >= EXTIOI_NODETYPE_START) && (offset < EXTIOI_NODETYPE_END)) {
> +        stb_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START), val);
> +    }
> +}
> +
> +static void extioi_writew(void *opaque, hwaddr addr, uint32_t val,
> +                          unsigned size)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    int cpu, level, irqnum, ipnum;
> +    uint32_t offset, old_data, reg_count, i, j, bits;
> +
> +    offset = addr & 0xffff;
> +    trace_loongarch_extioi_writew(size, (uint32_t)addr, val);
> +
> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
> +        reg_count = (offset - EXTIOI_ENABLE_START);
> +        old_data = ldl_p((void *)s->enable + reg_count);
> +        if (old_data != val) {
> +            stl_p((void *)s->enable + reg_count, val);
> +            old_data = old_data ^ val;
> +
> +            bits = size * 8;
> +            while ((i = find_first_bit((void *)&old_data, bits)) != bits) {
> +                level = test_bit(i, (unsigned long *)&val);
> +                extioi_update_irq(s, i + reg_count * 8, level);
> +                clear_bit(i, (void *)&old_data);
> +            }
> +        }
> +    } else if ((offset >= EXTIOI_BOUNCE_START) && (offset < EXTIOI_BOUNCE_END)) {
> +        stl_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START), val);
> +    } else if ((offset >= EXTIOI_COREISR_START) && (offset < EXTIOI_COREISR_END)) {
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +
> +        /* Ext_core_ioisr */
> +        old_data = ldl_p((void *)s->coreisr[cpu] + reg_count);
> +        stl_p((void *)s->coreisr[cpu] + reg_count, (old_data & ~val));
> +
> +        if (old_data != (old_data & ~val)) {
> +            bits = size * 8;
> +            while ((i = find_first_bit((void *)&val, bits)) != bits) {
> +                j = test_bit(i, (unsigned long *)&old_data);
> +                if (j) {
> +                    extioi_update_irq(s, i + reg_count * 8, 0);
> +                }
> +                clear_bit(i, (void *)&val);
> +            }
> +        }
> +    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) {
> +        /* Drop arch.core_ip_mask use s->ipmap */
> +        reg_count = (offset - EXTIOI_IPMAP_START);
> +        stl_p((void *)&s->ipmap + reg_count, val);
> +
> +        /* Routing in groups of 32 interrupt */
> +        while (val) {
> +            ipnum = find_first_bit((void *)&val, 4);
> +            for (i = 0; i < 32; i++) {
> +                irqnum = reg_count * 32 + i;
> +                if (ipnum != 4) {
> +                    s->sw_ipmap[irqnum] = ipnum;
> +                } else {
> +                    s->sw_ipmap[irqnum] = 0;
> +                }
> +            }
> +            val = val >> 8;
> +            reg_count += 1;
> +        }
> +    } else if ((offset >= EXTIOI_COREMAP_START) && (offset < EXTIOI_COREMAP_END)) {
> +        reg_count = (offset - EXTIOI_COREMAP_START);
> +        /* Only map the core */
> +        while (val) {
> +            stl_p((void *)s->coremap + reg_count, val);
> +            s->sw_coremap[reg_count] = val & 0xf;
> +            val = val >> 8;
> +        }
> +    } else if ((offset >= EXTIOI_NODETYPE_START) && (offset < EXTIOI_NODETYPE_END)) {
> +        stl_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START), val);
> +    }
> +}
> +
> +static void extioi_writel(void *opaque, hwaddr addr, uint64_t val,
> +                          unsigned size)
> +{
> +    loongarch_extioi *s = LOONGARCH_EXTIOI(opaque);
> +    int cpu, level, i, j, bits, ipnum, irqnum;
> +    uint64_t offset, old_data, reg_count;
> +
> +    offset = addr & 0xffff;
> +    trace_loongarch_extioi_writel(size, (uint32_t)addr, val);
> +
> +    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
> +        reg_count = (offset - EXTIOI_ENABLE_START);
> +        old_data = s->enable[reg_count];
> +        if (old_data != val) {
> +            s->enable[reg_count] = val;
> +            old_data = old_data ^ val;
> +
> +            bits = size * 8;
> +            while ((i = find_first_bit((void *)&old_data, bits)) != bits) {
> +                level = test_bit(i, (unsigned long *)&val);
> +                extioi_update_irq(s, i + reg_count * 8, level);
> +                clear_bit(i, (void *)&old_data);
> +            }
> +        }
> +    } else if ((offset >= EXTIOI_BOUNCE_START) && (offset < EXTIOI_BOUNCE_END)) {
> +        stq_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START), val);
> +    } else if ((offset >= EXTIOI_COREISR_START) && (offset < EXTIOI_COREISR_END)) {
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +
> +        /* core_ext_ioisr */
> +        old_data = ldq_p((void *)s->coreisr[cpu] + reg_count);
> +        stq_p((void *)s->coreisr[cpu] + reg_count, (old_data & ~val));
> +
> +        if (old_data != (old_data & ~val)) {
> +            bits = size * 8;
> +            while ((i = find_first_bit((void *)&val, bits)) != bits) {
> +                j = test_bit(i, (unsigned long *)&old_data);
> +                if (j) {
> +                    extioi_update_irq(s, i + reg_count * 8, 0);
> +                }
> +                clear_bit(i, (void *)&val);
> +            }
> +        }
> +    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) {
> +        /* Drop arch.core_ip_mask use s->ipmap */
> +        reg_count = (offset - EXTIOI_IPMAP_START);
> +        stq_p((void *)&s->ipmap + reg_count, val);
> +
> +        /* Routing in groups of 32 interrupt */
> +        while (val) {
> +            ipnum = find_first_bit((void *)&val, 4);
> +            for (i = 0; i < 32; i++) {
> +                irqnum = reg_count * 32 + i;
> +                if (ipnum != 4) {
> +                    s->sw_ipmap[irqnum] = ipnum;
> +                } else {
> +                    s->sw_ipmap[irqnum] = 0;
> +                }
> +            }
> +            val = val >> 8;
> +            reg_count += 1;
> +        }
> +    } else if ((offset >= EXTIOI_COREMAP_START) && (offset < EXTIOI_COREMAP_END)) {
> +        reg_count = (offset - EXTIOI_COREMAP_START);
> +        /* Only map the core */
> +        while (val) {
> +            stq_p((void *)s->coremap + reg_count, val);
> +            s->sw_coremap[reg_count] = val & 0xf;
> +            val = val >> 8;
> +        }
> +    } else if ((offset >= EXTIOI_NODETYPE_START) && (offset < EXTIOI_NODETYPE_END)) {
> +        stq_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START), val);
> +    }
> +}
> +
> +static uint64_t extioi_readfn(void *opaque, hwaddr addr, unsigned size)
> +{
> +    switch (size) {
> +    case 1:
> +        return extioi_readb(opaque, addr);
> +    case 4:
> +        return extioi_readw(opaque, addr);
> +    case 8:
> +        return extioi_readl(opaque, addr);
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
> +static void extioi_writefn(void *opaque, hwaddr addr,
> +                           uint64_t value, unsigned size)
> +{
> +    switch (size) {
> +    case 1:
> +        extioi_writeb(opaque, addr, value, size);
> +        break;
> +    case 4:
> +        extioi_writew(opaque, addr, value, size);
> +        break;
> +    case 8:
> +        extioi_writel(opaque, addr, value, size);
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
> +static const MemoryRegionOps extioi_ops = {
> +    .read = extioi_readfn,
> +    .write = extioi_writefn,
> +    .impl.min_access_size = 1,
> +    .impl.max_access_size = 8,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 8,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};

Are all of the extioi registers accessible with 1 byte accesses? It feels as if this 
should be split into separate memory regions.

> +static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
> +{
> +    LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
> +    MachineState *ms = MACHINE(lams);

Since lams isn't used could you not just use:

MachineState *ms = MACHINE(qdev_get_machine());

> +    loongarch_extioi *p = LOONGARCH_EXTIOI(dev);
> +    int i, cpu, pin;
> +
> +    qdev_init_gpio_in(dev, extioi_setirq, EXTIOI_IRQS);
> +
> +    for (i = 0; i < EXTIOI_IRQS; i++) {
> +        sysbus_init_irq(SYS_BUS_DEVICE(dev), &p->irq[i]);
> +    }

Since qdev_init_gpio_in() doesn't depend upon a qdev property you can do this in an 
instance init function rather than realize.

> +    memory_region_init_io(&p->mmio, OBJECT(p), &extioi_ops, p,
> +                          TYPE_LOONGARCH_EXTIOI, 0x900);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &p->mmio);

Same here.

> +    for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
> +        for (pin = 0; pin < LS3A_INTC_IP; pin++) {
> +            qdev_init_gpio_out(dev, &p->parent_irq[cpu][pin], 1);
> +        }
> +    }
> +}
> +
> +static const VMStateDescription vmstate_ext_sw_ipisr = {
> +    .name = "ext_sw_ipisr",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8_ARRAY(irq, ext_sw_ipisr, EXTIOI_IRQS_BITMAP_SIZE),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_loongarch_extioi = {
> +    .name = TYPE_LOONGARCH_EXTIOI,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64_ARRAY(enable, loongarch_extioi,
> +                             EXTIOI_IRQS_BITMAP_SIZE / 8),
> +        VMSTATE_UINT64_ARRAY(bounce, loongarch_extioi,
> +                             EXTIOI_IRQS_BITMAP_SIZE / 8),
> +        VMSTATE_UINT64_2DARRAY(coreisr, loongarch_extioi,
> +                               MAX_CORES, EXTIOI_IRQS_BITMAP_SIZE / 8),
> +        VMSTATE_UINT64(ipmap, loongarch_extioi),
> +        VMSTATE_UINT64_ARRAY(coremap, loongarch_extioi,
> +                             EXTIOI_IRQS_COREMAP_SIZE / 8),
> +        VMSTATE_UINT64_ARRAY(nodetype, loongarch_extioi,
> +                             EXTIOI_IRQS_NODETYPE_SIZE / 4),
> +        VMSTATE_UINT8_ARRAY(sw_ipmap, loongarch_extioi, EXTIOI_IRQS),
> +        VMSTATE_UINT8_ARRAY(sw_coremap, loongarch_extioi, EXTIOI_IRQS),
> +        VMSTATE_STRUCT_2DARRAY(sw_ipisr, loongarch_extioi, MAX_CORES,
> +                               LS3A_INTC_IP, 1, vmstate_ext_sw_ipisr,
> +                               ext_sw_ipisr),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void loongarch_extioi_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->vmsd = &vmstate_loongarch_extioi;
> +    dc->realize = loongarch_extioi_realize;
> +}
> +
> +static const TypeInfo loongarch_extioi_info = {
> +    .name          = TYPE_LOONGARCH_EXTIOI,

TYPE_LOONGARCH_EXTIOI_SYS_BUS_DEVICE helps to show the inheritance from SYS_BUS_DEVICE.

> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(struct loongarch_extioi),
> +    .class_init    = loongarch_extioi_class_init,
> +};
> +
> +static void loongarch_extioi_register_types(void)
> +{
> +    type_register_static(&loongarch_extioi_info);
> +}
> +
> +type_init(loongarch_extioi_register_types)
> diff --git a/hw/intc/meson.build b/hw/intc/meson.build
> index acefe0c5aa..cee88a0d73 100644
> --- a/hw/intc/meson.build
> +++ b/hw/intc/meson.build
> @@ -60,3 +60,4 @@ 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'))
> +specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c'))
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index 20da343cfe..3f85126cf0 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -258,3 +258,12 @@ loongarch_pch_pic_write(unsigned size, uint32_t addr, unsigned long val) "size:
>   
>   # loongarch_pch_msi.c
>   loongarch_msi_set_irq(int irq_num) "set msi irq %d"
> +
> +# loongarch_extioi.c
> +extioi_setirq(int irq, int level) "set extirq irq %d level %d"
> +loongarch_extioi_readb(uint32_t addr, uint8_t val) "addr: 0x%"PRIx32 "val: 0x%" PRIu8
> +loongarch_extioi_readw(uint32_t addr, uint32_t val) "addr: 0x%"PRIx32 "val: 0x%" PRIx32
> +loongarch_extioi_readl(uint32_t addr, uint64_t val) "addr: 0x%"PRIx32 "val: 0x%" PRIx64
> +loongarch_extioi_writeb(unsigned size, uint32_t addr, uint8_t val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIu8
> +loongarch_extioi_writew(unsigned size, uint32_t addr, uint32_t val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx32
> +loongarch_extioi_writel(unsigned size, uint32_t addr, uint64_t val) "size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
> diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
> index cd38d03a19..468e3acc74 100644
> --- a/hw/loongarch/Kconfig
> +++ b/hw/loongarch/Kconfig
> @@ -4,3 +4,4 @@ config LOONGSON3_LS7A
>       select LOONGARCH_IPI
>       select LOONGARCH_PCH_PIC
>       select LOONGARCH_PCH_MSI
> +    select LOONGARCH_EXTIOI
> diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
> new file mode 100644
> index 0000000000..4e6a20dced
> --- /dev/null
> +++ b/include/hw/intc/loongarch_extioi.h
> @@ -0,0 +1,69 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * LoongArch 3A5000 ext interrupt controller definitions
> + *
> + * Copyright (C) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "hw/sysbus.h"
> +#include "hw/loongarch/loongarch.h"
> +
> +#ifndef LOONGARCH_EXTIOI_H
> +#define LOONGARCH_EXTIOI_H
> +
> +#define LS3A_INTC_IP               8
> +#define MAX_CORES                  LOONGARCH_MAX_VCPUS
> +#define EXTIOI_IRQS                (256)
> +#define EXTIOI_IRQS_BITMAP_SIZE    (256 / 8)
> +/* map to ipnum per 32 irqs */
> +#define EXTIOI_IRQS_IPMAP_SIZE     (256 / 32)
> +#define EXTIOI_IRQS_COREMAP_SIZE   256
> +#define EXTIOI_IRQS_NODETYPE_SIZE  16
> +
> +#define APIC_OFFSET                  0x400
> +#define APIC_BASE                    (0x1000ULL + APIC_OFFSET)
> +
> +#define EXTIOI_NODETYPE_START        (0x4a0 - APIC_OFFSET)
> +#define EXTIOI_NODETYPE_END          (0x4c0 - APIC_OFFSET)
> +#define EXTIOI_IPMAP_START           (0x4c0 - APIC_OFFSET)
> +#define EXTIOI_IPMAP_END             (0x4c8 - APIC_OFFSET)
> +#define EXTIOI_ENABLE_START          (0x600 - APIC_OFFSET)
> +#define EXTIOI_ENABLE_END            (0x620 - APIC_OFFSET)
> +#define EXTIOI_BOUNCE_START          (0x680 - APIC_OFFSET)
> +#define EXTIOI_BOUNCE_END            (0x6a0 - APIC_OFFSET)
> +#define EXTIOI_ISR_START             (0x700 - APIC_OFFSET)
> +#define EXTIOI_ISR_END               (0x720 - APIC_OFFSET)
> +#define EXTIOI_COREISR_START         (0x800 - APIC_OFFSET)
> +#define EXTIOI_COREISR_END           (0xB20 - APIC_OFFSET)
> +#define EXTIOI_COREMAP_START         (0xC00 - APIC_OFFSET)
> +#define EXTIOI_COREMAP_END           (0xD00 - APIC_OFFSET)
> +
> +#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi"
> +DECLARE_INSTANCE_CHECKER(struct loongarch_extioi, LOONGARCH_EXTIOI,
> +                         TYPE_LOONGARCH_EXTIOI)
> +
> +typedef struct ext_sw_ipisr {
> +    uint8_t irq[EXTIOI_IRQS_BITMAP_SIZE];
> +} ext_sw_ipisr;
> +
> +typedef struct loongarch_extioi {

LoongArchExtIOI?

> +    SysBusDevice parent_obj;
> +    /* hardware state */
> +    uint64_t enable[EXTIOI_IRQS_BITMAP_SIZE / 8];
> +    uint64_t bounce[EXTIOI_IRQS_BITMAP_SIZE / 8];
> +    uint64_t coreisr[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE / 8];
> +    uint64_t ipmap;
> +    uint64_t coremap[EXTIOI_IRQS_COREMAP_SIZE / 8];
> +    uint64_t nodetype[EXTIOI_IRQS_NODETYPE_SIZE / 4];
> +
> +    /*software state */
> +    uint8_t sw_ipmap[EXTIOI_IRQS];
> +    uint8_t sw_coremap[EXTIOI_IRQS];
> +    ext_sw_ipisr sw_ipisr[MAX_CORES][LS3A_INTC_IP];
> +
> +    qemu_irq parent_irq[MAX_CORES][LS3A_INTC_IP];
> +    qemu_irq irq[EXTIOI_IRQS];
> +    MemoryRegion mmio;
> +} loongarch_extioi;
> +
> +#endif /* LOONGARCH_EXTIOI_H */


ATB,

Mark.


  reply	other threads:[~2021-12-18  0:52 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-04 12:06 [RFC PATCH v3 00/27] Add LoongArch softmmu support Xiaojuan Yang
2021-12-04 12:06 ` [RFC PATCH v3 01/27] target/loongarch: Update README Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 02/27] target/loongarch: Add CSR registers definition Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 03/27] target/loongarch: Add basic vmstate description of CPU Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 04/27] target/loongarch: Implement qmp_query_cpu_definitions() Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 05/27] target/loongarch: Add stabletimer support Xiaojuan Yang
2021-12-06  4:38   ` chen huacai
2021-12-07  7:04     ` maobibo
2021-12-04 12:07 ` [RFC PATCH v3 06/27] target/loongarch: Add MMU support for LoongArch CPU Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 07/27] target/loongarch: Add LoongArch CSR instruction Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 08/27] target/loongarch: Add LoongArch IOCSR instruction Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 09/27] target/loongarch: Add TLB instruction support Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 10/27] target/loongarch: Add other core instructions support Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 11/27] target/loongarch: Add LoongArch interrupt and exception handle Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 12/27] target/loongarch: Add timer related instructions support Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 13/27] target/loongarch: Add gdb support Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 14/27] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson3 Platform Xiaojuan Yang
2021-12-17 23:39   ` Mark Cave-Ayland
2021-12-20 11:42     ` yangxiaojuan
2021-12-04 12:07 ` [RFC PATCH v3 15/27] hw/loongarch: Add support loongson3-ls7a machine type Xiaojuan Yang
2021-12-06  4:36   ` chen huacai
2021-12-06  6:57     ` yangxiaojuan
2021-12-17 23:48   ` Mark Cave-Ayland
2021-12-04 12:07 ` [RFC PATCH v3 16/27] hw/loongarch: Add LoongArch cpu interrupt support(CPUINTC) Xiaojuan Yang
2021-12-17 23:54   ` Mark Cave-Ayland
2021-12-21  3:43     ` yangxiaojuan
2021-12-04 12:07 ` [RFC PATCH v3 17/27] hw/loongarch: Add LoongArch ipi interrupt support(IPI) Xiaojuan Yang
2021-12-18  0:09   ` Mark Cave-Ayland
2021-12-04 12:07 ` [RFC PATCH v3 18/27] hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC) Xiaojuan Yang
2021-12-18  0:33   ` Mark Cave-Ayland
2021-12-22  2:38     ` yangxiaojuan
2021-12-23 10:21       ` Mark Cave-Ayland
2022-01-08  9:44         ` yangxiaojuan
2021-12-04 12:07 ` [RFC PATCH v3 19/27] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI) Xiaojuan Yang
2021-12-18  0:36   ` Mark Cave-Ayland
2021-12-04 12:07 ` [RFC PATCH v3 20/27] hw/intc: Add LoongArch extioi interrupt controller(EIOINTC) Xiaojuan Yang
2021-12-18  0:50   ` Mark Cave-Ayland [this message]
2021-12-04 12:07 ` [RFC PATCH v3 21/27] hw/loongarch: Add irq hierarchy for the system Xiaojuan Yang
2021-12-18  9:45   ` Mark Cave-Ayland
2021-12-04 12:07 ` [RFC PATCH v3 22/27] hw/loongarch: Add some devices support for 3A5000 Xiaojuan Yang
2021-12-04 17:54   ` Philippe Mathieu-Daudé
2021-12-06  6:55     ` yangxiaojuan
2021-12-18 10:02   ` Mark Cave-Ayland
2021-12-22  8:26     ` yangxiaojuan
2021-12-23 10:52       ` Mark Cave-Ayland
2022-01-10  2:26         ` yangxiaojuan
2022-01-15 14:03           ` Mark Cave-Ayland
2022-01-12  9:37         ` maobibo
2022-01-15 14:05           ` Mark Cave-Ayland
2021-12-04 12:07 ` [RFC PATCH v3 23/27] hw/loongarch: Add LoongArch ls7a rtc device support Xiaojuan Yang
2021-12-18 10:10   ` Mark Cave-Ayland
2021-12-04 12:07 ` [RFC PATCH v3 24/27] hw/loongarch: Add default bios startup support Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 25/27] hw/loongarch: Add -kernel and -initrd options support Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 26/27] hw/loongarch: Add LoongArch smbios support Xiaojuan Yang
2021-12-04 12:07 ` [RFC PATCH v3 27/27] hw/loongarch: Add LoongArch acpi support Xiaojuan Yang
2021-12-13  3:13 ` [RFC PATCH v3 00/27] Add LoongArch softmmu support yangxiaojuan
2021-12-13 22:43   ` Mark Cave-Ayland
2021-12-14  1:08     ` yangxiaojuan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d639f689-cc25-ac4d-0d2a-760f64103101@ilande.co.uk \
    --to=mark.cave-ayland@ilande.co.uk \
    --cc=alex.bennee@linaro.org \
    --cc=alistair.francis@wdc.com \
    --cc=chenhuacai@loongson.cn \
    --cc=f4bug@amsat.org \
    --cc=gaosong@loongson.cn \
    --cc=i.qemu@xen0n.name \
    --cc=laurent@vivier.eu \
    --cc=maobibo@loongson.cn \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=peterx@redhat.com \
    --cc=philmd@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=thuth@redhat.com \
    --cc=yangxiaojuan@loongson.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.