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: richard.henderson@linaro.org, gaosong@loongson.cn
Subject: Re: [PATCH v2 34/43] hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)
Date: Mon, 25 Apr 2022 17:27:13 +0100	[thread overview]
Message-ID: <6ca20e3d-9e1a-03e0-482d-2b989eb6dd73@ilande.co.uk> (raw)
In-Reply-To: <20220425091027.2877892-35-yangxiaojuan@loongson.cn>

On 25/04/2022 10:10, 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         | 483 +++++++++++++++++++++++++++++
>   hw/intc/meson.build                |   1 +
>   hw/intc/trace-events               |   9 +
>   hw/loongarch/Kconfig               |   1 +
>   include/hw/intc/loongarch_extioi.h |  60 ++++
>   6 files changed, 557 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 71c04c328e..28bd1f185d 100644
> --- a/hw/intc/Kconfig
> +++ b/hw/intc/Kconfig
> @@ -96,3 +96,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..1d9317c5bd
> --- /dev/null
> +++ b/hw/intc/loongarch_extioi.c
> @@ -0,0 +1,483 @@
> +/* 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/virt.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(LoongArchExtIOI *s, int irq_num, int level)
> +{
> +    uint64_t ipnum, cpu;
> +
> +    /*
> +     * Routing in group of 32 interrupts.
> +     * The default value of csr[0x420][49]
> +     * is 0 and nobody will change it,
> +     * so 'ipmap' use bitmap function.
> +     */
> +    ipnum = ldub_p((void *)&s->ipmap + (irq_num / 32)) & 0xf;
> +    ipnum = find_first_bit(&ipnum, 4);
> +    ipnum = (ipnum == 4) ? 0 : ipnum;
> +
> +    cpu = ldub_p((void *)s->coremap + irq_num) & 0xf;
> +    cpu = find_first_bit(&cpu, 4);
> +    cpu = (cpu == 4) ? 0 : cpu;
> +
> +    if (level) {
> +        if (test_bit(irq_num, (unsigned long *)s->enable) == false) {
> +            return;
> +        }
> +        bitmap_set((unsigned long *)s->coreisr[cpu], irq_num, 1);
> +        qemu_set_irq(s->parent_irq[cpu][ipnum], level);
> +    } else {
> +        bitmap_clear((unsigned long *)s->coreisr[cpu], irq_num, 1);
> +        qemu_set_irq(s->parent_irq[cpu][ipnum], level);
> +    }
> +}
> +
> +static void extioi_setirq(void *opaque, int irq, int level)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    trace_loongarch_extioi_setirq(irq, level);
> +    extioi_update_irq(s, irq, level);
> +}
> +
> +static uint32_t extioi_readb(void *opaque, hwaddr addr)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    uint8_t ret = 0;
> +    int cpu;
> +
> +    offset = addr & 0xffff;
> +    switch (offset) {
> +    case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
> +        ret = ldub_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
> +        break;
> +    case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
> +        ret = ldub_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
> +        break;
> +    case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +        ret = ldub_p((void *)s->coreisr[cpu] + reg_count);
> +        break;
> +    case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
> +        ret = ldub_p((void *)&s->ipmap + (offset - EXTIOI_IPMAP_START));
> +        break;
> +    case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
> +        ret = ldub_p((void *)s->coremap + (offset - EXTIOI_COREMAP_START));
> +        break;
> +    case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
> +        ret = ldub_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START));
> +        break;
> +    default:
> +        break;
> +    }
> +    trace_loongarch_extioi_readb((uint32_t)addr, ret);
> +    return ret;
> +}
> +
> +static uint32_t extioi_readw(void *opaque, hwaddr addr)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    uint32_t ret = 0;
> +    int cpu;
> +
> +    offset = addr & 0xffff;
> +    switch (offset) {
> +    case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
> +        ret = ldl_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
> +        break;
> +    case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
> +        ret = ldl_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
> +        break;
> +    case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +        ret = ldl_p((void *)s->coreisr[cpu] + reg_count);
> +        break;
> +    case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
> +        ret = ldl_p((void *)&s->ipmap + (offset - EXTIOI_IPMAP_START));
> +        break;
> +    case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
> +        ret = ldl_p((void *)s->coremap + (offset - EXTIOI_COREMAP_START));
> +        break;
> +    case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
> +        ret = ldl_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START));
> +        break;
> +    default:
> +        break;
> +    }
> +    trace_loongarch_extioi_readw((uint32_t)addr, ret);
> +    return ret;
> +}
> +
> +static uint64_t extioi_readl(void *opaque, hwaddr addr)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    uint64_t ret = 0;
> +    int cpu;
> +
> +    offset = addr & 0xffff;
> +
> +    switch (offset) {
> +    case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
> +        ret = ldq_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
> +        break;
> +    case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
> +        ret = ldq_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
> +        break;
> +    case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
> +        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
> +        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
> +        ret = ldq_p((void *)s->coreisr[cpu] + reg_count);
> +        break;
> +    case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
> +        ret = ldq_p((void *)&s->ipmap + (offset - EXTIOI_IPMAP_START));
> +        break;
> +    case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
> +        ret = ldq_p((void *)s->coremap + (offset - EXTIOI_COREMAP_START));
> +        break;
> +    case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
> +        ret = ldq_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START));
> +        break;
> +    default:
> +        break;
> +    }
> +    trace_loongarch_extioi_readl((uint32_t)addr, ret);
> +    return ret;
> +}
> +
> +static void extioi_writeb(void *opaque, hwaddr addr, uint32_t value,
> +                          unsigned size)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    unsigned long offset, reg_count;
> +    int cpu, i, j, level, bits;
> +    uint64_t old_data, val = value & 0xff;
> +
> +    offset = addr & 0xffff;
> +
> +    trace_loongarch_extioi_writeb(size, (uint32_t)addr, (uint8_t)val);
> +    switch (offset) {
> +    case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
> +        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, (uint8_t)val);
> +            old_data = old_data ^ val;
> +            bits = size * 8;
> +            while ((i = find_first_bit(&old_data, bits)) != bits) {
> +                level = test_bit(i, &val);
> +                extioi_update_irq(s, i + reg_count * 8, level);
> +                clear_bit(i, &old_data);
> +            }
> +        }
> +        break;
> +    case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
> +        stb_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START), (uint8_t)val);
> +        break;
> +    case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
> +        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, (uint8_t)(old_data & ~val));
> +
> +        if (old_data != (old_data & ~val)) {
> +            bits = size * 8;
> +
> +            while ((i = find_first_bit(&val, bits)) != bits) {
> +                j = test_bit(i, &old_data);
> +                if (j) {
> +                    extioi_update_irq(s, i + reg_count * 8, 0);
> +                }
> +                clear_bit(i, &val);
> +            }
> +        }
> +        break;
> +    case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
> +        /* Drop arch.core_ip_mask use s->ipmap */
> +        reg_count = (offset - EXTIOI_IPMAP_START);
> +        stb_p((void *)&s->ipmap + reg_count, (uint8_t)val);
> +        break;
> +    case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
> +        reg_count = (offset - EXTIOI_COREMAP_START);
> +
> +        /* Only map the core */
> +        while (val) {
> +            stb_p((void *)s->coremap + reg_count, (uint8_t)val);
> +            val = val >> 8;
> +        }
> +        break;
> +    case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
> +        stb_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START),
> +                                     (uint8_t)val);
> +        break;
> +    default:
> +        break;
> +    }
> +}
> +
> +static void extioi_writew(void *opaque, hwaddr addr, uint32_t val,
> +                          unsigned size)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    int cpu, level;
> +    uint32_t offset, reg_count, i, j, bits;
> +    uint64_t old_data, value = val;
> +    offset = addr & 0xffff;
> +    trace_loongarch_extioi_writew(size, (uint32_t)addr, val);
> +
> +    switch (offset) {
> +    case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
> +        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(&old_data, bits)) != bits) {
> +                level = test_bit(i, &value);
> +                extioi_update_irq(s, i + reg_count * 8, level);
> +                clear_bit(i, &old_data);
> +            }
> +        }
> +        break;
> +    case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
> +        stl_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START), val);
> +        break;
> +    case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
> +        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(&value, bits)) != bits) {
> +                j = test_bit(i, &old_data);
> +                if (j) {
> +                    extioi_update_irq(s, i + reg_count * 8, 0);
> +                }
> +                clear_bit(i, &value);
> +            }
> +        }
> +        break;
> +    case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
> +        /* Drop arch.core_ip_mask use s->ipmap */
> +        reg_count = (offset - EXTIOI_IPMAP_START);
> +        stl_p((void *)&s->ipmap + reg_count, val);
> +        break;
> +    case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
> +        reg_count = (offset - EXTIOI_COREMAP_START);
> +        /* Only map the core */
> +        while (val) {
> +            stl_p((void *)s->coremap + reg_count, val);
> +            val = val >> 8;
> +        }
> +        break;
> +    case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
> +        stl_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START), val);
> +        break;
> +    default:
> +        break;
> +    }
> +}
> +
> +static void extioi_writel(void *opaque, hwaddr addr, uint64_t val,
> +                          unsigned size)
> +{
> +    LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
> +    int cpu, level, i, j, bits;
> +    uint64_t offset, old_data, reg_count;
> +
> +    offset = addr & 0xffff;
> +    trace_loongarch_extioi_writel(size, (uint32_t)addr, val);
> +    switch (offset) {
> +    case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
> +        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(&old_data, bits)) != bits) {
> +                level = test_bit(i, &val);
> +                extioi_update_irq(s, i + reg_count * 8, level);
> +                clear_bit(i, &old_data);
> +            }
> +        }
> +        break;
> +    case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
> +        stq_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START), val);
> +        break;
> +    case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
> +        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(&val, bits)) != bits) {
> +                j = test_bit(i, &old_data);
> +                if (j) {
> +                    extioi_update_irq(s, i + reg_count * 8, 0);
> +                }
> +                clear_bit(i, &val);
> +            }
> +        }
> +        break;
> +    case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
> +        /* Drop arch.core_ip_mask use s->ipmap */
> +        reg_count = (offset - EXTIOI_IPMAP_START);
> +        stq_p((void *)&s->ipmap + reg_count, val);
> +        break;
> +    case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
> +        reg_count = (offset - EXTIOI_COREMAP_START);
> +        /* Only map the core */
> +        while (val) {
> +            stq_p((void *)s->coremap + reg_count, val);
> +            val = val >> 8;
> +        }
> +        break;
> +    case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
> +        stq_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START), val);
> +        break;
> +    default:
> +        break;
> +    }
> +}
> +
> +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,
> +};

