All of lore.kernel.org
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@arm.com>
To: Andre Przywara <andre.przywara@arm.com>,
	Stefano Stabellini <sstabellini@kernel.org>
Cc: xen-devel@lists.xenproject.org
Subject: Re: [PATCH v4 15/27] ARM: vITS: introduce translation table walks
Date: Tue, 4 Apr 2017 16:59:51 +0100	[thread overview]
Message-ID: <180ce30b-09c2-84fa-43a0-432a8989a9a0@arm.com> (raw)
In-Reply-To: <20170403202829.7278-16-andre.przywara@arm.com>

Hi Andre,

On 03/04/17 21:28, Andre Przywara wrote:
> The ITS stores the target (v)CPU and the (virtual) LPI number in tables.
> Introduce functions to walk those tables and translate an device ID -
> event ID pair into a pair of virtual LPI and vCPU.
> We map those tables on demand - which is cheap on arm64. Also we take
> care of the locking on the way, since we can't easily protect those ITTs
> from being altered by the guest.
>
> To allow compiling without warnings, we declare two functions as
> non-static for the moment, which two later patches will fix.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  xen/arch/arm/vgic-v3-its.c | 183 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 183 insertions(+)
>
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index fd3b9a1..fcfea3b 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -71,6 +71,189 @@ static bool its_is_enabled(struct virt_its *its)
>      return test_bit(VIRT_ITS_ENABLED, &its->flags);
>  }
>
> +#define UNMAPPED_COLLECTION      ((uint16_t)~0)
> +
> +/*
> + * The physical address is encoded slightly differently depending on
> + * the used page size: the highest four bits are stored in the lowest
> + * four bits of the field for 64K pages.
> + */
> +static paddr_t get_baser_phys_addr(uint64_t reg)
> +{
> +    if ( reg & BIT(9) )
> +        return (reg & GENMASK_ULL(47, 16)) |
> +                ((reg & GENMASK_ULL(15, 12)) << 36);
> +    else
> +        return reg & GENMASK_ULL(47, 12);
> +}
> +
> +/* Must be called with the ITS lock held. */

Again, this is a call for an ASSERT(...).

> +static struct vcpu *get_vcpu_from_collection(struct virt_its *its,
> +                                             uint16_t collid)
> +{
> +    paddr_t addr = get_baser_phys_addr(its->baser_coll);
> +    uint16_t *coll_table;
> +    uint16_t vcpu_id;
> +
> +    if ( collid >= its->max_collections )
> +        return NULL;
> +
> +    coll_table = map_one_guest_page(its->d, addr + collid * sizeof(uint16_t));
> +    if ( !coll_table )
> +        return NULL;
> +
> +    vcpu_id = *coll_table;
> +
> +    unmap_one_guest_page(coll_table);
> +
> +    if ( vcpu_id == UNMAPPED_COLLECTION || vcpu_id >= its->d->max_vcpus )
> +        return NULL;
> +
> +    return its->d->vcpu[vcpu_id];
> +}
> +
> +/*
> + * Our device table encodings:
> + * Contains the guest physical address of the Interrupt Translation Table in
> + * bits [51:8], and the size of it encoded in the lowest 8 bits.

The size is in term of bits, correct? If so, can you clarify in it in 
the comment?

> + */
> +#define DEV_TABLE_ITT_ADDR(x) ((x) & GENMASK_ULL(51, 8))
> +#define DEV_TABLE_ITT_SIZE(x) (BIT(((x) & GENMASK_ULL(7, 0)) + 1))
> +#define DEV_TABLE_ENTRY(addr, bits)                     \
> +        (((addr) & GENMASK_ULL(51, 8)) | (((bits) - 1) & GENMASK_ULL(7, 0)))
> +
> +/*
> + * Lookup the address of the Interrupt Translation Table associated with
> + * a device ID and return the address of the ITTE belonging to the event ID
> + * (which is an index into that table).
> + */
> +static paddr_t its_get_itte_address(struct virt_its *its,
> +                                    uint32_t devid, uint32_t evid)
> +{
> +    paddr_t ret, addr = get_baser_phys_addr(its->baser_dev);
> +    uint64_t *itt_ptr;
> +    uint64_t itt;

What is the plan for two-level page support for vITS?

> +
> +    if ( devid >= its->max_devices )
> +        return INVALID_PADDR;
> +
> +    itt_ptr = map_one_guest_page(its->d, addr + devid * sizeof(uint64_t));
> +    if ( !itt_ptr )
> +        return INVALID_PADDR;
> +
> +    itt = read_u64_atomic(itt_ptr);
> +
> +    if ( evid < DEV_TABLE_ITT_SIZE(itt) &&
> +         DEV_TABLE_ITT_ADDR(itt) != INVALID_PADDR )
> +        ret = DEV_TABLE_ITT_ADDR(itt) + evid * sizeof(struct vits_itte);
> +    else
> +        ret = INVALID_PADDR;
> +
> +    unmap_one_guest_page(itt_ptr);
> +
> +    return ret;
> +}
> +
> +/*
> + * Looks up a given deviceID/eventID pair on an ITS and returns a pointer to
> + * the corresponding ITTE. This maps the respective guest page into Xen.
> + * Once finished with handling the ITTE, call put_itte() to unmap
> + * the page again.
> + * Must be called with the ITS lock held.

This is a call for adding an ASSERT.

> + */
> +static struct vits_itte *get_itte(struct virt_its *its,
> +                                  uint32_t devid, uint32_t evid)
> +{
> +    paddr_t addr = its_get_itte_address(its, devid, evid);
> +
> +    if ( addr == INVALID_PADDR )
> +        return NULL;
> +
> +    return map_one_guest_page(its->d, addr);
> +}
> +
> +/* Must be called with the ITS lock held. */

