All of lore.kernel.org
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@arm.com>
To: Andre Przywara <andre.przywara@linaro.org>,
	Stefano Stabellini <sstabellini@kernel.org>
Cc: xen-devel@lists.xenproject.org
Subject: Re: [PATCH v2 22/45] ARM: new VGIC: Add MMIO handling framework
Date: Mon, 19 Mar 2018 07:59:30 +0000	[thread overview]
Message-ID: <ae44742f-f52c-c1c2-e796-d2ae2a686872@arm.com> (raw)
In-Reply-To: <20180315203050.19791-23-andre.przywara@linaro.org>

Hi Andre,

On 03/15/2018 08:30 PM, Andre Przywara wrote:
> Add an MMIO handling framework to the VGIC emulation:
> Each register is described by its offset, size (or number of bits per
> IRQ, if applicable) and the read/write handler functions. We provide
> initialization macros to describe each GIC register later easily.
> 
> Separate dispatch functions for read and write accesses are connected
> to Xen's MMIO handling framework and binary-search for the responsible
> register handler based on the offset address within the region.
> 
> The register handler prototype are courtesy of Christoffer Dall.
> 
> This is based on Linux commit 4493b1c4866a, written by Marc Zyngier.
> 
> Signed-off-by: Andre Przywara <andre.przywara@linaro.org>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