I think you may have misunderstood what Richard was saying about using a single 
memory region - it seems to me you have gone back to using the original approach with 
multiple access functions for different sizes, which almost certainly isn't correct 
for modern hardware.

Going back to the previous revision of this patch, the question to ask is: do you 
really need byte-level access using extioi_ipmap_enable_ops and extioi_coremap_ops? 
Given that all the other register accesses appear to be 32-bit it seems odd that just 
these 2 sets of registers require 8-bit accesses. The register access size should be 
clearly stated in the EIOINTC documentaion.

My suspicion would be that is possible to update extioi_ipmap_enable_ops and 
extioi_coremap_ops from the previous version of this patch to use the same access 
sizes as all the other registers i.e.

     .impl.min_access_size = 4,
     .impl.max_access_size = 4,
     .valid.min_access_size = 4,
     .valid.max_access_size = 8,

Once you have got this working then recalculating the address offsets and collapsing 
everything into a single memory region as suggested by Richard becomes trivial. I 
should also add that if for whatever reason this isn't possible, the previous version 
of the patch is the correct way to handle this, and this should be clearly documented 
as a reply in this thread along with a suitable reference to relevant part of the 
EIOINTC documentation.

> +static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
> +{
> +    LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
> +    MachineState *ms = MACHINE(lams);
> +    LoongArchExtIOI *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]);
> +    }
> +    /* two ways to access extioi: iocsr memory and system memory */
> +    memory_region_init_io(&p->extioi_iocsr_mem, OBJECT(p), &extioi_ops, p,
> +                          "loongarch_extioi_iocsr", 0x900);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &p->extioi_iocsr_mem);
> +
> +    memory_region_init_io(&p->extioi_system_mem, OBJECT(p), &extioi_ops, p,
> +                          "loongarch_extioi", 0x900);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &p->extioi_system_mem);
> +
> +    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_loongarch_extioi = {
> +    .name = TYPE_LOONGARCH_EXTIOI,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64_ARRAY(enable, LoongArchExtIOI,
> +                             EXTIOI_IRQS_BITMAP_SIZE / 8),
> +        VMSTATE_UINT64_ARRAY(bounce, LoongArchExtIOI,
> +                             EXTIOI_IRQS_BITMAP_SIZE / 8),
> +        VMSTATE_UINT64_2DARRAY(coreisr, LoongArchExtIOI,
> +                               MAX_CORES, EXTIOI_IRQS_BITMAP_SIZE / 8),
> +        VMSTATE_UINT64(ipmap, LoongArchExtIOI),
> +        VMSTATE_UINT64_ARRAY(coremap, LoongArchExtIOI,
> +                             EXTIOI_IRQS_COREMAP_SIZE / 8),
> +        VMSTATE_UINT64_ARRAY(nodetype, LoongArchExtIOI,
> +                             EXTIOI_IRQS_NODETYPE_SIZE / 4),
> +        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,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(struct LoongArchExtIOI),
> +    .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 77a30cec33..405e18f4bb 100644
> --- a/hw/intc/meson.build
> +++ b/hw/intc/meson.build
> @@ -65,3 +65,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 8bcc1b6992..285d64ab83 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -303,3 +303,12 @@ loongarch_pch_pic_writeb(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
> +loongarch_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 d814fc6103..f779087416 100644
> --- a/hw/loongarch/Kconfig
> +++ b/hw/loongarch/Kconfig
> @@ -5,3 +5,4 @@ config LOONGARCH_VIRT
>       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..5482483a5f
> --- /dev/null
> +++ b/include/hw/intc/loongarch_extioi.h
> @@ -0,0 +1,60 @@
> +/* 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/virt.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 EXTIOI_SYSTEM_MEM            0x1fe01400
> +#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi"
> +OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
> +struct 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];
> +
> +    qemu_irq parent_irq[MAX_CORES][LS3A_INTC_IP];
> +    qemu_irq irq[EXTIOI_IRQS];
> +    MemoryRegion extioi_iocsr_mem;
> +    MemoryRegion extioi_system_mem;
> +};
> +
> +#endif /* LOONGARCH_EXTIOI_H */


ATB,

Mark.


  reply	other threads:[~2022-04-25 16:29 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-25  9:09 [PATCH v2 00/43] Add LoongArch softmmu support Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 01/43] target/loongarch: Add README Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 02/43] target/loongarch: Add core definition Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 03/43] target/loongarch: Add main translation routines Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 04/43] target/loongarch: Add fixed point arithmetic instruction translation Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 05/43] target/loongarch: Add fixed point shift " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 06/43] target/loongarch: Add fixed point bit " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 07/43] target/loongarch: Add fixed point load/store " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 08/43] target/loongarch: Add fixed point atomic " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 09/43] target/loongarch: Add fixed point extra " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 10/43] target/loongarch: Add floating point arithmetic " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 11/43] target/loongarch: Add floating point comparison " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 12/43] target/loongarch: Add floating point conversion " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 13/43] target/loongarch: Add floating point move " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 14/43] target/loongarch: Add floating point load/store " Xiaojuan Yang
