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,
	Shanker Donthineni <shankerd@codeaurora.org>,
	Vijay Kilari <vijay.kilari@gmail.com>
Subject: Re: [PATCH v3 11/26] ARM: vGICv3: handle virtual LPI pending and property tables
Date: Tue, 4 Apr 2017 13:56:54 +0100	[thread overview]
Message-ID: <0d92de72-9f52-39c5-be30-db1289b6c16b@arm.com> (raw)
In-Reply-To: <bbd2e755-7b97-c7fd-2b90-6efbe088e30b@arm.com>

Hmmm I posted the comment on v3, rather than v4 :/. I will duplicate 
them on v4 for convenience.

Cheers,

On 04/04/17 13:55, Julien Grall wrote:
> Hi Andre,
>
> On 31/03/17 19:05, Andre Przywara wrote:
>> Allow a guest to provide the address and size for the memory regions
>> it has reserved for the GICv3 pending and property tables.
>> We sanitise the various fields of the respective redistributor
>> registers and map those pages into Xen's address space to have easy
>> access.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>>  xen/arch/arm/vgic-v3.c       | 136
>> +++++++++++++++++++++++++++++++++++++------
>>  xen/common/memory.c          |  61 +++++++++++++++++++
>>  xen/include/asm-arm/domain.h |   6 +-
>>  xen/include/asm-arm/vgic.h   |   2 +
>>  xen/include/xen/mm.h         |   8 +++
>>  5 files changed, 195 insertions(+), 18 deletions(-)
>>
>> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
>> index 69572e3..7f84fbf 100644
>> --- a/xen/arch/arm/vgic-v3.c
>> +++ b/xen/arch/arm/vgic-v3.c
>> @@ -20,12 +20,14 @@
>>
>>  #include <xen/bitops.h>
>>  #include <xen/config.h>
>> +#include <xen/domain_page.h>
>>  #include <xen/lib.h>
>>  #include <xen/init.h>
>>  #include <xen/softirq.h>
>>  #include <xen/irq.h>
>>  #include <xen/sched.h>
>>  #include <xen/sizes.h>
>> +#include <xen/vmap.h>
>>  #include <asm/current.h>
>>  #include <asm/mmio.h>
>>  #include <asm/gic_v3_defs.h>
>> @@ -229,12 +231,15 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct
>> vcpu *v, mmio_info_t *info,
>>          goto read_reserved;
>>
>>      case VREG64(GICR_PROPBASER):
>> -        /* LPI's not implemented */
>> -        goto read_as_zero_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +        *r = vgic_reg64_extract(v->domain->arch.vgic.rdist_propbase,
>> info);
>
> vgic_reg64_extract will likely turned into a series of non-atomic
> operation. So how do you prevent issue?
>
>> +        return 1;
>>
>>      case VREG64(GICR_PENDBASER):
>> -        /* LPI's not implemented */
>> -        goto read_as_zero_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +        *r = vgic_reg64_extract(v->arch.vgic.rdist_pendbase, info);
>
> Ditto.
>
>> +        *r &= ~GICR_PENDBASER_PTZ;       /* WO, reads as 0 */
>> +        return 1;
>
> [...]
>
>>  static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t
>> *info,
>>                                            uint32_t gicr_reg,
>>                                            register_t r)
>>  {
>>      struct hsr_dabt dabt = info->dabt;
>> +    uint64_t reg;
>>
>>      switch ( gicr_reg )
>>      {
>> @@ -394,36 +478,54 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct
>> vcpu *v, mmio_info_t *info,
>>          goto write_impl_defined;
>>
>>      case VREG64(GICR_SETLPIR):
>> -        /* LPI is not implemented */
>> +        /* LPIs without an ITS are not implemented */
>>          goto write_ignore_64;
>>
>>      case VREG64(GICR_CLRLPIR):
>> -        /* LPI is not implemented */
>> +        /* LPIs without an ITS are not implemented */
>>          goto write_ignore_64;
>>
>>      case 0x0050:
>>          goto write_reserved;
>>
>>      case VREG64(GICR_PROPBASER):
>> -        /* LPI is not implemented */
>> -        goto write_ignore_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +
>> +        /* Writing PROPBASER with LPIs enabled is UNPREDICTABLE. */
>> +        if ( v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
>
> v will point to the vCPU associated to the re-distributor. However, this
> could be updated from any vCPU. So I think there is tiny race where
> v->arch.vgic.flags may not been seen and therefore you will
>
>> +            return 1;
>> +
>> +        reg = v->domain->arch.vgic.rdist_propbase;
>> +        vgic_reg64_update(&reg, r, info);
>> +        reg = sanitize_propbaser(reg);
>> +        v->domain->arch.vgic.rdist_propbase = reg;
>
> This code could be called concurrently and I don't think this will
> behave well.
>
>> +        return 1;
>>
>>      case VREG64(GICR_PENDBASER):
>> -        /* LPI is not implemented */
>> -        goto write_ignore_64;
>> +        if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
>> +
>> +        /* Writing PENDBASER with LPIs enabled is UNPREDICTABLE. */
>> +        if ( v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
>
> Ditto
>
>> +            return 1;
>> +
>> +        reg = v->arch.vgic.rdist_pendbase;
>> +        vgic_reg64_update(&reg, r, info);
>> +        reg = sanitize_pendbaser(reg);
>> +        v->arch.vgic.rdist_pendbase = reg;
>
> Ditto.
>
>
>> +        return 1;
>
> [...]
>
>> diff --git a/xen/common/memory.c b/xen/common/memory.c
>> index 21797ca..29ef9bb 100644
>> --- a/xen/common/memory.c
>> +++ b/xen/common/memory.c
>
> Any modification in common code should be a separate patch and have
> appropriate maintainers CCed.
>
>> @@ -1419,6 +1419,67 @@ int prepare_ring_for_helper(
>>  }
>>
>>  /*
>> + * Mark a given number of guest pages as used (by increasing their
>> refcount),
>> + * starting with the given guest address. This needs to be called
>> once before
>> + * calling (possibly repeatedly) map_one_guest_pages().
>> + * Before the domain gets destroyed, call put_guest_pages() to drop the
>> + * reference.
>> + */
>
> I was hoping that you would have taken my comments into account where
> you wrote the new functions but it seems they were ignored :/. I feel
> like it is a wasted of my time to repeat again and again comments.
>
> Both get_guest_pages and put_guest_pages are wrong because you are
> assuming the p2m mapping will never changes. This is wrong and I asked a
> forward plan for that which seems to have been skipped too...
>
>> +int get_guest_pages(struct domain *d, paddr_t gpa, unsigned int
>> nr_pages)
>
> Many comments here:
>    * please use the type gfn_t rather paddr_t,
>
>> +{
>> +    unsigned int i;
>> +    struct page_info *page;
>> +
>> +    for ( i = 0; i < nr_pages; i++ )
>> +    {
>> +        page = get_page_from_gfn(d, (gpa >> PAGE_SHIFT) + i, NULL,
>> P2M_ALLOC);
>
> Get page may return a foreign page (e.g belonging to another domain) and
> we don't want to use this type of page for ITS memory.
>
>> +        if ( !page )
>> +        {
>> +            /* Make sure we drop the references of pages we got so
>> far. */
>> +            put_guest_pages(d, gpa, i);
>> +            return -EINVAL;
>> +        }
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +void put_guest_pages(struct domain *d, paddr_t gpa, unsigned int
>> nr_pages)
>
> Same comments as above.
>
>> +{
>> +    mfn_t mfn;
>> +    int i;
>> +
>> +    p2m_read_lock(&d->arch.p2m);
>> +    for ( i = 0; i < nr_pages; i++ )
>> +    {
>> +        mfn = p2m_get_entry(&d->arch.p2m, _gfn((gpa >> PAGE_SHIFT) + i),
>> +                            NULL, NULL, NULL);
>> +        if ( mfn_eq(mfn, INVALID_MFN) )
>> +            continue;
>> +        put_page(mfn_to_page(mfn_x(mfn)));
>
> This function is completely wrong in the actual state. You assume that
> the stage-2 page table has not been modified by the guest between
> get_guest_pages and put_guest_pages. If it has been modified, you may
> remove a reference on the wrong page.
>
> Furthermore, it is likely an error to have the mfn not valid in this case.
>
> As we discussed earlier, the way forward is to protect the pages. It is
> not mandatory for DOM0, but a comment in the code is necessary to
> explain what is missing.
>
>> +    }
>> +    p2m_read_unlock(&d->arch.p2m);
>> +}
>> +
>> +/*
>> + * Provides easy access to guest memory by "mapping" one page of it into
>> + * Xen's VA space. In fact it relies on the memory being already mapped
>> + * and just provides a pointer to it.
>> + */
>> +void *map_one_guest_page(struct domain *d, paddr_t guest_addr)
>> +{
>> +    void *ptr = map_domain_page(_mfn(guest_addr >> PAGE_SHIFT));
>
> This might be correct for DOM0 but will not work for guest. Even if you
> don't support guest right now, we should really avoid such assumption in
> the code. It will likely mean quite a lot of rework which I'd like to
> see now.
>
> Looking at how you use this, it would make more sense to have an helper
> to copy from the guest memory to a buffer. I think this is not the first
> time I am suggesting that.
>
> I think this would also avoid protecting the guest memory.
>
> For an example of what I meant give a look to the vITS series sent by
> Cavium a year ago:
>
> https://patchwork.kernel.org/patch/8177251/
>
>> +
>> +    return ptr + (guest_addr & ~PAGE_MASK);
>> +}
>> +
>> +/* "Unmap" a previously mapped guest page. Could be optimized away. */
>> +void unmap_one_guest_page(void *va)
>> +{
>> +    unmap_domain_page(((uintptr_t)va & PAGE_MASK));
>> +}
>> +
>> +/*
>>   * Local variables:
>>   * mode: C
>>   * c-file-style: "BSD"
>> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
>> index a83904a..ad4dfdc 100644
>> --- a/xen/include/asm-arm/domain.h
>> +++ b/xen/include/asm-arm/domain.h
>> @@ -110,6 +110,8 @@ struct arch_domain
>>          } *rdist_regions;
>>          int nr_regions;                     /* Number of rdist
>> regions */
>>          uint32_t rdist_stride;              /* Re-Distributor stride */
>> +        unsigned int nr_lpis;
>
> You switched to "unsigned long" in the gic-v3-its code, but still keep
> "unsigned int" here.
>
> Why that?
>
> [...]
>
>> diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
>> index eabdf91..9f48e9a 100644
>> --- a/xen/include/asm-arm/vgic.h
>> +++ b/xen/include/asm-arm/vgic.h
>> @@ -310,6 +310,8 @@ extern void register_vgic_ops(struct domain *d,
>> const struct vgic_ops *ops);
>>  int vgic_v2_init(struct domain *d, int *mmio_count);
>>  int vgic_v3_init(struct domain *d, int *mmio_count);
>>
>> +extern int vgic_lpi_get_priority(struct domain *d, uint32_t vlpi);
>
> Prototype should be added in the same patch as the declaration. So
> please move to patch #10.
>
> Cheers,
>

-- 
Julien Grall

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

  reply	other threads:[~2017-04-04 12:56 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-31 18:04 [PATCH v3 00/26] arm64: Dom0 ITS emulation Andre Przywara
2017-03-31 18:05 ` [PATCH v3 01/26] ARM: GICv3 ITS: parse and store ITS subnodes from hardware DT Andre Przywara
2017-03-31 23:08   ` Stefano Stabellini
2017-03-31 18:05 ` [PATCH v3 02/26] ARM: GICv3: allocate LPI pending and property table Andre Przywara
2017-03-31 22:59   ` Stefano Stabellini
2017-04-03  9:05     ` Andre Przywara
2017-04-03 18:16       ` Stefano Stabellini
2017-04-03 13:53   ` Julien Grall
2017-04-03 14:01     ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 03/26] ARM: GICv3 ITS: allocate device and collection table Andre Przywara
2017-03-31 23:06   ` Stefano Stabellini
2017-04-03 15:38   ` Julien Grall
2017-04-03 17:22     ` Julien Grall
2017-04-03 19:39       ` Andre Przywara
2017-04-03 20:46         ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 04/26] ARM: GICv3 ITS: map ITS command buffer Andre Przywara
2017-03-31 23:10   ` Stefano Stabellini
2017-04-03 16:00   ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 05/26] ARM: GICv3 ITS: introduce ITS command handling Andre Przywara
2017-03-31 23:16   ` Stefano Stabellini
2017-04-03 17:32   ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 06/26] ARM: GICv3 ITS: introduce device mapping Andre Przywara
2017-03-31 23:20   ` Stefano Stabellini
2017-04-01  8:01   ` Vijay Kilari
2017-04-03 18:33     ` Julien Grall
2017-04-03 18:56   ` Julien Grall
2017-03-31 18:05 ` [PATCH v3 07/26] ARM: GICv3 ITS: introduce host LPI array Andre Przywara
2017-03-31 23:24   ` Stefano Stabellini
2017-03-31 18:05 ` [PATCH v3 08/26] ARM: GICv3: introduce separate pending_irq structs for LPIs Andre Przywara
2017-03-31 18:05 ` [PATCH v3 09/26] ARM: GICv3: forward pending LPIs to guests Andre Przywara
2017-03-31 18:05 ` [PATCH v3 10/26] ARM: GICv3: enable ITS and LPIs on the host Andre Przywara
2017-03-31 18:05 ` [PATCH v3 11/26] ARM: vGICv3: handle virtual LPI pending and property tables Andre Przywara
2017-04-04 12:55   ` Julien Grall
2017-04-04 12:56     ` Julien Grall [this message]
2017-03-31 18:05 ` [PATCH v3 12/26] ARM: vGICv3: Handle disabled LPIs Andre Przywara
2017-03-31 18:05 ` [PATCH v3 13/26] ARM: vGICv3: introduce basic ITS emulation bits Andre Przywara
2017-03-31 18:05 ` [PATCH v3 14/26] ARM: vITS: introduce translation table walks Andre Przywara
2017-03-31 18:05 ` [PATCH v3 15/26] ARM: vITS: handle CLEAR command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 16/26] ARM: vITS: handle INT command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 17/26] ARM: vITS: handle MAPC command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 18/26] ARM: vITS: handle MAPD command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 19/26] ARM: vITS: handle MAPTI command Andre Przywara
2017-04-01  8:32   ` Vijay Kilari
2017-03-31 18:05 ` [PATCH v3 20/26] ARM: vITS: handle MOVI command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 21/26] ARM: vITS: handle DISCARD command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 22/26] ARM: vITS: handle INV command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 23/26] ARM: vITS: handle INVALL command Andre Przywara
2017-03-31 18:05 ` [PATCH v3 24/26] ARM: vITS: create and initialize virtual ITSes for Dom0 Andre Przywara
2017-03-31 18:05 ` [PATCH v3 25/26] ARM: vITS: create ITS subnodes for Dom0 DT Andre Przywara
2017-03-31 18:05 ` [PATCH v3 26/26] ARM: vGIC: advertise LPI support Andre Przywara
2017-04-04 17:06   ` Julien Grall
2017-04-01 20:37 ` [PATCH v3 00/26] 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=0d92de72-9f52-39c5-be30-db1289b6c16b@arm.com \
    --to=julien.grall@arm.com \
    --cc=andre.przywara@arm.com \
    --cc=shankerd@codeaurora.org \
    --cc=sstabellini@kernel.org \
    --cc=vijay.kilari@gmail.com \
    --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.