Ditto.

> +static void put_itte(struct virt_its *its, struct vits_itte *itte)
> +{
> +    unmap_one_guest_page(itte);
> +}
> +
> +/*
> + * Queries the collection and device tables to get the vCPU and virtual
> + * LPI number for a given guest event. This takes care of mapping the
> + * respective tables and validating the values, since we can't efficiently
> + * protect the ITTs with their less-than-page-size granularity.
> + * This function takes care of the locking by taking the its_lock itself, so
> + * a caller shall not hold this. Upon returning, the lock is dropped again.
> + */
> +bool read_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
> +               struct vcpu **vcpu, uint32_t *vlpi)
> +{
> +    struct vits_itte *itte;
> +    uint16_t collid;
> +    uint32_t _vlpi;
> +    struct vcpu *_vcpu;
> +
> +    spin_lock(&its->its_lock);
> +    itte = get_itte(its, devid, evid);
> +    if ( !itte )
> +    {
> +        spin_unlock(&its->its_lock);
> +        return false;
> +    }
> +    collid = itte->collection;
> +    _vlpi = itte->vlpi;
> +    put_itte(its, itte);
> +
> +    _vcpu = get_vcpu_from_collection(its, collid);
> +    spin_unlock(&its->its_lock);
> +
> +    if ( !_vcpu )
> +        return false;
> +
> +    *vcpu = _vcpu;
> +    *vlpi = _vlpi;
> +
> +    return true;
> +}
> +
> +#define SKIP_LPI_UPDATE 1

Can you describe in which case you don't want to update the LPI?

> +/*
> + * This function takes care of the locking by taking the its_lock itself, so
> + * a caller shall not hold this. Upon returning, the lock is dropped again.
> + */
> +bool write_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
> +                uint32_t collid, uint32_t vlpi, struct vcpu **vcpu)
> +{
> +    struct vits_itte *itte;
> +
> +    if ( collid >= its->max_collections )
> +        return false;
> +
> +    if ( vlpi >= its->d->arch.vgic.nr_lpis )
> +        return false;
> +
> +    spin_lock(&its->its_lock);
> +    itte = get_itte(its, devid, evid);
> +    if ( !itte )
> +    {
> +        spin_unlock(&its->its_lock);
> +        return false;
> +    }
> +
> +    itte->collection = collid;
> +    if ( vlpi != SKIP_LPI_UPDATE )
> +        itte->vlpi = vlpi;
> +
> +    if ( vcpu )
> +        *vcpu = get_vcpu_from_collection(its, collid);
> +
> +    put_itte(its, itte);
> +    spin_unlock(&its->its_lock);
> +
> +    return true;
> +}
> +
>  /**************************************
>   * Functions that handle ITS commands *
>   **************************************/
>