2022-04-25  9:09 ` [PATCH v2 15/43] target/loongarch: Add branch " Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 16/43] target/loongarch: Add disassembler Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 17/43] target/loongarch: Add target build suport Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 18/43] target/loongarch: Add system emulation introduction Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 19/43] target/loongarch: Add CSRs definition Xiaojuan Yang
2022-04-25 22:36   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 20/43] target/loongarch: Add basic vmstate description of CPU Xiaojuan Yang
2022-04-25 22:46   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 21/43] target/loongarch: Implement qmp_query_cpu_definitions() Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 22/43] target/loongarch: Add MMU support for LoongArch CPU Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 23/43] target/loongarch: Add LoongArch interrupt and exception handle Xiaojuan Yang
2022-04-25 22:30   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 24/43] target/loongarch: Add constant timer support Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 25/43] target/loongarch: Add LoongArch CSR instruction Xiaojuan Yang
2022-04-25 22:55   ` Richard Henderson
2022-04-26  9:03     ` yangxiaojuan
2022-04-26 14:52       ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 26/43] target/loongarch: Add LoongArch IOCSR instruction Xiaojuan Yang
2022-04-27  1:37   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 27/43] target/loongarch: Add TLB instruction support Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 28/43] target/loongarch: Add other core instructions support Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 29/43] target/loongarch: Add timer related " Xiaojuan Yang
2022-04-26  0:06   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 30/43] hw/loongarch: Add support loongson3 virt machine type Xiaojuan Yang
2022-04-27  1:43   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 31/43] hw/loongarch: Add LoongArch ipi interrupt support(IPI) Xiaojuan Yang
2022-04-27  1:49   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 32/43] hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC) Xiaojuan Yang
2022-04-28  8:15   ` Mark Cave-Ayland
2022-04-25  9:10 ` [PATCH v2 33/43] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI) Xiaojuan Yang
2022-04-27  2:01   ` Richard Henderson
2022-04-28  7:40     ` Mark Cave-Ayland
2022-04-28  8:16   ` Mark Cave-Ayland
2022-04-25  9:10 ` [PATCH v2 34/43] hw/intc: Add LoongArch extioi interrupt controller(EIOINTC) Xiaojuan Yang
2022-04-25 16:27   ` Mark Cave-Ayland [this message]
2022-04-27 10:02     ` yangxiaojuan
2022-04-27  2:07   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 35/43] hw/loongarch: Add irq hierarchy for the system Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 36/43] Enable common virtio pci support for LoongArch Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 37/43] hw/loongarch: Add some devices support for 3A5000 Xiaojuan Yang
2022-04-27  2:21   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 38/43] hw/loongarch: Add LoongArch ls7a rtc device support Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 39/43] hw/loongarch: Add LoongArch load elf function Xiaojuan Yang
2022-04-27  2:23   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 40/43] hw/loongarch: Add LoongArch ls7a acpi device support Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 41/43] target/loongarch: Add gdb support Xiaojuan Yang
2022-04-27  2:24   ` Richard Henderson
2022-04-25  9:10 ` [PATCH v2 42/43] tests/tcg/loongarch64: Add hello/memory test in loongarch64 system Xiaojuan Yang
2022-04-25  9:10 ` [PATCH v2 43/43] target/loongarch: 'make check-tcg' support Xiaojuan Yang

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=6ca20e3d-9e1a-03e0-482d-2b989eb6dd73@ilande.co.uk \
    --to=mark.cave-ayland@ilande.co.uk \
    --cc=gaosong@loongson.cn \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --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.