> ---
> Changelog v1 ... v2:
> - adjust indentation
> - remove unneeded macros
> - use unsigned types
> - use new ilog2() implementation
> 
>   xen/arch/arm/vgic/vgic-mmio.c | 180 ++++++++++++++++++++++++++++++++++++++++++
>   xen/arch/arm/vgic/vgic-mmio.h |  89 +++++++++++++++++++++
>   2 files changed, 269 insertions(+)
>   create mode 100644 xen/arch/arm/vgic/vgic-mmio.c
>   create mode 100644 xen/arch/arm/vgic/vgic-mmio.h
> 
> diff --git a/xen/arch/arm/vgic/vgic-mmio.c b/xen/arch/arm/vgic/vgic-mmio.c
> new file mode 100644
> index 0000000000..866023a84d
> --- /dev/null
> +++ b/xen/arch/arm/vgic/vgic-mmio.c
> @@ -0,0 +1,180 @@
> +/*
> + * VGIC MMIO handling functions
> + * Imported from Linux ("new" KVM VGIC) and heavily adapted to Xen.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <xen/bitops.h>
> +#include <xen/lib.h>
> +#include <xen/sched.h>
> +#include <asm/new_vgic.h>
> +#include <asm/byteorder.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +unsigned long vgic_mmio_read_raz(struct vcpu *vcpu,
> +                                 paddr_t addr, unsigned int len)
> +{
> +    return 0;
> +}
> +
> +unsigned long vgic_mmio_read_rao(struct vcpu *vcpu,
> +                                 paddr_t addr, unsigned int len)
> +{
> +    return -1UL;
> +}
> +
> +void vgic_mmio_write_wi(struct vcpu *vcpu, paddr_t addr,
> +                        unsigned int len, unsigned long val)
> +{
> +    /* Ignore */
> +}
> +
> +static int match_region(const void *key, const void *elt)
> +{
> +    const unsigned int offset = (unsigned long)key;
> +    const struct vgic_register_region *region = elt;
> +
> +    if ( offset < region->reg_offset )
> +        return -1;
> +
> +    if ( offset >= region->reg_offset + region->len )
> +        return 1;
> +
> +    return 0;
> +}
> +
> +static const struct vgic_register_region *
> +vgic_find_mmio_region(const struct vgic_register_region *regions,
> +                      int nr_regions, unsigned int offset)
> +{
> +    return bsearch((void *)(uintptr_t)offset, regions, nr_regions,
> +                   sizeof(regions[0]), match_region);
> +}
> +
> +static bool check_region(const struct domain *d,
> +                         const struct vgic_register_region *region,
> +                         paddr_t addr, int len)
> +{
> +    unsigned int flags, nr_irqs = d->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> +
> +    switch ( len )
> +    {
> +    case sizeof(uint8_t):
> +        flags = VGIC_ACCESS_8bit;
> +        break;
> +    case sizeof(uint32_t):
> +        flags = VGIC_ACCESS_32bit;
> +        break;
> +    case sizeof(uint64_t):
> +        flags = VGIC_ACCESS_64bit;
> +        break;
> +    default:
> +        return false;
> +    }
> +
> +    if ( (region->access_flags & flags) && IS_ALIGNED(addr, len) )
> +    {
> +        if ( !region->bits_per_irq )
> +            return true;
> +
> +        /* Do we access a non-allocated IRQ? */
> +        return VGIC_ADDR_TO_INTID(addr, region->bits_per_irq) < nr_irqs;
> +    }
> +
> +    return false;
> +}
> +
> +static const struct vgic_register_region *
> +vgic_get_mmio_region(struct vcpu *vcpu, struct vgic_io_device *iodev,
> +                     paddr_t addr, unsigned int len)
> +{
> +    const struct vgic_register_region *region;
> +
> +    region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> +                                   addr - gfn_to_gaddr(iodev->base_fn));
> +    if ( !region || !check_region(vcpu->domain, region, addr, len) )
> +        return NULL;
> +
> +    return region;
> +}
> +
> +static int dispatch_mmio_read(struct vcpu *vcpu, mmio_info_t *info,
> +                              register_t *r, void *priv)
> +{
> +    struct vgic_io_device *iodev = priv;
> +    const struct vgic_register_region *region;
> +    unsigned long data = 0;
> +    paddr_t addr = info->gpa;
> +    int len = 1U << info->dabt.size;
> +
> +    region = vgic_get_mmio_region(vcpu, iodev, addr, len);
> +    if ( !region )
> +    {
> +        memset(r, 0, len);
> +        return 0;
> +    }
> +
> +    switch (iodev->iodev_type)
> +    {
> +    case IODEV_DIST:
> +        data = region->read(vcpu, addr, len);
> +        break;
> +    case IODEV_REDIST:
> +        data = region->read(iodev->redist_vcpu, addr, len);
> +        break;
> +    }
> +
> +    memcpy(r, &data, len);
> +
> +    return 1;
> +}
> +
> +static int dispatch_mmio_write(struct vcpu *vcpu, mmio_info_t *info,
> +                               register_t r, void *priv)
> +{
> +    struct vgic_io_device *iodev = priv;
> +    const struct vgic_register_region *region;
> +    unsigned long data = r;
> +    paddr_t addr = info->gpa;
> +    int len = 1U << info->dabt.size;
> +
> +    region = vgic_get_mmio_region(vcpu, iodev, addr, len);
> +    if ( !region )
> +        return 0;
> +
> +    switch (iodev->iodev_type)
> +    {
> +    case IODEV_DIST:
> +        region->write(vcpu, addr, len, data);
> +        break;
> +    case IODEV_REDIST:
> +        region->write(iodev->redist_vcpu, addr, len, data);
> +        break;
> +    }
> +
> +    return 1;
> +}
> +
> +struct mmio_handler_ops vgic_io_ops = {
> +    .read = dispatch_mmio_read,
> +    .write = dispatch_mmio_write,
> +};
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/vgic/vgic-mmio.h b/xen/arch/arm/vgic/vgic-mmio.h
> new file mode 100644
> index 0000000000..bf062a27ca
> --- /dev/null
> +++ b/xen/arch/arm/vgic/vgic-mmio.h
> @@ -0,0 +1,89 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __XEN_ARM_VGIC_VGIC_MMIO_H__
> +#define __XEN_ARM_VGIC_VGIC_MMIO_H__
> +
> +struct vgic_register_region {
> +    unsigned int reg_offset;
> +    unsigned int len;
> +    unsigned int bits_per_irq;
> +    unsigned int access_flags;
> +    unsigned long (*read)(struct vcpu *vcpu, paddr_t addr,
> +                          unsigned int len);
> +    void (*write)(struct vcpu *vcpu, paddr_t addr,
> +                  unsigned int len, unsigned long val);
> +};
> +
> +extern struct mmio_handler_ops vgic_io_ops;
> +
> +#define VGIC_ACCESS_8bit    1
> +#define VGIC_ACCESS_32bit   2
> +#define VGIC_ACCESS_64bit   4
> +
> +/*
> + * Generate a mask that covers the number of bytes required to address
> + * up to 1024 interrupts, each represented by <bits> bits. This assumes
> + * that <bits> is a power of two.
> + */
> +#define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1)
> +
> +/*
> + * (addr & mask) gives us the _byte_ offset for the INT ID.
> + * We multiply this by 8 the get the _bit_ offset, then divide this by
> + * the number of bits to learn the actual INT ID.
> + * But instead of a division (which requires a "long long div" implementation),
> + * we shift by the binary logarithm of <bits>.
> + * This assumes that <bits> is a power of two.
> + */
> +#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> +                                         8 >> ilog2(bits))
> +
> +/*
> + * Some VGIC registers store per-IRQ information, with a different number
> + * of bits per IRQ. For those registers this macro is used.
> + * The _WITH_LENGTH version instantiates registers with a fixed length
> + * and is mutually exclusive with the _PER_IRQ version.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)  \
> +    {                                                           \
> +        .reg_offset = off,                                      \
> +        .bits_per_irq = bpi,                                    \
> +        .len = bpi * 1024 / 8,                                  \
> +        .access_flags = acc,                                    \
> +        .read = rd,                                             \
> +        .write = wr,                                            \
> +    }
> +
> +#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)     \
> +    {                                                           \
> +        .reg_offset = off,                                      \
> +        .bits_per_irq = 0,                                      \
> +        .len = length,                                          \
> +        .access_flags = acc,                                    \
> +        .read = rd,                                             \
> +        .write = wr,                                            \
> +    }
> +
> +unsigned long vgic_mmio_read_raz(struct vcpu *vcpu,
> +                                 paddr_t addr, unsigned int len);
> +
> +unsigned long vgic_mmio_read_rao(struct vcpu *vcpu,
> +                                 paddr_t addr, unsigned int len);
> +
> +void vgic_mmio_write_wi(struct vcpu *vcpu, paddr_t addr,
> +                        unsigned int len, unsigned long val);
> +
> +#endif
> 

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  reply	other threads:[~2018-03-19  8:00 UTC|newest]

Thread overview: 106+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-15 20:30 [PATCH v2 00/45] New VGIC(-v2) implementation Andre Przywara
2018-03-15 20:30 ` [PATCH v2 01/45] ARM: VGIC: rename gic_event_needs_delivery() Andre Przywara
2018-03-16 10:58   ` Julien Grall
2018-03-16 21:21   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 02/45] ARM: Implement vcpu_kick() Andre Przywara
2018-03-16 10:59   ` Julien Grall
2018-03-16 21:23   ` Stefano Stabellini
2018-03-20 10:35   ` Jan Beulich
2018-03-21  4:10     ` Julien Grall
2018-03-21  7:40       ` Jan Beulich
2018-03-15 20:30 ` [PATCH v2 03/45] xen/arm: gic: Fix indentation in gic_update_one_lr Andre Przywara
2018-03-15 20:30 ` [PATCH v2 04/45] xen/arm: vgic: Override the group in lr everytime Andre Przywara
2018-03-16 21:25   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 05/45] xen/arm: gic: Use bool instead of uint8_t for the hw_status in gic_lr Andre Przywara
2018-03-16 21:25   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 06/45] xen/arm: gic: Split the field state in gic_lr in 2 fields active and pending Andre Przywara
2018-03-16 21:34   ` Stefano Stabellini
2018-03-16 22:14     ` Julien Grall
2018-03-16 22:52       ` Stefano Stabellini
2018-03-19  9:10         ` Andre Przywara
2018-03-15 20:30 ` [PATCH v2 07/45] xen/arm: GIC: Only set pirq in the LR when hw_status is set Andre Przywara
2018-03-16 21:38   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 08/45] ARM: GIC: extend LR read/write functions to cover EOI and source Andre Przywara
2018-03-16 21:43   ` Stefano Stabellini
2018-03-15 20:30 ` [PATCH v2 09/45] ARM: GIC: Allow tweaking the active and pending state of an IRQ Andre Przywara
2018-03-16 16:05   ` Andre Przywara
2018-03-19  9:30     ` Julien Grall
2018-03-19 17:54       ` Andre Przywara
2018-03-20  0:57         ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 10/45] ARM: GIC: Allow reading pending state of a hardware IRQ Andre Przywara
2018-03-19 10:04   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 11/45] ARM: timer: Handle level triggered IRQs correctly Andre Przywara
2018-03-19 10:07   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 12/45] ARM: evtchn: " Andre Przywara
2018-03-19 10:54   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 13/45] ARM: vPL011: Use the VGIC's level triggered IRQs handling if available Andre Przywara
2018-03-19 10:59   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 14/45] ARM: new VGIC: Add data structure definitions Andre Przywara
2018-03-19 11:01   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 15/45] ARM: new VGIC: Add acccessor to new struct vgic_irq instance Andre Przywara
2018-03-19 11:04   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 16/45] ARM: new VGIC: Implement virtual IRQ injection Andre Przywara
2018-03-19 12:48   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 17/45] Add list_sort() routine from Linux Andre Przywara
2018-03-16 10:47   ` Jan Beulich
2018-03-15 20:30 ` [PATCH v2 18/45] ARM: new VGIC: Add IRQ sorting Andre Przywara
2018-03-19 12:51   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 19/45] ARM: new VGIC: Add IRQ sync/flush framework Andre Przywara
2018-03-19 14:17   ` Julien Grall
2018-03-19 17:32     ` Andre Przywara
2018-03-15 20:30 ` [PATCH v2 20/45] ARM: new VGIC: Add GICv2 world switch backend Andre Przywara
2018-03-19 14:36   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 21/45] ARM: new VGIC: Implement vgic_vcpu_pending_irq Andre Przywara
2018-03-19  7:55   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 22/45] ARM: new VGIC: Add MMIO handling framework Andre Przywara
2018-03-19  7:59   ` Julien Grall [this message]
2018-03-15 20:30 ` [PATCH v2 23/45] ARM: new VGIC: Add GICv2 " Andre Przywara
2018-03-15 20:30 ` [PATCH v2 24/45] ARM: new VGIC: Add CTLR, TYPER and IIDR handlers Andre Przywara
2018-03-19  8:13   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 25/45] ARM: new VGIC: Add ENABLE registers handlers Andre Przywara
2018-03-19  8:22   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 26/45] ARM: new VGIC: Add PENDING " Andre Przywara
2018-03-19  8:25   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 27/45] ARM: new VGIC: Add ACTIVE " Andre Przywara
2018-03-19  8:27   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 28/45] ARM: new VGIC: Add PRIORITY " Andre Przywara
2018-03-19  9:40   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 29/45] ARM: new VGIC: Add CONFIG " Andre Przywara
2018-03-15 20:30 ` [PATCH v2 30/45] ARM: new VGIC: Add TARGET " Andre Przywara
2018-03-19  9:44   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 31/45] ARM: new VGIC: Add SGIR register handler Andre Przywara
2018-03-19  9:47   ` Julien Grall
2018-03-19 16:21     ` Andre Przywara
2018-03-15 20:30 ` [PATCH v2 32/45] ARM: new VGIC: Add SGIPENDR register handlers Andre Przywara
2018-03-15 20:30 ` [PATCH v2 33/45] ARM: new VGIC: Handle hardware mapped IRQs Andre Przywara
2018-03-15 20:30 ` [PATCH v2 34/45] ARM: new VGIC: Add event channel IRQ handling Andre Przywara
2018-03-15 20:30 ` [PATCH v2 35/45] ARM: new VGIC: Handle virtual IRQ allocation/reservation Andre Przywara
2018-03-15 20:30 ` [PATCH v2 36/45] ARM: new VGIC: Dump virtual IRQ info Andre Przywara
2018-03-15 20:30 ` [PATCH v2 37/45] ARM: new VGIC: Provide system register emulation stub Andre Przywara
2018-03-15 20:30 ` [PATCH v2 38/45] ARM: new VGIC: Implement arch_move_irqs() Andre Przywara
2018-03-19  9:53   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 39/45] ARM: new VGIC: Add preliminary stub implementation Andre Przywara
2018-03-19  9:54   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 40/45] ARM: new VGIC: vgic-init: register VGIC Andre Przywara
2018-03-20  1:17   ` Julien Grall
2018-03-20 17:11     ` Andre Przywara
2018-03-21  4:29       ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 41/45] ARM: new VGIC: Add vgic_v2_enable Andre Przywara
2018-03-19  9:57   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 42/45] ARM: new VGIC: vgic-init: implement vgic_init Andre Przywara
2018-03-20  3:02   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 43/45] ARM: new VGIC: vgic-init: implement map_resources Andre Przywara
2018-03-20  3:10   ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 44/45] ARM: new VGIC: Allocate two pages for struct vcpu Andre Przywara
2018-03-19 10:00   ` Julien Grall
2018-03-19 10:04     ` Julien Grall
2018-03-15 20:30 ` [PATCH v2 45/45] ARM: VGIC: wire new VGIC(-v2) files into Xen build system Andre Przywara
2018-03-16 10:48   ` Jan Beulich
2018-03-16 11:10     ` Andre Przywara
2018-03-16 11:32       ` Jan Beulich
2018-03-16 15:13         ` Andre Przywara
2018-03-16 15:34           ` Jan Beulich
2018-03-20  3:13   ` Julien Grall
2018-03-20 15:57     ` Andre Przywara
2018-03-20  8:30 ` [PATCH v2 00/45] New VGIC(-v2) implementation Julien Grall
2018-03-20 11:20   ` Andre Przywara

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=ae44742f-f52c-c1c2-e796-d2ae2a686872@arm.com \
    --to=julien.grall@arm.com \
    --cc=andre.przywara@linaro.org \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /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.