Cheers,

-- 
Julien Grall

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

  reply	other threads:[~2017-04-04 15:59 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-03 20:28 [PATCH v4 00/27] arm64: Dom0 ITS emulation Andre Przywara
2017-04-03 20:28 ` [PATCH v4 01/27] ARM: GICv3 ITS: parse and store ITS subnodes from hardware DT Andre Przywara
2017-04-05  0:40   ` Stefano Stabellini
2017-04-03 20:28 ` [PATCH v4 02/27] ARM: GICv3 ITS: initialize host ITS Andre Przywara
2017-04-03 21:03   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 03/27] ARM: GICv3: allocate LPI pending and property table Andre Przywara
2017-04-03 21:47   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 04/27] ARM: GICv3 ITS: allocate device and collection table Andre Przywara
2017-04-05  0:56   ` Stefano Stabellini
2017-04-03 20:28 ` [PATCH v4 05/27] ARM: GICv3 ITS: map ITS command buffer Andre Przywara
2017-04-03 21:56   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 06/27] ARM: GICv3 ITS: introduce ITS command handling Andre Przywara
2017-04-03 22:39   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 07/27] ARM: GICv3 ITS: introduce host LPI array Andre Przywara
2017-04-03 23:07   ` Julien Grall
2017-04-04 10:40     ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 08/27] ARM: GICv3 ITS: introduce device mapping Andre Przywara
2017-04-04  9:03   ` Julien Grall
2017-04-04 16:13   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 09/27] ARM: GICv3: introduce separate pending_irq structs for LPIs Andre Przywara
2017-04-04 11:43   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 10/27] ARM: GICv3: forward pending LPIs to guests Andre Przywara
2017-04-04 11:55   ` Julien Grall
2017-04-04 15:36   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 11/27] ARM: GICv3: enable ITS and LPIs on the host Andre Przywara
2017-04-03 20:28 ` [PATCH v4 12/27] ARM: vGICv3: handle virtual LPI pending and property tables Andre Przywara
2017-04-04 13:01   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 13/27] ARM: vGICv3: Handle disabled LPIs Andre Przywara
2017-04-03 20:28 ` [PATCH v4 14/27] ARM: vGICv3: introduce basic ITS emulation bits Andre Przywara
2017-04-04 13:35   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 15/27] ARM: vITS: introduce translation table walks Andre Przywara
2017-04-04 15:59   ` Julien Grall [this message]
2017-04-03 20:28 ` [PATCH v4 16/27] ARM: vITS: handle CLEAR command Andre Przywara
2017-04-04 16:03   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 17/27] ARM: vITS: handle INT command Andre Przywara
2017-04-04 16:05   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 18/27] ARM: vITS: handle MAPC command Andre Przywara
2017-04-04 16:08   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 19/27] ARM: vITS: handle MAPD command Andre Przywara
2017-04-04 16:09   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 20/27] ARM: vITS: handle MAPTI command Andre Przywara
2017-04-04 16:22   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 21/27] ARM: vITS: handle MOVI command Andre Przywara
2017-04-04 16:37   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 22/27] ARM: vITS: handle DISCARD command Andre Przywara
2017-04-04 16:40   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 23/27] ARM: vITS: handle INV command Andre Przywara
2017-04-04 16:51   ` Julien Grall
2017-04-05 23:21     ` André Przywara
2017-04-03 20:28 ` [PATCH v4 24/27] ARM: vITS: handle INVALL command Andre Przywara
2017-04-04 17:00   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 25/27] ARM: vITS: create and initialize virtual ITSes for Dom0 Andre Przywara
2017-04-04 17:03   ` Julien Grall
2017-04-03 20:28 ` [PATCH v4 26/27] ARM: vITS: create ITS subnodes for Dom0 DT Andre Przywara
2017-04-03 20:28 ` [PATCH v4 27/27] ARM: vGIC: advertise LPI support Andre Przywara
2017-04-05 13:06   ` Julien Grall
2017-04-04 12:36 ` [PATCH v4 00/27] arm64: Dom0 ITS emulation Julien Grall

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=180ce30b-09c2-84fa-43a0-432a8989a9a0@arm.com \
    --to=julien.grall@arm.com \
    --cc=andre.przywara@arm.com \
    --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.